From 95d1268308b97d3b85c1588ccbd84881484462fe Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:02:06 +0200 Subject: [PATCH] Bootstrapping implementation --- .gitignore | 3 - CHANGELOG.md | 9 +- Cargo.lock | 8 + crates/common/Cargo.toml | 2 +- crates/common/src/auth/authentication.rs | 52 +- crates/common/src/cache/invalidate.rs | 18 +- .../common/src/config/mailstore/spamfilter.rs | 2 +- crates/common/src/config/mod.rs | 4 +- crates/common/src/config/server/listener.rs | 65 +- crates/common/src/config/telemetry.rs | 677 +- crates/common/src/enterprise/config.rs | 9 +- crates/common/src/manager/boot.rs | 62 +- crates/common/src/manager/defaults.rs | 80 +- crates/common/src/network/dns/update.rs | 60 + crates/common/src/network/security.rs | 5 + crates/common/src/telemetry/tracers/store.rs | 2 +- crates/dav/src/calendar/freebusy.rs | 2 +- crates/dav/src/calendar/query.rs | 3 +- crates/dav/src/common/lock.rs | 15 +- crates/dav/src/common/propfind.rs | 8 +- crates/dav/src/file/copy_move.rs | 2 +- crates/email/src/message/crypto.rs | 9 +- crates/email/src/message/ingest.rs | 11 +- crates/groupware/src/scheduling/itip.rs | 42 +- crates/http/src/auth/permissions.rs | 8 +- crates/http/src/request.rs | 21 +- crates/imap-proto/src/parser/fetch.rs | 4 +- crates/jmap-proto/src/types/date.rs | 34 +- crates/jmap/Cargo.toml | 1 + crates/jmap/src/calendar/set.rs | 24 +- crates/jmap/src/contact/query.rs | 2 +- crates/jmap/src/registry/get.rs | 14 +- crates/jmap/src/registry/mapping/account.rs | 24 +- crates/jmap/src/registry/mapping/bootstrap.rs | 585 + crates/jmap/src/registry/mapping/mod.rs | 1 + crates/jmap/src/registry/mapping/principal.rs | 33 +- .../src/registry/mapping/queued_message.rs | 7 +- crates/jmap/src/registry/query.rs | 7 + crates/jmap/src/registry/set.rs | 12 + crates/main/Cargo.toml | 3 +- crates/main/src/main.rs | 5 +- crates/migration/src/lib.rs | 8 +- crates/migration/src/v016.rs | 43 +- crates/registry/src/jmap/patch.rs | 2 +- crates/registry/src/schema/enums.rs | 3827 ++ crates/registry/src/schema/enums_impl.rs | 13891 ++++++ crates/registry/src/schema/mod.rs | 1 + crates/registry/src/schema/properties.rs | 1131 + crates/registry/src/schema/properties_impl.rs | 7599 +++ crates/registry/src/schema/structs.rs | 5133 ++ crates/registry/src/schema/structs_impl.rs | 39085 ++++++++++++++++ crates/registry/src/types/datetime.rs | 34 +- crates/registry/src/types/list.rs | 8 +- crates/services/Cargo.toml | 2 +- crates/services/src/broadcast/subscriber.rs | 2 +- crates/services/src/lib.rs | 31 +- crates/services/src/task_manager/imip.rs | 3 +- crates/services/src/task_manager/manager.rs | 2 +- crates/smtp/src/inbound/auth.rs | 16 +- crates/smtp/src/inbound/mail.rs | 10 +- crates/smtp/src/inbound/rcpt.rs | 12 +- crates/smtp/src/inbound/spawn.rs | 2 +- crates/smtp/src/lib.rs | 5 +- crates/smtp/src/queue/manager.rs | 1 + crates/spam-filter/src/analysis/mime.rs | 9 +- crates/spam-filter/src/analysis/replyto.rs | 10 +- crates/spam-filter/src/modules/classifier.rs | 2 +- crates/spam-filter/src/modules/html.rs | 16 +- .../src/backend/composite/sharded_blob.rs | 3 + crates/store/src/backend/ephemeral/blob.rs | 51 + crates/store/src/backend/ephemeral/main.rs | 21 + crates/store/src/backend/ephemeral/mod.rs | 22 + crates/store/src/backend/ephemeral/read.rs | 90 + crates/store/src/backend/ephemeral/write.rs | 197 + crates/store/src/backend/mod.rs | 1 + crates/store/src/backend/redis/mod.rs | 2 +- crates/store/src/build/registry.rs | 26 +- crates/store/src/dispatch/blob.rs | 3 + crates/store/src/dispatch/mod.rs | 1 + crates/store/src/dispatch/search.rs | 2 +- crates/store/src/dispatch/store.rs | 7 + crates/store/src/lib.rs | 16 +- crates/store/src/registry/get.rs | 26 +- crates/store/src/registry/local.rs | 38 +- crates/trc/src/event/enums.rs | 4 +- crates/trc/src/event/enums_impl.rs | 14 + crates/trc/src/ipc/metrics.rs | 8 +- crates/utils/src/glob.rs | 10 +- crates/utils/src/template.rs | 6 +- resources/schema/schema.json.gz | Bin 0 -> 138692 bytes resources/schema/schema.json.sha256 | 1 + tests/Cargo.toml | 2 +- tests/src/imap/mod.rs | 445 +- tests/src/jmap/mod.rs | 347 +- tests/src/jmap/principal/get.rs | 8 +- tests/src/smtp/inbound/throttle.rs | 1 + tests/src/smtp/management/queue.rs | 44 +- tests/src/system/mod.rs | 107 +- tests/src/utils/account.rs | 28 +- tests/src/utils/webdav.rs | 3 +- 100 files changed, 73102 insertions(+), 1252 deletions(-) create mode 100644 crates/jmap/src/registry/mapping/bootstrap.rs create mode 100644 crates/registry/src/schema/enums.rs create mode 100644 crates/registry/src/schema/enums_impl.rs create mode 100644 crates/registry/src/schema/properties.rs create mode 100644 crates/registry/src/schema/properties_impl.rs create mode 100644 crates/registry/src/schema/structs.rs create mode 100644 crates/registry/src/schema/structs_impl.rs create mode 100644 crates/store/src/backend/ephemeral/blob.rs create mode 100644 crates/store/src/backend/ephemeral/main.rs create mode 100644 crates/store/src/backend/ephemeral/mod.rs create mode 100644 crates/store/src/backend/ephemeral/read.rs create mode 100644 crates/store/src/backend/ephemeral/write.rs create mode 100644 resources/schema/schema.json.gz create mode 100644 resources/schema/schema.json.sha256 diff --git a/.gitignore b/.gitignore index c984fe13..fe8547c4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,3 @@ run.sh .ignore .data .DS_Store -crates/registry/src/schema/*s.rs -crates/registry/src/schema/*impl.rs -resources/schema diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b0698f8..7b0318c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,9 +18,12 @@ This version includes **multiple breaking changes**. If you are upgrading from v - Automatic DNS management of `MX`, `TXT`, `CNAME`, `SRV`, `CAA` and `TLSA` records (#463 #1017 #1419 #2438 #1370 #1406 #1371) - Automatic update of `TLSA` records when ACME certificates change (#1664) - RFC2136 `SIG(0)` support (#856) - - BunnyDNS provider support - - Porkbun provider support - - DNSimple provider support + - Route53 provider support (contributed by @jimmystewpot) + - Google Cloud DNS provider support (contributed by @jimmystewpot) + - Bunny provider support (contributed by @angeloanan) + - Porkbun provider support (contributed by @jeffesquivels) + - DNSimple provider support (contributed by @NelsonVides) + - Spaceship provider support (contributed by @matserix) - DKIM: - Automatic DKIM key generation, rotation and DNS management (#368 #961) - Store DKIM keys in the database (#1264) diff --git a/Cargo.lock b/Cargo.lock index bc1f7674..72c356a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1880,9 +1880,15 @@ dependencies = [ [[package]] name = "dns-update" version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccef4d864bf07191beab1ddaced3e108208058ba0350ce535407e2704aafcc18" dependencies = [ "aws-lc-rs", + "base64 0.22.1", + "chrono", + "hex", "hickory-client", + "quick-xml 0.39.2", "reqwest 0.13.2", "rustls 0.23.37", "serde", @@ -5509,6 +5515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", + "serde", ] [[package]] @@ -6088,6 +6095,7 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier 0.6.2", "serde", + "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 67f4c67d..ad20addb 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -20,7 +20,7 @@ mail-parser = { version = "0.11", features = ["full_encoding"] } mail-builder = { version = "0.4" } mail-auth = { version = "0.8" } smtp-proto = { version = "0.2", features = ["rkyv"] } -dns-update = { path = "/Users/me/code/dns-update" } +dns-update = { version = "0.2.0" } calcard = { version = "0.3", features = ["rkyv"] } ahash = { version = "0.8.2", features = ["serde"] } parking_lot = "0.12.1" diff --git a/crates/common/src/auth/authentication.rs b/crates/common/src/auth/authentication.rs index 10c8c2b9..d004da9c 100644 --- a/crates/common/src/auth/authentication.rs +++ b/crates/common/src/auth/authentication.rs @@ -80,7 +80,7 @@ impl Server { secret, mfa_token, } => { - let username = UsernameParts::new(username); + let mut username = UsernameParts::new(username); // Try to authenticate as fallback admin if configured if let Some((fallback_user, fallback_hash)) = &self.registry().recovery_admin() @@ -127,14 +127,18 @@ impl Server { }; } + // Add domain if missing, use the default domain + self.add_missing_domain(&mut username.account); + if let Some(master_user) = &mut username.master_user { + self.add_missing_domain(master_user); + } + // Obtain domain let auth_as = username.auth_as(); let auth_as_address = auth_as.address(); let auth_as_local = auth_as.local(); - let auth_as_domain = auth_as.domain(); - let domain = self - .domain_or_default(auth_as_address, auth_as_domain) - .await?; + let auth_as_domain = auth_as.domain().unwrap(); + let domain = self.resolve_domain(auth_as_domain).await?; // Authenticate app passwords if let Some(app_pass) = AppPassword::parse(secret) { @@ -420,34 +424,26 @@ impl Server { } } - async fn domain_or_default( - &self, - address: &str, - domain_name: Option<&str>, - ) -> trc::Result> { - if let Some(domain_name) = domain_name { - if let Some(domain) = self.domain(domain_name).await? { - Ok(domain) - } else { - Err(trc::AuthEvent::Failed - .into_err() - .ctx(trc::Key::AccountName, address.to_string()) - .reason("Domain not found")) - } + async fn resolve_domain(&self, domain_name: &str) -> trc::Result> { + if let Some(domain) = self.domain(domain_name).await? { + Ok(domain) } else { + Err(trc::AuthEvent::Failed + .into_err() + .ctx(trc::Key::Details, domain_name.to_string()) + .reason("Domain not found")) + } + } + + fn add_missing_domain(&self, address: &mut Username) { + if address.domain().is_none() { trc::event!( Auth(trc::AuthEvent::Warning), - AccountName = address.to_string(), + AccountName = address.address().to_string(), Reason = "No domain in username", ); - self.domain_by_id(self.core.email.default_domain_id) - .await? - .ok_or_else(|| { - trc::AuthEvent::Error - .into_err() - .details("Default domain does not exist or has been disabled") - .ctx(trc::Key::Id, self.core.email.default_domain_id) - }) + address.domain_start = address.name.len() + 1; + address.name = format!("{}@{}", address.name, self.core.email.default_domain_name); } } diff --git a/crates/common/src/cache/invalidate.rs b/crates/common/src/cache/invalidate.rs index 4e980aa3..d60d365a 100644 --- a/crates/common/src/cache/invalidate.rs +++ b/crates/common/src/cache/invalidate.rs @@ -142,24 +142,22 @@ impl CacheInvalidationBuilder { } } - (ObjectInner::Role(current), ObjectInner::Role(new)) => { + (ObjectInner::Role(current), ObjectInner::Role(new)) if (current.enabled_permissions != new.enabled_permissions) || (current.disabled_permissions != new.disabled_permissions) || (current.member_tenant_id != new.member_tenant_id) - || (current.role_ids != new.role_ids) - { - self.invalidate(CacheInvalidation::Role(id)); - } + || (current.role_ids != new.role_ids) => + { + self.invalidate(CacheInvalidation::Role(id)); } - (ObjectInner::MailingList(current), ObjectInner::MailingList(new)) => { + (ObjectInner::MailingList(current), ObjectInner::MailingList(new)) if (current.aliases != new.aliases) || (current.name != new.name) || (current.recipients != new.recipients) - || (current.domain_id != new.domain_id) - { - self.invalidate(CacheInvalidation::List(id)); - } + || (current.domain_id != new.domain_id) => + { + self.invalidate(CacheInvalidation::List(id)); } _ => {} } diff --git a/crates/common/src/config/mailstore/spamfilter.rs b/crates/common/src/config/mailstore/spamfilter.rs index 33ab6e0a..c42f7559 100644 --- a/crates/common/src/config/mailstore/spamfilter.rs +++ b/crates/common/src/config/mailstore/spamfilter.rs @@ -215,7 +215,7 @@ impl SpamFilterRules { rules.push(rule); } } - rules.sort_by(|a, b| a.priority.cmp(&b.priority)); + rules.sort_by_key(|a| a.priority); let mut result = SpamFilterRules::default(); diff --git a/crates/common/src/config/mod.rs b/crates/common/src/config/mod.rs index 9a6fa733..0a3487d1 100644 --- a/crates/common/src/config/mod.rs +++ b/crates/common/src/config/mod.rs @@ -38,7 +38,7 @@ impl Core { #[cfg(feature = "enterprise")] let enterprise = { let enterprise = crate::enterprise::Enterprise::parse(bp).await; - if enterprise.is_none() { + if enterprise.is_none() && !bp.registry.is_recovery_mode() { use registry::schema::prelude::ObjectType; use store::Store; @@ -64,7 +64,7 @@ impl Core { storage.memory = storage.memory.downgrade_store(); } storage.metrics = Store::None; - storage.metrics = Store::None; + storage.tracing = Store::None; storage.directories.clear(); } enterprise diff --git a/crates/common/src/config/server/listener.rs b/crates/common/src/config/server/listener.rs index 0403b214..cc089f88 100644 --- a/crates/common/src/config/server/listener.rs +++ b/crates/common/src/config/server/listener.rs @@ -12,18 +12,23 @@ use crate::{ Inner, network::{TcpAcceptor, tls::CertificateResolver}, }; -use registry::schema::{ - enums::{NetworkListenerProtocol, TlsCipherSuite, TlsVersion}, - structs::{ClusterListenerGroup, NetworkListener, SystemSettings}, +use registry::{ + schema::{ + enums::{NetworkListenerProtocol, TlsCipherSuite, TlsVersion}, + prelude::{ObjectType, SocketAddr}, + structs::{ClusterListenerGroup, NetworkListener, SystemSettings}, + }, + types::{id::ObjectId, map::Map}, }; use rustls::{ ALL_VERSIONS, ServerConfig, SupportedCipherSuite, crypto::aws_lc_rs::{ALL_CIPHER_SUITES, cipher_suite::*, default_provider}, }; -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use store::registry::{RegistryObject, bootstrap::Bootstrap}; use tokio::net::TcpSocket; use tokio_rustls::TlsAcceptor; +use types::id::Id; use utils::snowflake::SnowflakeIdGenerator; impl Listeners { @@ -35,21 +40,47 @@ impl Listeners { }; // Parse servers - let system = bp.setting_infallible::().await; - - for listener in bp.list_infallible::().await { - if bp.role.as_ref().is_none_or(|r| match &r.listeners { - ClusterListenerGroup::EnableAll => true, - ClusterListenerGroup::DisableAll => false, - ClusterListenerGroup::EnableSome(group) => { - group.listener_ids.iter().any(|id| *id == listener.id.id()) + if !bp.registry.is_recovery_mode() { + let system = bp.setting_infallible::().await; + for listener in bp.list_infallible::().await { + if bp.role.as_ref().is_none_or(|r| match &r.listeners { + ClusterListenerGroup::EnableAll => true, + ClusterListenerGroup::DisableAll => false, + ClusterListenerGroup::EnableSome(group) => { + group.listener_ids.iter().any(|id| *id == listener.id.id()) + } + ClusterListenerGroup::DisableSome(group) => { + !group.listener_ids.iter().any(|id| *id == listener.id.id()) + } + }) { + servers.parse_server(bp, listener, &system); } - ClusterListenerGroup::DisableSome(group) => { - !group.listener_ids.iter().any(|id| *id == listener.id.id()) - } - }) { - servers.parse_server(bp, listener, &system); } + } else { + servers.parse_server( + bp, + RegistryObject { + id: ObjectId::new(ObjectType::NetworkListener, Id::singleton()), + object: NetworkListener { + bind: Map::new(vec![ + SocketAddr::from_str(&format!( + "[::]:{}", + std::env::var("STALWART_RECOVERY_MODE_PORT") + .ok() + .and_then(|p| p.parse::().ok()) + .unwrap_or(8080) + )) + .unwrap(), + ]), + name: "http-recovery".to_string(), + protocol: NetworkListenerProtocol::Http, + tls_implicit: false, + ..Default::default() + }, + revision: 0, + }, + &SystemSettings::default(), + ); } servers } diff --git a/crates/common/src/config/telemetry.rs b/crates/common/src/config/telemetry.rs index cbffeeb1..f0b272d4 100644 --- a/crates/common/src/config/telemetry.rs +++ b/crates/common/src/config/telemetry.rs @@ -19,7 +19,7 @@ use registry::schema::{ prelude::ObjectType, structs::{self, EventTracingLevel, MetricsPrometheus, Tracer, WebHook}, }; -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, str::FromStr, sync::Arc, time::Duration}; use store::registry::bootstrap::Bootstrap; use trc::{EventType, Level, MetricType, TelemetryEvent, ipc::subscriber::Interests}; @@ -156,70 +156,48 @@ impl Telemetry { impl Tracers { pub async fn parse(bp: &mut Bootstrap, storage: &Storage) -> Self { - // Parse custom logging levels let mut custom_levels = AHashMap::new(); - for level in bp.list_infallible::().await { - custom_levels.insert(level.object.event, level.object.level.into()); - } - - // Parse tracers let mut tracers: Vec = Vec::new(); let mut global_interests = Interests::default(); - for tracer in bp.list_infallible::().await { - let id = tracer.id; - let tracer = tracer.object; - let level; - let lossy; - let events; - let events_policy; - let enable; + if !bp.registry.is_recovery_mode() { + // Parse custom logging levels + for level in bp.list_infallible::().await { + custom_levels.insert(level.object.event, level.object.level.into()); + } - let typ = match tracer { - Tracer::Log(tracer) if tracer.enable => { - level = Level::from(tracer.level); - lossy = tracer.lossy; - events = tracer.events; - events_policy = tracer.events_policy; - enable = tracer.enable; + // Parse tracers + for tracer in bp.list_infallible::().await { + let id = tracer.id; + let tracer = tracer.object; + let level; + let lossy; + let events; + let events_policy; + let enable; - TelemetrySubscriberType::LogTracer(LogTracer { - path: tracer.path, - prefix: tracer.prefix, - rotate: match tracer.rotate { - LogRotateFrequency::Daily => RotationStrategy::Daily, - LogRotateFrequency::Hourly => RotationStrategy::Hourly, - LogRotateFrequency::Minutely => RotationStrategy::Minutely, - LogRotateFrequency::Never => RotationStrategy::Never, - }, - ansi: tracer.ansi, - multiline: tracer.multiline, - }) - } - Tracer::Stdout(tracer) if tracer.enable => { - level = Level::from(tracer.level); - lossy = tracer.lossy; - events = tracer.events; - events_policy = tracer.events_policy; - enable = tracer.enable; + let typ = match tracer { + Tracer::Log(tracer) if tracer.enable => { + level = Level::from(tracer.level); + lossy = tracer.lossy; + events = tracer.events; + events_policy = tracer.events_policy; + enable = tracer.enable; - if !tracers - .iter() - .any(|t| matches!(t.typ, TelemetrySubscriberType::ConsoleTracer(_))) - { - TelemetrySubscriberType::ConsoleTracer(ConsoleTracer { + TelemetrySubscriberType::LogTracer(LogTracer { + path: tracer.path, + prefix: tracer.prefix, + rotate: match tracer.rotate { + LogRotateFrequency::Daily => RotationStrategy::Daily, + LogRotateFrequency::Hourly => RotationStrategy::Hourly, + LogRotateFrequency::Minutely => RotationStrategy::Minutely, + LogRotateFrequency::Never => RotationStrategy::Never, + }, ansi: tracer.ansi, multiline: tracer.multiline, - buffered: tracer.buffered, }) - } else { - bp.build_error(id, "Only one console tracer is allowed"); - continue; } - } - Tracer::Journal(tracer) if tracer.enable => { - #[cfg(unix)] - { + Tracer::Stdout(tracer) if tracer.enable => { level = Level::from(tracer.level); lossy = tracer.lossy; events = tracer.events; @@ -228,323 +206,348 @@ impl Tracers { if !tracers .iter() - .any(|t| matches!(t.typ, TelemetrySubscriberType::JournalTracer(_))) + .any(|t| matches!(t.typ, TelemetrySubscriberType::ConsoleTracer(_))) { - match crate::telemetry::tracers::journald::Subscriber::new() { - Ok(subscriber) => { - TelemetrySubscriberType::JournalTracer(subscriber) - } - Err(e) => { - bp.build_error( - id, - format!("Failed to create journald subscriber: {e}"), - ); - continue; - } - } + TelemetrySubscriberType::ConsoleTracer(ConsoleTracer { + ansi: tracer.ansi, + multiline: tracer.multiline, + buffered: tracer.buffered, + }) } else { - bp.build_error(id, "Only one journal tracer is allowed"); + bp.build_error(id, "Only one console tracer is allowed"); continue; } } + Tracer::Journal(tracer) if tracer.enable => { + #[cfg(unix)] + { + level = Level::from(tracer.level); + lossy = tracer.lossy; + events = tracer.events; + events_policy = tracer.events_policy; + enable = tracer.enable; - #[cfg(not(unix))] - { - bp.build_error(id, "Journald is only available on Unix systems."); - continue; - } - } - Tracer::OtelHttp(tracer) if tracer.enable => { - level = Level::from(tracer.level); - lossy = tracer.lossy; - events = tracer.events; - events_policy = tracer.events_policy; - enable = tracer.enable; - - let headers = match tracer - .http_auth - .build_headers(tracer.http_headers, None) - .await - { - Ok(headers) => headers - .into_iter() - .filter_map(|(k, v)| { - k.and_then(|k| Some((k.to_string(), v.to_str().ok()?.to_string()))) - }) - .collect::>(), - Err(err) => { - bp.build_error( - id, - format!("Failed to build OpenTelemetry HTTP headers: {err}"), - ); - continue; + if !tracers + .iter() + .any(|t| matches!(t.typ, TelemetrySubscriberType::JournalTracer(_))) + { + match crate::telemetry::tracers::journald::Subscriber::new() { + Ok(subscriber) => { + TelemetrySubscriberType::JournalTracer(subscriber) + } + Err(e) => { + bp.build_error( + id, + format!("Failed to create journald subscriber: {e}"), + ); + continue; + } + } + } else { + bp.build_error(id, "Only one journal tracer is allowed"); + continue; + } } - }; - let mut span_exporter = SpanExporter::builder() - .with_http() - .with_endpoint(tracer.endpoint.clone()) - .with_timeout(tracer.timeout.into_inner()); - let mut log_exporter = LogExporter::builder() - .with_http() - .with_endpoint(tracer.endpoint) - .with_timeout(tracer.timeout.into_inner()); - if !headers.is_empty() { - span_exporter = span_exporter.with_headers(headers.clone()); - log_exporter = log_exporter.with_headers(headers); - } - - match (span_exporter.build(), log_exporter.build()) { - (Ok(span_exporter), Ok(log_exporter)) => { - TelemetrySubscriberType::OtelTracer(OtelTracer { - span_exporter, - log_exporter, - throttle: tracer.throttle.into_inner(), - span_exporter_enable: tracer.enable_span_exporter, - log_exporter_enable: tracer.enable_log_exporter, - }) - } - (Err(err), _) => { - bp.build_error( - id, - format!("Failed to build OpenTelemetry span exporter: {err}"), - ); - continue; - } - (_, Err(err)) => { - bp.build_error( - id, - format!("Failed to build OpenTelemetry log exporter: {err}"), - ); + #[cfg(not(unix))] + { + bp.build_error(id, "Journald is only available on Unix systems."); continue; } } - } - Tracer::OtelGrpc(tracer) if tracer.enable => { - level = Level::from(tracer.level); - lossy = tracer.lossy; - events = tracer.events; - events_policy = tracer.events_policy; - enable = tracer.enable; + Tracer::OtelHttp(tracer) if tracer.enable => { + level = Level::from(tracer.level); + lossy = tracer.lossy; + events = tracer.events; + events_policy = tracer.events_policy; + enable = tracer.enable; - let mut span_exporter = SpanExporter::builder() - .with_tonic() - .with_protocol(opentelemetry_otlp::Protocol::Grpc) - .with_timeout(tracer.timeout.into_inner()); - let mut log_exporter = LogExporter::builder() - .with_tonic() - .with_protocol(opentelemetry_otlp::Protocol::Grpc) - .with_timeout(tracer.timeout.into_inner()); - if let Some(endpoint) = tracer.endpoint { - span_exporter = span_exporter.with_endpoint(endpoint.clone()); - log_exporter = log_exporter.with_endpoint(endpoint); - } + let headers = match tracer + .http_auth + .build_headers(tracer.http_headers, None) + .await + { + Ok(headers) => headers + .into_iter() + .filter_map(|(k, v)| { + k.and_then(|k| { + Some((k.to_string(), v.to_str().ok()?.to_string())) + }) + }) + .collect::>(), + Err(err) => { + bp.build_error( + id, + format!("Failed to build OpenTelemetry HTTP headers: {err}"), + ); + continue; + } + }; - match (span_exporter.build(), log_exporter.build()) { - (Ok(span_exporter), Ok(log_exporter)) => { - TelemetrySubscriberType::OtelTracer(OtelTracer { - span_exporter, - log_exporter, - throttle: tracer.throttle.into_inner(), - span_exporter_enable: tracer.enable_span_exporter, - log_exporter_enable: tracer.enable_log_exporter, - }) + let mut span_exporter = SpanExporter::builder() + .with_http() + .with_endpoint(tracer.endpoint.clone()) + .with_timeout(tracer.timeout.into_inner()); + let mut log_exporter = LogExporter::builder() + .with_http() + .with_endpoint(tracer.endpoint) + .with_timeout(tracer.timeout.into_inner()); + if !headers.is_empty() { + span_exporter = span_exporter.with_headers(headers.clone()); + log_exporter = log_exporter.with_headers(headers); } - (Err(err), _) => { - bp.build_error( - id, - format!("Failed to build OpenTelemetry span exporter: {err}"), - ); - continue; - } - (_, Err(err)) => { - bp.build_error( - id, - format!("Failed to build OpenTelemetry log exporter: {err}"), - ); - continue; + + match (span_exporter.build(), log_exporter.build()) { + (Ok(span_exporter), Ok(log_exporter)) => { + TelemetrySubscriberType::OtelTracer(OtelTracer { + span_exporter, + log_exporter, + throttle: tracer.throttle.into_inner(), + span_exporter_enable: tracer.enable_span_exporter, + log_exporter_enable: tracer.enable_log_exporter, + }) + } + (Err(err), _) => { + bp.build_error( + id, + format!("Failed to build OpenTelemetry span exporter: {err}"), + ); + continue; + } + (_, Err(err)) => { + bp.build_error( + id, + format!("Failed to build OpenTelemetry log exporter: {err}"), + ); + continue; + } } } - } - _ => continue, - }; + Tracer::OtelGrpc(tracer) if tracer.enable => { + level = Level::from(tracer.level); + lossy = tracer.lossy; + events = tracer.events; + events_policy = tracer.events_policy; + enable = tracer.enable; - if !enable { - continue; - } + let mut span_exporter = SpanExporter::builder() + .with_tonic() + .with_protocol(opentelemetry_otlp::Protocol::Grpc) + .with_timeout(tracer.timeout.into_inner()); + let mut log_exporter = LogExporter::builder() + .with_tonic() + .with_protocol(opentelemetry_otlp::Protocol::Grpc) + .with_timeout(tracer.timeout.into_inner()); + if let Some(endpoint) = tracer.endpoint { + span_exporter = span_exporter.with_endpoint(endpoint.clone()); + log_exporter = log_exporter.with_endpoint(endpoint); + } - // Create tracer - let mut tracer = TelemetrySubscriber { - id: format!("t_{}", id.id()), - interests: Default::default(), - lossy, - typ, - }; - - // Parse disabled events - let exclude_event = match &tracer.typ { - TelemetrySubscriberType::ConsoleTracer(_) => None, - TelemetrySubscriberType::LogTracer(_) => { - EventType::Telemetry(TelemetryEvent::LogError).into() - } - TelemetrySubscriberType::OtelTracer(_) => { - EventType::Telemetry(TelemetryEvent::OtelExporterError).into() - } - TelemetrySubscriberType::Webhook(_) => { - EventType::Telemetry(TelemetryEvent::WebhookError).into() - } - #[cfg(unix)] - TelemetrySubscriberType::JournalTracer(_) => { - EventType::Telemetry(TelemetryEvent::JournalError).into() - } - // SPDX-SnippetBegin - // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC - // SPDX-License-Identifier: LicenseRef-SEL - #[cfg(feature = "enterprise")] - TelemetrySubscriberType::StoreTracer(_) => None, - // SPDX-SnippetEnd - }; - - // Parse disabled events - apply_events(events, events_policy, |event_type| { - if exclude_event != Some(event_type) { - let event_level = custom_levels - .get(&event_type) - .copied() - .unwrap_or(event_type.level()); - if level.is_contained(event_level) { - tracer.interests.set(event_type); - global_interests.set(event_type); + match (span_exporter.build(), log_exporter.build()) { + (Ok(span_exporter), Ok(log_exporter)) => { + TelemetrySubscriberType::OtelTracer(OtelTracer { + span_exporter, + log_exporter, + throttle: tracer.throttle.into_inner(), + span_exporter_enable: tracer.enable_span_exporter, + log_exporter_enable: tracer.enable_log_exporter, + }) + } + (Err(err), _) => { + bp.build_error( + id, + format!("Failed to build OpenTelemetry span exporter: {err}"), + ); + continue; + } + (_, Err(err)) => { + bp.build_error( + id, + format!("Failed to build OpenTelemetry log exporter: {err}"), + ); + continue; + } + } } - } - }); + _ => continue, + }; - if !tracer.interests.is_empty() { - tracers.push(tracer); - } else { - bp.build_warning(id, "No events enabled for tracer"); - } - } - - // SPDX-SnippetBegin - // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC - // SPDX-License-Identifier: LicenseRef-SEL - - // Parse tracing history - #[cfg(feature = "enterprise")] - if storage.tracing.is_active() { - let mut tracer = TelemetrySubscriber { - id: "history".to_string(), - interests: Default::default(), - lossy: false, - typ: TelemetrySubscriberType::StoreTracer(StoreTracer { - store: storage.tracing.clone(), - }), - }; - - for event_type in StoreTracer::default_events() { - tracer.interests.set(event_type); - global_interests.set(event_type); - } - - tracers.push(tracer); - } - // SPDX-SnippetEnd - - // Parse webhooks - for hook in bp.list_infallible::().await { - let id = hook.id; - let hook = hook.object; - - if !hook.enable { - continue; - } - - let headers = match hook - .http_auth - .build_headers(hook.http_headers, "application/json".into()) - .await - { - Ok(headers) => headers, - Err(err) => { - bp.build_error(id, format!("Unable to build HTTP headers: {}", err)); + if !enable { continue; } - }; - // Build tracer - let mut tracer = TelemetrySubscriber { - id: format!("w_{}", id.id()), - interests: Default::default(), - lossy: hook.lossy, - typ: TelemetrySubscriberType::Webhook(WebhookTracer { - url: hook.url, - timeout: hook.timeout.into_inner(), - tls_allow_invalid_certs: hook.allow_invalid_certs, - headers, - key: hook - .signature_key - .secret() - .await - .map_err(|err| { - bp.build_error( - id, - format!("Unable to retrieve signature key: {}", err), - ); - }) - .unwrap_or_default() - .unwrap_or_default() - .into_owned(), - throttle: hook.throttle.into_inner(), - discard_after: hook.discard_after.into_inner(), - }), - }; + // Create tracer + let mut tracer = TelemetrySubscriber { + id: format!("t_{}", id.id()), + interests: Default::default(), + lossy, + typ, + }; - // Parse webhook events - apply_events(hook.events, hook.events_policy, |event_type| { - if event_type != EventType::Telemetry(TelemetryEvent::WebhookError) { + // Parse disabled events + let exclude_event = match &tracer.typ { + TelemetrySubscriberType::ConsoleTracer(_) => None, + TelemetrySubscriberType::LogTracer(_) => { + EventType::Telemetry(TelemetryEvent::LogError).into() + } + TelemetrySubscriberType::OtelTracer(_) => { + EventType::Telemetry(TelemetryEvent::OtelExporterError).into() + } + TelemetrySubscriberType::Webhook(_) => { + EventType::Telemetry(TelemetryEvent::WebhookError).into() + } + #[cfg(unix)] + TelemetrySubscriberType::JournalTracer(_) => { + EventType::Telemetry(TelemetryEvent::JournalError).into() + } + // SPDX-SnippetBegin + // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + // SPDX-License-Identifier: LicenseRef-SEL + #[cfg(feature = "enterprise")] + TelemetrySubscriberType::StoreTracer(_) => None, + // SPDX-SnippetEnd + }; + + // Parse disabled events + apply_events(events, events_policy, |event_type| { + if exclude_event != Some(event_type) { + let event_level = custom_levels + .get(&event_type) + .copied() + .unwrap_or(event_type.level()); + if level.is_contained(event_level) { + tracer.interests.set(event_type); + global_interests.set(event_type); + } + } + }); + + if !tracer.interests.is_empty() { + tracers.push(tracer); + } else { + bp.build_warning(id, "No events enabled for tracer"); + } + } + + // SPDX-SnippetBegin + // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + // SPDX-License-Identifier: LicenseRef-SEL + + // Parse tracing history + #[cfg(feature = "enterprise")] + if storage.tracing.is_active() { + let mut tracer = TelemetrySubscriber { + id: "history".to_string(), + interests: Default::default(), + lossy: false, + typ: TelemetrySubscriberType::StoreTracer(StoreTracer { + store: storage.tracing.clone(), + }), + }; + + for event_type in StoreTracer::default_events() { tracer.interests.set(event_type); global_interests.set(event_type); } - }); - if !tracer.interests.is_empty() { tracers.push(tracer); - } else { - bp.build_error(id, "No events enabled for webhook"); } - } + // SPDX-SnippetEnd - // Add default tracer if none were found - #[cfg(not(feature = "test_mode"))] - if tracers.is_empty() { - for event_type in EventType::variants() { - let event_level = custom_levels - .get(event_type) - .copied() - .unwrap_or(event_type.level()); - if Level::Info.is_contained(event_level) { - global_interests.set(event_type.to_id() as usize); + // Parse webhooks + for hook in bp.list_infallible::().await { + let id = hook.id; + let hook = hook.object; + + if !hook.enable { + continue; + } + + let headers = match hook + .http_auth + .build_headers(hook.http_headers, "application/json".into()) + .await + { + Ok(headers) => headers, + Err(err) => { + bp.build_error(id, format!("Unable to build HTTP headers: {}", err)); + continue; + } + }; + + // Build tracer + let mut tracer = TelemetrySubscriber { + id: format!("w_{}", id.id()), + interests: Default::default(), + lossy: hook.lossy, + typ: TelemetrySubscriberType::Webhook(WebhookTracer { + url: hook.url, + timeout: hook.timeout.into_inner(), + tls_allow_invalid_certs: hook.allow_invalid_certs, + headers, + key: hook + .signature_key + .secret() + .await + .map_err(|err| { + bp.build_error( + id, + format!("Unable to retrieve signature key: {}", err), + ); + }) + .unwrap_or_default() + .unwrap_or_default() + .into_owned(), + throttle: hook.throttle.into_inner(), + discard_after: hook.discard_after.into_inner(), + }), + }; + + // Parse webhook events + apply_events(hook.events, hook.events_policy, |event_type| { + if event_type != EventType::Telemetry(TelemetryEvent::WebhookError) { + tracer.interests.set(event_type); + global_interests.set(event_type); + } + }); + + if !tracer.interests.is_empty() { + tracers.push(tracer); + } else { + bp.build_error(id, "No events enabled for webhook"); } } - tracers.push(TelemetrySubscriber { - id: "default".to_string(), - interests: global_interests.clone(), - typ: TelemetrySubscriberType::ConsoleTracer(ConsoleTracer { - ansi: true, - multiline: false, - buffered: true, - }), - lossy: false, - }); - } + #[cfg(feature = "dev_mode")] + if let Ok(level) = std::env::var("LOG") { + let level = Level::from_str(&level).expect("Invalid LOG level"); + for event_type in EventType::variants() { + let event_level = custom_levels + .get(event_type) + .copied() + .unwrap_or(event_type.level()); + if level.is_contained(event_level) { + global_interests.set(event_type.to_id() as usize); + } + } - #[cfg(feature = "dev_mode")] - if let Ok(level) = std::env::var("LOG") { - use std::str::FromStr; - - let level = Level::from_str(&level).expect("Invalid LOG level"); + tracers.push(TelemetrySubscriber { + id: "default".to_string(), + interests: global_interests.clone(), + typ: TelemetrySubscriberType::ConsoleTracer(ConsoleTracer { + ansi: true, + multiline: false, + buffered: true, + }), + lossy: false, + }); + } + } else { + // Add default tracer if none were found + let level = std::env::var("STALWART_RECOVERY_MODE_LOG_LEVEL") + .ok() + .and_then(|level| Level::from_str(&level).ok()) + .unwrap_or(Level::Info); for event_type in EventType::variants() { let event_level = custom_levels .get(event_type) @@ -556,7 +559,7 @@ impl Tracers { } tracers.push(TelemetrySubscriber { - id: "default".to_string(), + id: "recover-log".to_string(), interests: global_interests.clone(), typ: TelemetrySubscriberType::ConsoleTracer(ConsoleTracer { ansi: true, diff --git a/crates/common/src/enterprise/config.rs b/crates/common/src/enterprise/config.rs index 15ba74ca..83ed7d36 100644 --- a/crates/common/src/enterprise/config.rs +++ b/crates/common/src/enterprise/config.rs @@ -48,7 +48,7 @@ impl Enterprise { // violators to the fullest extent of the law, including but not limited to claims // for copyright infringement, breach of contract, and fraud. - /*let license_result = match ( + let license_result = match ( enterprise.license_key.secret().await, enterprise.api_key.secret().await, ) { @@ -112,13 +112,6 @@ impl Enterprise { bp.build_warning(ObjectType::Enterprise.singleton(), err.to_string()); return None; } - };*/ - - let license = LicenseKey { - valid_to: store::write::now() + (86400 * 365), - valid_from: store::write::now() - 3600, - domain: "example.org".to_string(), - accounts: 99999, }; // Update the license if a new one was obtained diff --git a/crates/common/src/manager/boot.rs b/crates/common/src/manager/boot.rs index b86bce15..a21b48f4 100644 --- a/crates/common/src/manager/boot.rs +++ b/crates/common/src/manager/boot.rs @@ -137,12 +137,8 @@ impl BootManager { .failed("⚠️ Startup failed"); let mut bootstrap = Bootstrap::new(registry).await; - if matches!(import_export, StoreOp::None) { - // Add safe defaults if missing - bootstrap.insert_safe_defaults().await; - } - - let todo = "implement recovery mode, check env_recovery_mode in RegistryStoreInner"; + // Add safe defaults if missing + bootstrap.insert_safe_defaults().await; // Start listeners let mut servers = Listeners::parse(&mut bootstrap).await; @@ -173,11 +169,27 @@ impl BootManager { #[cfg(not(feature = "enterprise"))] telemetry.enable(false); - trc::event!( - Server(trc::ServerEvent::Startup), - Hostname = bootstrap.registry.local_hostname().to_string(), - Version = env!("CARGO_PKG_VERSION"), - ); + if bootstrap.registry.is_bootstrap_mode() { + trc::event!( + Server(trc::ServerEvent::BootstrapMode), + Details = + "No configuration file was found. Port 8080 is open for initial setup.", + Version = env!("CARGO_PKG_VERSION"), + ); + } else if bootstrap.registry.is_recovery_mode() { + trc::event!( + Server(trc::ServerEvent::RecoveryMode), + Details = "Port 8080 is open for troubleshooting and recovery.", + Hostname = bootstrap.registry.local_hostname().to_string(), + Version = env!("CARGO_PKG_VERSION"), + ); + } else { + trc::event!( + Server(trc::ServerEvent::Startup), + Hostname = bootstrap.registry.local_hostname().to_string(), + Version = env!("CARGO_PKG_VERSION"), + ); + } if core.storage.coordinator.is_enabled() { trc::event!( @@ -205,20 +217,22 @@ impl BootManager { cache, }); - // Load spam model - if let Err(err) = inner.build_server().spam_model_reload().await { - trc::error!( - err.details("Failed to load spam filter model") - .caused_by(trc::location!()) - ); - } + if !bootstrap.registry.is_recovery_mode() { + // Load spam model + if let Err(err) = inner.build_server().spam_model_reload().await { + trc::error!( + err.details("Failed to load spam filter model") + .caused_by(trc::location!()) + ); + } - // Fetch ASN database - if has_remote_asn { - inner - .build_server() - .lookup_asn_country(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))) - .await; + // Fetch ASN database + if has_remote_asn { + inner + .build_server() + .lookup_asn_country(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))) + .await; + } } // Parse TCP acceptors diff --git a/crates/common/src/manager/defaults.rs b/crates/common/src/manager/defaults.rs index 1c7d8630..3b44b212 100644 --- a/crates/common/src/manager/defaults.rs +++ b/crates/common/src/manager/defaults.rs @@ -47,6 +47,49 @@ impl BootstrapDefaults for Bootstrap { } async fn insert_safe_defaults(bp: &mut Bootstrap) -> trc::Result<()> { + if bp.registry.is_recovery_mode() { + return Ok(()); + } + + #[cfg(not(feature = "test_mode"))] + if bp.registry.count_object(ObjectType::Application).await? == 0 { + bp.registry + .write(RegistryWrite::insert( + &Application { + auto_update_frequency: Duration::from_millis(30 * 24 * 60 * 60 * 1000), + description: "Stalwart Web Interface".to_string(), + enabled: true, + #[cfg(not(feature = "dev_mode"))] + resource_url: + "https://github.com/stalwartlabs/webui/releases/latest/download/webui.zip" + .into(), + #[cfg(feature = "dev_mode")] + resource_url: "file:///Users/me/code/webui/.ignore/webui.zip".into(), + unpack_directory: None, + url_prefix: Map::new(vec!["/admin".into(), "/account".into()]), + } + .into(), + )) + .await?; + } + + if bp.registry.is_bootstrap_mode() { + #[cfg(not(any(feature = "dev_mode", feature = "test_mode")))] + if bp.registry.count_object(ObjectType::SystemSettings).await? == 0 { + bp.registry + .write(RegistryWrite::insert( + &SystemSettings { + default_hostname: bp.registry.local_hostname().to_string(), + ..Default::default() + } + .into(), + )) + .await?; + } + + return Ok(()); + } + if bp.registry.count_object(ObjectType::MtaQueueQuota).await? == 0 { bp.registry .write(RegistryWrite::insert( @@ -380,19 +423,6 @@ async fn insert_safe_defaults(bp: &mut Bootstrap) -> trc::Result<()> { } } - #[cfg(not(any(feature = "dev_mode", feature = "test_mode")))] - if bp.registry.count_object(ObjectType::SystemSettings).await? == 0 { - bp.registry - .write(RegistryWrite::insert( - &SystemSettings { - default_hostname: bp.registry.local_hostname().to_string(), - ..Default::default() - } - .into(), - )) - .await?; - } - if bp .registry .count_object(ObjectType::NetworkListener) @@ -443,12 +473,14 @@ async fn insert_safe_defaults(bp: &mut Bootstrap) -> trc::Result<()> { .await?; } + #[cfg(not(feature = "test_mode"))] if bp.registry.count_object(ObjectType::TracingStore).await? == 0 { bp.registry .write(RegistryWrite::insert(&TracingStore::Default.into())) .await?; } + #[cfg(not(feature = "test_mode"))] if bp.registry.count_object(ObjectType::MetricsStore).await? == 0 { bp.registry .write(RegistryWrite::insert(&MetricsStore::Default.into())) @@ -471,28 +503,6 @@ async fn insert_safe_defaults(bp: &mut Bootstrap) -> trc::Result<()> { .await?; } - #[cfg(not(feature = "test_mode"))] - if bp.registry.count_object(ObjectType::Application).await? == 0 { - bp.registry - .write(RegistryWrite::insert( - &Application { - auto_update_frequency: Duration::from_millis(30 * 24 * 60 * 60 * 1000), - description: "Stalwart Web Interface".to_string(), - enabled: true, - #[cfg(not(feature = "dev_mode"))] - resource_url: - "https://github.com/stalwartlabs/webui/releases/latest/download/webui.zip" - .into(), - #[cfg(feature = "dev_mode")] - resource_url: "file:///Users/me/code/webui/.ignore/webui.zip".into(), - unpack_directory: None, - url_prefix: Map::new(vec!["/admin".into(), "/account".into()]), - } - .into(), - )) - .await?; - } - #[cfg(not(feature = "test_mode"))] { use store::write::BatchBuilder; diff --git a/crates/common/src/network/dns/update.rs b/crates/common/src/network/dns/update.rs index 35339fc2..abad6f1a 100644 --- a/crates/common/src/network/dns/update.rs +++ b/crates/common/src/network/dns/update.rs @@ -252,6 +252,66 @@ impl DnsUpdater { ) .map_err(|err| format!("Failed to build DNS updater: {}", err))?, }), + DnsServer::Spaceship(server) => Ok(DnsUpdater { + polling_interval: server.polling_interval.into_inner(), + propagation_timeout: server.propagation_timeout.into_inner(), + propagation_delay: server.propagation_delay.map(|d| d.into_inner()), + ttl: server.ttl.into_inner(), + core, + updater: dns_update::DnsUpdater::new_spaceship( + server.api_key.as_str(), + server.secret.secret().await?, + server.timeout.into_inner().into(), + ) + .map_err(|err| format!("Failed to build DNS updater: {}", err))?, + }), + DnsServer::Route53(server) => { + let secret_access_key = + server.secret_access_key.secret().await?.into_owned(); + let session_token = server + .session_token + .secret() + .await? + .map(|c| c.into_owned()); + let config = dns_update::providers::route53::Route53Config { + access_key_id: server.access_key_id, + secret_access_key, + session_token, + region: Some(server.region), + hosted_zone_id: server.hosted_zone_id, + private_zone_only: Some(server.private_zone_only), + }; + Ok(DnsUpdater { + polling_interval: server.polling_interval.into_inner(), + propagation_timeout: server.propagation_timeout.into_inner(), + propagation_delay: server.propagation_delay.map(|d| d.into_inner()), + ttl: server.ttl.into_inner(), + core, + updater: dns_update::DnsUpdater::new_route53(config) + .map_err(|err| format!("Failed to build DNS updater: {}", err))?, + }) + } + DnsServer::GoogleCloudDns(server) => { + let service_account_json = + server.service_account_json.secret().await?.into_owned(); + let config = dns_update::providers::google_cloud_dns::GoogleCloudDnsConfig { + service_account_json, + project_id: server.project_id, + managed_zone: server.managed_zone, + private_zone: server.private_zone, + impersonate_service_account: server.impersonate_service_account, + request_timeout: Some(server.timeout.into_inner()), + }; + Ok(DnsUpdater { + polling_interval: server.polling_interval.into_inner(), + propagation_timeout: server.propagation_timeout.into_inner(), + propagation_delay: server.propagation_delay.map(|d| d.into_inner()), + ttl: server.ttl.into_inner(), + core, + updater: dns_update::DnsUpdater::new_google_cloud_dns(config) + .map_err(|err| format!("Failed to build DNS updater: {}", err))?, + }) + } } } diff --git a/crates/common/src/network/security.rs b/crates/common/src/network/security.rs index 19589462..38a09643 100644 --- a/crates/common/src/network/security.rs +++ b/crates/common/src/network/security.rs @@ -404,6 +404,11 @@ impl Server { impl BlockedIps { pub async fn parse(bp: &mut Bootstrap) -> Self { let mut ips = Self::default(); + + if bp.registry.is_recovery_mode() { + return ips; + } + let mut expired_blocks = Vec::new(); let now = now() as i64; diff --git a/crates/common/src/telemetry/tracers/store.rs b/crates/common/src/telemetry/tracers/store.rs index c2cccb39..9d4a9653 100644 --- a/crates/common/src/telemetry/tracers/store.rs +++ b/crates/common/src/telemetry/tracers/store.rs @@ -62,7 +62,7 @@ pub(crate) fn spawn_store_tracer(builder: SubscriberBuilder, settings: StoreTrac [span.as_ref()] .into_iter() .chain(events.iter().map(|event| event.as_ref())) - .chain([event.as_ref()].into_iter()), + .chain([event.as_ref()]), events.len() + 2, ) .to_pickled_vec(), diff --git a/crates/dav/src/calendar/freebusy.rs b/crates/dav/src/calendar/freebusy.rs index 5ffa742a..051bd02e 100644 --- a/crates/dav/src/calendar/freebusy.rs +++ b/crates/dav/src/calendar/freebusy.rs @@ -312,7 +312,7 @@ impl CalendarFreebusyRequestHandler for Server { fn merge_intervals(mut intervals: Vec<(i64, i64)>) -> Vec { if intervals.len() > 1 { - intervals.sort_unstable_by(|a, b| a.0.cmp(&b.0)); + intervals.sort_unstable_by_key(|a| a.0); let mut unique_intervals = Vec::new(); let mut start_time = intervals[0].0; diff --git a/crates/dav/src/calendar/query.rs b/crates/dav/src/calendar/query.rs index 76e8a7c4..dbe05be7 100644 --- a/crates/dav/src/calendar/query.rs +++ b/crates/dav/src/calendar/query.rs @@ -428,8 +428,7 @@ impl CalendarQueryHandler { Vec::with_capacity(4); if data.expand.is_some() { - self.expanded_times - .sort_unstable_by(|a, b| a.start.cmp(&b.start)); + self.expanded_times.sort_unstable_by_key(|a| a.start); } loop { diff --git a/crates/dav/src/common/lock.rs b/crates/dav/src/common/lock.rs index fb9916d8..ca9f89a3 100644 --- a/crates/dav/src/common/lock.rs +++ b/crates/dav/src/common/lock.rs @@ -346,24 +346,21 @@ impl LockRequestHandler for Server { ) -> crate::Result<()> { let no_if_headers = headers.if_.is_empty(); match method { - DavMethod::GET | DavMethod::HEAD => { + DavMethod::GET | DavMethod::HEAD if no_if_headers => { // Return early for GET/HEAD requests without If headers - if no_if_headers { - return Ok(()); - } + return Ok(()); } DavMethod::COPY | DavMethod::MOVE | DavMethod::POST | DavMethod::PUT - | DavMethod::PATCH => { + | DavMethod::PATCH if headers.overwrite_fail && resources.last().is_some_and(|r| { r.etag.is_some() || r.document_id.is_some_and(|id| id != u32::MAX) - }) - { - return Err(DavError::Code(StatusCode::PRECONDITION_FAILED)); - } + }) => + { + return Err(DavError::Code(StatusCode::PRECONDITION_FAILED)); } _ => {} } diff --git a/crates/dav/src/common/propfind.rs b/crates/dav/src/common/propfind.rs index a1be5c97..3a66803b 100644 --- a/crates/dav/src/common/propfind.rs +++ b/crates/dav/src/common/propfind.rs @@ -454,10 +454,10 @@ impl PropFindRequestHandler for Server { let mut calendar_filter = None; if let Some(query_filter) = &query_filter { match (query_filter, &archive) { - (DavQueryFilter::Addressbook(filter), ArchivedResource::ContactCard(card)) => { - if !vcard_query(&card.inner.card, filter) { - continue; - } + (DavQueryFilter::Addressbook(filter), ArchivedResource::ContactCard(card)) + if !vcard_query(&card.inner.card, filter) => + { + continue; } ( DavQueryFilter::Calendar { diff --git a/crates/dav/src/file/copy_move.rs b/crates/dav/src/file/copy_move.rs index 78f4a41f..c1894a51 100644 --- a/crates/dav/src/file/copy_move.rs +++ b/crates/dav/src/file/copy_move.rs @@ -469,7 +469,7 @@ async fn copy_container( } else { Vec::new() }; - copy_files.sort_unstable_by(|a, b| a.1.cmp(&b.1)); + copy_files.sort_unstable_by_key(|a| a.1); let now = now() as i64; let mut next_document_id = server .store() diff --git a/crates/email/src/message/crypto.rs b/crates/email/src/message/crypto.rs index 64721889..bb55e6fc 100644 --- a/crates/email/src/message/crypto.rs +++ b/crates/email/src/message/crypto.rs @@ -345,10 +345,11 @@ impl EncryptMessage for Message<'_> { } match text_part { - Some(text) if self.parts.len() == 1 || is_multipart => { - if text.trim_start().starts_with("-----BEGIN PGP MESSAGE-----") { - return true; - } + Some(text) + if (self.parts.len() == 1 || is_multipart) + && text.trim_start().starts_with("-----BEGIN PGP MESSAGE-----") => + { + return true; } _ => (), } diff --git a/crates/email/src/message/ingest.rs b/crates/email/src/message/ingest.rs index ee4b549a..5a840d98 100644 --- a/crates/email/src/message/ingest.rs +++ b/crates/email/src/message/ingest.rs @@ -785,12 +785,11 @@ impl EmailIngest for Server { let document_id = key.deserialize_be_u32(document_id_pos)?; let thread_id = value.deserialize_be_u32(0)?; - if message_ids.len() == 1 - || (message_ids.len() == references.len() / CheekyHash::HASH_SIZE - && references - .chunks_exact(CheekyHash::HASH_SIZE) - .zip(message_ids.iter()) - .all(|(a, b)| a == b.as_raw_bytes())) + if message_ids.len() == references.len() / CheekyHash::HASH_SIZE + && references + .chunks_exact(CheekyHash::HASH_SIZE) + .zip(message_ids.iter()) + .all(|(a, b)| a == b.as_raw_bytes()) { result.duplicate_ids.push(document_id); } diff --git a/crates/groupware/src/scheduling/itip.rs b/crates/groupware/src/scheduling/itip.rs index 5c2626cb..ea7cae65 100644 --- a/crates/groupware/src/scheduling/itip.rs +++ b/crates/groupware/src/scheduling/itip.rs @@ -115,28 +115,26 @@ pub(crate) fn itip_export_component( ( ICalendarProperty::Organizer | ICalendarProperty::Attendee, ItipExportAs::Attendee(attendee_entry_ids), - ) => { - if attendee_entry_ids.contains(&(entry_id as u16)) - || entry.name == ICalendarProperty::Organizer - { - comp.entries.push(ICalendarEntry { - name: entry.name.clone(), - params: entry - .params - .iter() - .filter(|param| { - !matches!( - ¶m.name, - ICalendarParameterName::ScheduleStatus - | ICalendarParameterName::ScheduleAgent - | ICalendarParameterName::ScheduleForceSend - ) - }) - .cloned() - .collect(), - values: entry.values.clone(), - }); - } + ) if attendee_entry_ids.contains(&(entry_id as u16)) + || entry.name == ICalendarProperty::Organizer => + { + comp.entries.push(ICalendarEntry { + name: entry.name.clone(), + params: entry + .params + .iter() + .filter(|param| { + !matches!( + ¶m.name, + ICalendarParameterName::ScheduleStatus + | ICalendarParameterName::ScheduleAgent + | ICalendarParameterName::ScheduleForceSend + ) + }) + .cloned() + .collect(), + values: entry.values.clone(), + }); } ( ICalendarProperty::RequestStatus diff --git a/crates/http/src/auth/permissions.rs b/crates/http/src/auth/permissions.rs index bfc065f9..f3beb5e1 100644 --- a/crates/http/src/auth/permissions.rs +++ b/crates/http/src/auth/permissions.rs @@ -58,7 +58,9 @@ impl AccountApiHandler for Server { false }; let is_recovery_admin = access_token.account_id() == RECOVERY_ADMIN_ID; - let permissions = if let Some(scope) = access_token.access_scope() { + let permissions = if !self.registry().is_bootstrap_mode() + && let Some(scope) = access_token.access_scope() + { let mut permissions = scope.permissions.clone(); for p in [ @@ -79,6 +81,8 @@ impl AccountApiHandler for Server { Permission::SysClusterNodeCreate, Permission::SysClusterNodeUpdate, Permission::SysClusterNodeDestroy, + Permission::SysBootstrapGet, + Permission::SysBootstrapUpdate, ] { permissions.clear(p.to_id() as usize); } @@ -108,6 +112,8 @@ impl AccountApiHandler for Server { } permissions.build_permissions_list() + } else if self.registry().is_bootstrap_mode() { + vec![Permission::SysBootstrapGet, Permission::SysBootstrapUpdate] } else { Vec::new() }; diff --git a/crates/http/src/request.rs b/crates/http/src/request.rs index 4215eb9a..a7fb983f 100644 --- a/crates/http/src/request.rs +++ b/crates/http/src/request.rs @@ -325,19 +325,18 @@ impl ParseHttp for Server { .await .map(|resource| resource.into_http_response()); } - ("autoconfig", &Method::GET) => { + ("autoconfig", &Method::GET) if path.next().unwrap_or_default() == "mail" - && path.next().unwrap_or_default() == "config-v1.1.xml" - { - // Limit anonymous requests - self.is_http_anonymous_request_allowed(session.remote_ip) - .await?; + && path.next().unwrap_or_default() == "config-v1.1.xml" => + { + // Limit anonymous requests + self.is_http_anonymous_request_allowed(session.remote_ip) + .await?; - return self - .handle_autoconfig_request(req.uri().query()) - .await - .map(|resource| resource.into_http_response()); - } + return self + .handle_autoconfig_request(req.uri().query()) + .await + .map(|resource| resource.into_http_response()); } (_, &Method::OPTIONS) => { return Ok(JsonProblemResponse(StatusCode::NO_CONTENT).into_http_response()); diff --git a/crates/imap-proto/src/parser/fetch.rs b/crates/imap-proto/src/parser/fetch.rs index 1d40f96a..e10e7a85 100644 --- a/crates/imap-proto/src/parser/fetch.rs +++ b/crates/imap-proto/src/parser/fetch.rs @@ -313,10 +313,8 @@ impl Request { while let Some(token) = tokens.next() { match token { Token::ParenthesisClose => break, - Token::Argument(value) => { - if value.eq_ignore_ascii_case(b"LAZY") { + Token::Argument(value) if value.eq_ignore_ascii_case(b"LAZY") => { is_lazy = true; - } } _ => (), } diff --git a/crates/jmap-proto/src/types/date.rs b/crates/jmap-proto/src/types/date.rs index fdd0bc2c..b75cb5f9 100644 --- a/crates/jmap-proto/src/types/date.rs +++ b/crates/jmap-proto/src/types/date.rs @@ -65,34 +65,18 @@ impl FromStr for UTCDate { break; } } - b'T' => { - if pos == 2 { - pos += 1; - } else { - break; - } + b'T' if pos == 2 => { + pos += 1; } - b':' => { - if [3, 4, 6].contains(&pos) { - pos += 1; - } else { - break; - } + b':' if [3, 4, 6].contains(&pos) => { + pos += 1; } - b'+' => { - if pos == 5 { - pos += 1; - skip_digits = false; - } else { - break; - } + b'+' if pos == 5 => { + pos += 1; + skip_digits = false; } - b'.' => { - if pos == 5 { - skip_digits = true; - } else { - break; - } + b'.' if pos == 5 => { + skip_digits = true; } b'Z' | b'z' => (), _ => { diff --git a/crates/jmap/Cargo.toml b/crates/jmap/Cargo.toml index 0f9593e0..a290d485 100644 --- a/crates/jmap/Cargo.toml +++ b/crates/jmap/Cargo.toml @@ -55,4 +55,5 @@ hashify = "0.2" [features] test_mode = [] +dev_mode = [] enterprise = [] diff --git a/crates/jmap/src/calendar/set.rs b/crates/jmap/src/calendar/set.rs index 6fd9a36e..a8e16751 100644 --- a/crates/jmap/src/calendar/set.rs +++ b/crates/jmap/src/calendar/set.rs @@ -578,12 +578,12 @@ fn value_to_default_alert( }; match (key, value) { - (CalendarProperty::Type, Value::Element(CalendarValue::Type(value))) => { - if value != JSCalendarType::Alert { - return Err(SetError::invalid_properties() - .with_property(CalendarProperty::Trigger) - .with_description("Invalid alert object type.")); - } + (CalendarProperty::Type, Value::Element(CalendarValue::Type(value))) + if value != JSCalendarType::Alert => + { + return Err(SetError::invalid_properties() + .with_property(CalendarProperty::Trigger) + .with_description("Invalid alert object type.")); } ( CalendarProperty::Action, @@ -611,12 +611,12 @@ fn value_to_default_alert( alert.offset = value; has_offset = true; } - (CalendarProperty::Offset, Value::Element(CalendarValue::Type(value))) => { - if value != JSCalendarType::OffsetTrigger { - return Err(SetError::invalid_properties() - .with_property(CalendarProperty::Trigger) - .with_description("Invalid alert trigger type.")); - } + (CalendarProperty::Offset, Value::Element(CalendarValue::Type(value))) + if value != JSCalendarType::OffsetTrigger => + { + return Err(SetError::invalid_properties() + .with_property(CalendarProperty::Trigger) + .with_description("Invalid alert trigger type.")); } _ => {} } diff --git a/crates/jmap/src/contact/query.rs b/crates/jmap/src/contact/query.rs index acf48b31..5c6928d0 100644 --- a/crates/jmap/src/contact/query.rs +++ b/crates/jmap/src/contact/query.rs @@ -290,7 +290,7 @@ impl ContactCardQuery for Server { )), ContactCardComparator::Updated => { let mut updated = created_to_updated.clone(); - updated.sort_by(|a, b| a.updated.cmp(&b.updated)); + updated.sort_by_key(|a| a.updated); Ok(SearchComparator::sorted_set( updated .iter() diff --git a/crates/jmap/src/registry/get.rs b/crates/jmap/src/registry/get.rs index f1f6f67b..32b18b3e 100644 --- a/crates/jmap/src/registry/get.rs +++ b/crates/jmap/src/registry/get.rs @@ -7,9 +7,9 @@ use crate::registry::{ EnterpriseRegistry, mapping::{ - RegistryGetResponse, account::account_get, cluster::cluster_node_get, log::log_get, - queued_message::queued_message_get, report::report_get, spam_sample::spam_sample_get, - task::task_get, + RegistryGetResponse, account::account_get, bootstrap::bootstrap_get, + cluster::cluster_node_get, log::log_get, queued_message::queued_message_get, + report::report_get, spam_sample::spam_sample_get, task::task_get, }, }; use common::{Server, auth::AccessToken, network::dkim::generate_dkim_public_key}; @@ -51,6 +51,13 @@ impl RegistryGet for Server { mut request: GetRequest, access_token: &AccessToken, ) -> trc::Result> { + // Initial assertions + if self.registry().is_bootstrap_mode() && !matches!(object_type, ObjectType::Bootstrap) { + return Err(trc::JmapEvent::Forbidden.into_err().details(concat!( + "The server is in bootstrap mode. Only the 'Bootstrap' object type ", + "can be accessed until the bootstrap process is complete.", + ))); + } self.assert_enterprise_object(object_type)?; let object_flags = object_type.flags(); @@ -344,6 +351,7 @@ impl RegistryGet for Server { spam_sample_get(get).await.map(|get| get.into_response()) } ObjectType::Log => log_get(get).await.map(|get| get.into_response()), + ObjectType::Bootstrap => bootstrap_get(get).await.map(|get| get.into_response()), ObjectType::AccountSettings | ObjectType::ApiKey | ObjectType::AccountPassword diff --git a/crates/jmap/src/registry/mapping/account.rs b/crates/jmap/src/registry/mapping/account.rs index 90973e78..13968c33 100644 --- a/crates/jmap/src/registry/mapping/account.rs +++ b/crates/jmap/src/registry/mapping/account.rs @@ -535,17 +535,17 @@ pub(crate) async fn account_set( Credential::AppPassword(credential), Credential::AppPassword(old_credential), ) - | (Credential::ApiKey(credential), Credential::ApiKey(old_credential)) => { + | (Credential::ApiKey(credential), Credential::ApiKey(old_credential)) + if credential.secret != old_credential.secret => + { // Paranoid check, this is verified in the patch implementation - if credential.secret != old_credential.secret { - set.response.not_updated.append( - id, - SetError::forbidden().with_description( - "Cannot change the value of an app password or API key.", - ), - ); - continue 'outer; - } + set.response.not_updated.append( + id, + SetError::forbidden().with_description( + "Cannot change the value of an app password or API key.", + ), + ); + continue 'outer; } _ => {} } @@ -852,9 +852,9 @@ pub(crate) async fn credential_query( } Property::Id => { if params.sort_ascending { - matches.sort_by(|a, b| a.0.cmp(&b.0)); + matches.sort_by_key(|a| a.0); } else { - matches.sort_by(|a, b| b.0.cmp(&a.0)); + matches.sort_by_key(|b| std::cmp::Reverse(b.0)); } } property => { diff --git a/crates/jmap/src/registry/mapping/bootstrap.rs b/crates/jmap/src/registry/mapping/bootstrap.rs new file mode 100644 index 00000000..3708db39 --- /dev/null +++ b/crates/jmap/src/registry/mapping/bootstrap.rs @@ -0,0 +1,585 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use crate::registry::{ + mapping::{RegistryGetResponse, RegistrySetResponse}, + set::map_write_error, +}; +use common::{DATABASE_SCHEMA_VERSION, Server, network::acme::account::acme_create_account, psl}; +use directory::core::secret::hash_secret; +use jmap_proto::error::set::{SetError, SetErrorType}; +use jmap_tools::{JsonPointer, JsonPointerItem, Key}; +use rand::{Rng, distr::Alphanumeric, rng}; +use registry::{ + jmap::{IntoValue, JmapValue, JsonPointerPatch, RegistryJsonPatch}, + schema::{ + enums::{AcmeChallengeType, DnsRecordType}, + prelude::{Object, Property}, + structs::{ + Account, AcmeProvider, BlobStore, Bootstrap, CertificateManagement, + CertificateManagementProperties, Credential, DataStore, Directory, DirectoryBootstrap, + DkimManagement, DkimManagementProperties, DnsManagement, DnsManagementProperties, + DnsServer, DnsServerBootstrap, Domain, InMemoryStore, PasswordCredential, RocksDbStore, + SearchStore, SystemSettings, Task, TaskDnsManagement, TaskDomainManagement, TaskStatus, + Tracer, TracerLog, UserAccount, UserRoles, + }, + }, + types::{ObjectImpl, list::List, map::Map}, +}; +use store::{ + RegistryStore, SUBSPACE_PROPERTY, Store, + registry::write::{RegistryWrite, RegistryWriteResult}, + write::{AnyKey, BatchBuilder}, +}; +use types::id::Id; + +pub(crate) async fn bootstrap_get( + mut get: RegistryGetResponse<'_>, +) -> trc::Result> { + if !get.server.registry().is_bootstrap_mode() { + get.not_found(Id::singleton()); + return Ok(get); + } + + let mut ids = get + .ids + .take() + .unwrap_or_else(|| vec![Id::singleton()]) + .into_iter(); + + for id in ids.by_ref() { + if id == Id::singleton() { + get.insert( + Id::singleton(), + build_default_bootstrap(get.server).into_value(), + ); + break; + } else { + get.not_found(id); + } + } + + get.response.not_found.extend(ids); + Ok(get) +} + +pub(crate) async fn bootstrap_set( + mut set: RegistrySetResponse<'_>, +) -> trc::Result> { + if !set.server.registry().is_bootstrap_mode() { + set.fail_all_create("This operation is only allowed bootstrap mode"); + set.fail_all_update("This operation is only allowed bootstrap mode"); + set.fail_all_destroy("This operation is only allowed bootstrap mode"); + return Ok(set); + } + + set.fail_all_create("Bootstrap objects can only be updated"); + set.fail_all_destroy("Bootstrap objects cannot be deleted"); + + let mut bootstrap = build_default_bootstrap(set.server); + + 'outer: for (id, value) in set.update.drain(..) { + if id != Id::singleton() { + set.response.not_updated.append(id, SetError::not_found()); + continue; + } + + for (key, value) in value.into_expanded_object() { + if let Key::Property(property) = key { + let ptr = JsonPointer::new(vec![JsonPointerItem::Key(Key::Property(property))]); + if let Err(err) = + bootstrap.patch(JsonPointerPatch::new(&ptr).with_create(false), value) + { + set.response.not_updated.append(id, err.into()); + break 'outer; + } + } else { + set.response.not_updated.append( + id, + SetError::invalid_properties().with_property(key.into_owned()), + ); + break 'outer; + } + } + + let mut validation_errors = Vec::new(); + if !bootstrap.validate(&mut validation_errors) { + set.response.not_updated.append( + id, + SetError::new(SetErrorType::ValidationFailed) + .with_validation_errors(validation_errors), + ); + break; + } + + // Validate domain name and hostname + let server_hostname = bootstrap.server_hostname.trim().to_lowercase(); + let domain_name = bootstrap.default_domain.trim().to_lowercase(); + if psl::domain_str(&server_hostname).is_none() { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::ServerHostname) + .with_description("Invalid server hostname"), + ); + break; + } + if psl::domain_str(&domain_name).is_none() { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DefaultDomain) + .with_description("Invalid default domain"), + ); + break; + } + + // Build store + let store = match Store::build(bootstrap.data_store.clone()).await { + Ok(store) => store, + Err(err) => { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description(err), + ); + break; + } + }; + + // Create tables (SQL only) + if let Err(err) = store.create_tables().await { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description(format!("Failed to initialize data store: {err}")), + ); + break; + } + + // Make sure this is blank deployment + match store + .get_value::(AnyKey { + subspace: SUBSPACE_PROPERTY, + key: vec![0u8], + }) + .await + { + Ok(None) => {} + Ok(Some(DATABASE_SCHEMA_VERSION)) => { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description("The selected data store has already been initialized."), + ); + break; + } + Ok(Some(_)) => { + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description(concat!( + "The selected data store contains information from an older version. ", + "Please follow the upgrade instructions at ", + "https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md" + )), + ); + break; + } + Err(err) => { + trc::error!(err.caused_by(trc::location!())); + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description( + "Failed to initialize data store, check logs for details.", + ), + ); + break; + } + }; + + // Validate stores and registry + let tmp_registry = set.server.registry(); + for (property, object) in [ + ( + Property::BlobStore, + Some(bootstrap.blob_store.clone().into()), + ), + ( + Property::SearchStore, + Some(bootstrap.search_store.clone().into()), + ), + ( + Property::InMemoryStore, + Some(bootstrap.in_memory_store.clone().into()), + ), + ( + Property::Directory, + map_directory(&bootstrap.directory).map(Into::into), + ), + ( + Property::DnsServer, + map_dns_server(&bootstrap.dns_server).map(Into::into), + ), + (Property::Tracer, Some(bootstrap.tracer.clone().into())), + ] { + if let Some(object) = object { + match write_object(tmp_registry, &object).await { + Ok(_) => {} + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(property)); + break 'outer; + } + } + } + } + + // Create inner store + let registry = + RegistryStore::from_inner_bootstrapped(set.server.registry().initialize_inner(store)); + + // Save datastore + if let Err(err) = registry.write_data_store(&bootstrap.data_store).await { + let details = format!("Failed to save data store settings: {err}"); + trc::error!(err.caused_by(trc::location!())); + set.response.not_updated.append( + id, + SetError::invalid_properties() + .with_property(Property::DataStore) + .with_description(details), + ); + break; + } + + // Write stores and traces to registry + for (property, object) in [ + (Property::BlobStore, bootstrap.blob_store.into()), + (Property::SearchStore, bootstrap.search_store.into()), + (Property::InMemoryStore, bootstrap.in_memory_store.into()), + (Property::Tracer, bootstrap.tracer.into()), + ] { + match write_object(®istry, &object).await { + Ok(_) => {} + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(property)); + break 'outer; + } + } + } + + // Write directory and dns server to registry + let mut directory_id = None; + let mut dns_server_id = None; + if let Some(directory) = map_directory(&bootstrap.directory) { + match write_object(®istry, &directory.into()).await { + Ok(id) => { + directory_id = Some(id); + } + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::Directory)); + break 'outer; + } + } + } + if let Some(dns_server) = map_dns_server(&bootstrap.dns_server) { + match write_object(®istry, &dns_server.into()).await { + Ok(id) => { + dns_server_id = Some(id); + } + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::DnsServer)); + break 'outer; + } + } + } + + // Create ACME provider if needed + let mut acme_provider_id = None; + if bootstrap.request_tls_certificate { + let mut acme_provider = AcmeProvider { + challenge_type: if dns_server_id.is_some() { + AcmeChallengeType::Dns01 + } else { + AcmeChallengeType::TlsAlpn01 + }, + contact: Map::new(vec![format!("postmaster@{domain_name}")]), + #[cfg(not(feature = "dev_mode"))] + directory: "https://acme-v02.api.letsencrypt.org/directory".to_string(), + #[cfg(feature = "dev_mode")] + directory: "https://localhost:14000/dir".to_string(), + ..Default::default() + }; + if let Err(err) = acme_create_account(&mut acme_provider, None).await { + trc::error!(trc::ResourceEvent::Error.into_err().reason(err)); + } else { + match write_object(®istry, &acme_provider.into()).await { + Ok(id) => { + acme_provider_id = Some(id); + } + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::DataStore)); + break 'outer; + } + } + } + } + + // Create domain + let publish_records = Map::new(vec![ + DnsRecordType::Dkim, + DnsRecordType::Spf, + DnsRecordType::Dmarc, + DnsRecordType::Srv, + DnsRecordType::MtaSts, + DnsRecordType::TlsRpt, + DnsRecordType::AutoConfig, + DnsRecordType::AutoConfigLegacy, + DnsRecordType::AutoDiscover, + ]); + let domain = Domain { + name: domain_name.clone(), + is_enabled: true, + certificate_management: if let Some(acme_provider_id) = acme_provider_id { + CertificateManagement::Automatic(CertificateManagementProperties { + acme_provider_id, + subject_alternative_names: Default::default(), + }) + } else { + CertificateManagement::Manual + }, + dkim_management: if bootstrap.generate_dkim_keys { + DkimManagement::Automatic(DkimManagementProperties::default()) + } else { + DkimManagement::Manual + }, + dns_management: if let Some(dns_server_id) = dns_server_id { + DnsManagement::Automatic(DnsManagementProperties { + dns_server_id, + origin: None, + publish_records: publish_records.clone(), + }) + } else { + DnsManagement::Manual + }, + directory_id, + ..Default::default() + }; + let domain_id = match write_object(®istry, &domain.into()).await { + Ok(id) => id, + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::DefaultDomain)); + break 'outer; + } + }; + + // Write system settings + let system_settings = SystemSettings { + default_hostname: bootstrap.server_hostname, + default_domain_id: domain_id, + ..Default::default() + }; + match write_object(®istry, &system_settings.into()).await { + Ok(_) => {} + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::DefaultDomain)); + break 'outer; + } + } + + // Create tasks + let mut batch = BatchBuilder::new(); + if dns_server_id.is_some() { + batch.schedule_task(Task::DnsManagement(TaskDnsManagement { + domain_id, + update_records: publish_records, + on_success_renew_certificate: acme_provider_id.is_some(), + status: TaskStatus::now(), + })); + } else if acme_provider_id.is_some() { + batch.schedule_task(Task::AcmeRenewal(TaskDomainManagement { + domain_id, + status: TaskStatus::now(), + })); + } + if bootstrap.generate_dkim_keys { + batch.schedule_task(Task::DkimManagement(TaskDomainManagement { + domain_id, + status: TaskStatus::now(), + })); + } + if !batch.is_empty() { + match registry.store().write(batch.build_all()).await { + Ok(_) => {} + Err(err) => { + trc::error!(err.caused_by(trc::location!())); + } + } + } + + // Create admin account + let mut response = None; + if directory_id.is_none() { + let secret = rng() + .sample_iter(Alphanumeric) + .take(16) + .map(char::from) + .collect::(); + let account = Account::User(UserAccount { + name: "admin".to_string(), + domain_id, + credentials: List::from_iter([Credential::Password(PasswordCredential { + credential_id: Id::new(0), + secret: hash_secret( + set.server.core.network.security.password_hash_algorithm, + secret.clone().into_bytes(), + ) + .await + .unwrap_or_default(), + ..Default::default() + })]), + roles: UserRoles::Admin, + description: "System administrator".to_string().into(), + ..Default::default() + }); + match write_object(®istry, &account.into()).await { + Ok(_) => { + response = Some(JmapValue::Object(jmap_tools::Map::from_iter([ + ( + Key::Property(Property::Username), + JmapValue::Str(format!("admin@{domain_name}").into()), + ), + ( + Key::Property(Property::Secret), + JmapValue::Str(secret.into()), + ), + ]))); + } + Err(err) => { + set.response + .not_updated + .append(id, err.with_property(Property::DefaultDomain)); + break 'outer; + } + } + } + + set.response.updated.append(id, response); + break; + } + + Ok(set) +} + +async fn write_object(registry: &RegistryStore, object: &Object) -> Result> { + match registry.write(RegistryWrite::insert(object)).await { + Ok(RegistryWriteResult::Success(id)) => Ok(id), + Ok(err) => Err(map_write_error(err)), + Err(err) => { + let details = format!("Failed to save settings: {err}"); + trc::error!(err.caused_by(trc::location!())); + Err(SetError::invalid_properties().with_description(details)) + } + } +} + +fn map_directory(directory: &DirectoryBootstrap) -> Option { + match directory { + DirectoryBootstrap::Internal => None, + DirectoryBootstrap::Ldap(ldap_directory) => Directory::Ldap(ldap_directory.clone()).into(), + DirectoryBootstrap::Sql(sql_directory) => Directory::Sql(sql_directory.clone()).into(), + DirectoryBootstrap::Oidc(oidc_directory) => Directory::Oidc(oidc_directory.clone()).into(), + } +} + +fn map_dns_server(dns_server: &DnsServerBootstrap) -> Option { + match dns_server { + DnsServerBootstrap::Manual => None, + DnsServerBootstrap::Tsig(dns_server_tsig) => { + DnsServer::Tsig(dns_server_tsig.clone()).into() + } + DnsServerBootstrap::Sig0(dns_server_sig0) => { + DnsServer::Sig0(dns_server_sig0.clone()).into() + } + DnsServerBootstrap::Cloudflare(dns_server_cloudflare) => { + DnsServer::Cloudflare(dns_server_cloudflare.clone()).into() + } + DnsServerBootstrap::DigitalOcean(dns_server_cloud) => { + DnsServer::DigitalOcean(dns_server_cloud.clone()).into() + } + DnsServerBootstrap::DeSEC(dns_server_cloud) => { + DnsServer::DeSEC(dns_server_cloud.clone()).into() + } + DnsServerBootstrap::Ovh(dns_server_ovh) => DnsServer::Ovh(dns_server_ovh.clone()).into(), + DnsServerBootstrap::Bunny(dns_server_cloud) => { + DnsServer::Bunny(dns_server_cloud.clone()).into() + } + DnsServerBootstrap::Porkbun(dns_server_porkbun) => { + DnsServer::Porkbun(dns_server_porkbun.clone()).into() + } + DnsServerBootstrap::Dnsimple(dns_server_dnsimple) => { + DnsServer::Dnsimple(dns_server_dnsimple.clone()).into() + } + DnsServerBootstrap::Spaceship(dns_server_spaceship) => { + DnsServer::Spaceship(dns_server_spaceship.clone()).into() + } + DnsServerBootstrap::Route53(dns_server_route53) => { + DnsServer::Route53(dns_server_route53.clone()).into() + } + DnsServerBootstrap::GoogleCloudDns(dns_server_google_cloud_dns) => { + DnsServer::GoogleCloudDns(dns_server_google_cloud_dns.clone()).into() + } + } +} + +fn build_default_bootstrap(server: &Server) -> Bootstrap { + let server_hostname = server.registry().local_hostname().to_string(); + let default_domain = psl::domain_str(&server_hostname) + .unwrap_or("example.org") + .to_string(); + + Bootstrap { + data_store: DataStore::RocksDb(RocksDbStore { + path: "/var/lib/stalwart/".to_string(), + ..Default::default() + }), + blob_store: BlobStore::Default, + search_store: SearchStore::Default, + in_memory_store: InMemoryStore::Default, + directory: DirectoryBootstrap::Internal, + tracer: Tracer::Log(TracerLog { + path: "/var/log/stalwart/".to_string(), + prefix: "stalwart".to_string(), + ansi: true, + enable: true, + ..Default::default() + }), + server_hostname, + default_domain, + request_tls_certificate: true, + generate_dkim_keys: true, + dns_server: DnsServerBootstrap::Manual, + } +} diff --git a/crates/jmap/src/registry/mapping/mod.rs b/crates/jmap/src/registry/mapping/mod.rs index 22bca569..6a92b99f 100644 --- a/crates/jmap/src/registry/mapping/mod.rs +++ b/crates/jmap/src/registry/mapping/mod.rs @@ -23,6 +23,7 @@ use utils::map::vec_map::VecMap; pub mod account; pub mod action; +pub mod bootstrap; pub mod cluster; pub mod dkim; pub mod domain; diff --git a/crates/jmap/src/registry/mapping/principal.rs b/crates/jmap/src/registry/mapping/principal.rs index 83ff74cf..69ecd48a 100644 --- a/crates/jmap/src/registry/mapping/principal.rs +++ b/crates/jmap/src/registry/mapping/principal.rs @@ -4,8 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::str::FromStr; - use crate::registry::mapping::{ObjectResponse, RegistrySetResponse, ValidationResult}; use common::{ Server, @@ -64,6 +62,16 @@ pub(crate) async fn validate_account( } else { false }; + let recover_account_id = if set.server.registry().is_recovery_mode() + && let AccountUpdate::Create(client_id) = old_account + && let Some(account_id) = client_id + .strip_prefix("restore-") + .and_then(|id| id.parse::().ok()) + { + Some(account_id) + } else { + None + }; let validate_permissions = match (&mut account, old_account) { (Account::User(account), AccountUpdate::Update(Account::User(old_account))) => { @@ -173,6 +181,7 @@ pub(crate) async fn validate_account( credential, is_external_directory, has_password, + false, ) .await? { @@ -209,6 +218,7 @@ pub(crate) async fn validate_account( credential, is_external_directory, index > 0, + recover_account_id.is_some(), ) .await? { @@ -241,12 +251,8 @@ pub(crate) async fn validate_account( Ok(Ok(ObjectResponse::default())) }; - if set.server.registry().is_recovery_mode() + if let Some(account_id) = recover_account_id && let Ok(Ok(result)) = &mut result - && let AccountUpdate::Create(client_id) = old_account - && let Some(account_id) = client_id - .strip_prefix("restore-") - .and_then(|id| id.parse::().ok()) { restore_account_id(set.server, account_id).await?; result.id = Some(account_id.into()); @@ -260,6 +266,7 @@ async fn validate_credential_creation( credential: &mut Credential, is_external_directory: bool, has_password: bool, + is_recovery_mode: bool, ) -> trc::Result>> { match credential { Credential::Password(credential) => { @@ -273,6 +280,10 @@ async fn validate_credential_creation( .with_description("Only one password credential is allowed."))); } + if is_recovery_mode && credential.secret.starts_with('$') { + return Ok(Ok(())); + } + if let Err(err) = server.is_secure_password(&credential.secret, &[]) { Ok(Err(SetError::invalid_properties() .with_property(Property::Secret) @@ -490,13 +501,13 @@ async fn restore_account_id(server: &Server, id: u32) -> trc::Result<()> { ValueClass::Registry(RegistryClass::IdCounter { object_id }), (id - last_id) as i64, ); - if server + let last_id = server .store() .write(id_batch.build_all()) .await - .and_then(|v| v.last_counter_id())? - < id as i64 - { + .and_then(|v| v.last_counter_id())?; + + if last_id < id as i64 { return Err(trc::StoreEvent::UnexpectedError .into_err() .details("Failed to update id counter") diff --git a/crates/jmap/src/registry/mapping/queued_message.rs b/crates/jmap/src/registry/mapping/queued_message.rs index 9c763102..f1271c38 100644 --- a/crates/jmap/src/registry/mapping/queued_message.rs +++ b/crates/jmap/src/registry/mapping/queued_message.rs @@ -83,7 +83,7 @@ pub(crate) async fn queued_message_set( // Process patches let prev_event = archived_message.inner.next_delivery_event(None); let mut message = map_message(archived_message.inner); - let prev_next_retry = message.next_retry; + message.next_retry = None; for (key, value) in value.into_expanded_object() { let ptr = match key { Key::Property(prop) => { @@ -97,7 +97,7 @@ pub(crate) async fn queued_message_set( continue 'outer; } } - let set_next_retry = (message.next_retry != prev_next_retry).then_some(message.next_retry); + let set_next_retry = message.next_retry; // Process changes let mut has_changes = false; @@ -575,7 +575,8 @@ fn map_message(message_in: &ArchivedMessage) -> QueuedMessage { .next_delivery_event(None) .unwrap_or_else(now) .cast_signed(), - ), + ) + .into(), next_notify: message_in .next_notify_event(None) .map(|ts| UTCDateTime::from_timestamp(ts.cast_signed())), diff --git a/crates/jmap/src/registry/query.rs b/crates/jmap/src/registry/query.rs index 5949e1d8..457ee576 100644 --- a/crates/jmap/src/registry/query.rs +++ b/crates/jmap/src/registry/query.rs @@ -52,6 +52,13 @@ impl RegistryQuery for Server { mut request: QueryRequest, access_token: &AccessToken, ) -> trc::Result { + // Initial assertions + if self.registry().is_bootstrap_mode() { + return Err(trc::JmapEvent::Forbidden.into_err().details(concat!( + "The server is in bootstrap mode. Only the 'Bootstrap' object type ", + "can be accessed until the bootstrap process is complete.", + ))); + } self.assert_enterprise_object(object_type)?; match object_type { diff --git a/crates/jmap/src/registry/set.rs b/crates/jmap/src/registry/set.rs index 2f737966..da61ab5d 100644 --- a/crates/jmap/src/registry/set.rs +++ b/crates/jmap/src/registry/set.rs @@ -10,6 +10,7 @@ use crate::registry::{ ObjectResponse, RegistrySetResponse, account::account_set, action::action_set, + bootstrap::bootstrap_set, dkim::validate_dkim_signature, domain::{validate_dns_server, validate_domain}, map_bootstrap_error, @@ -92,6 +93,13 @@ impl RegistrySet for Server { access_token: &AccessToken, session: &HttpSessionData, ) -> trc::Result> { + // Initial assertions + if self.registry().is_bootstrap_mode() && !matches!(object_type, ObjectType::Bootstrap) { + return Err(trc::JmapEvent::Forbidden.into_err().details(concat!( + "The server is in bootstrap mode. Only the 'Bootstrap' object type ", + "can be modified until the bootstrap process is complete.", + ))); + } self.assert_enterprise_object(object_type)?; let object_flags = object_type.flags(); @@ -668,6 +676,10 @@ impl RegistrySet for Server { ObjectType::Action => action_set(set).await.map(|set| set.into_response()), + ObjectType::Bootstrap => Box::pin(bootstrap_set(set)) + .await + .map(|set| set.into_response()), + ObjectType::Log | ObjectType::Metric | ObjectType::Trace | ObjectType::ClusterNode => { set.fail_all_create("Telemetry objects cannot be created"); set.fail_all_update("Telemetry objects cannot be modified"); diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml index b7c0ae84..608425c9 100644 --- a/crates/main/Cargo.toml +++ b/crates/main/Cargo.toml @@ -75,4 +75,5 @@ dev_mode = [ "common/dev_mode", "trc/dev_mode", "dav/dev_mode", "http/dev_mode", - "http_proto/dev_mode" ] + "http_proto/dev_mode", + "jmap/dev_mode" ] diff --git a/crates/main/src/main.rs b/crates/main/src/main.rs index 7decd5ad..cbf2fbee 100644 --- a/crates/main/src/main.rs +++ b/crates/main/src/main.rs @@ -36,15 +36,14 @@ async fn main() -> std::io::Result<()> { let mut init = Box::pin(BootManager::init()).await; // Migrate database - let todo = "fix"; - /*if let Err(err) = migration::try_migrate(&init.inner.build_server()).await { + if let Err(err) = migration::try_migrate(&init.inner.build_server()).await { trc::event!( Server(trc::ServerEvent::StartupError), Details = "Failed to migrate database, aborting startup.", Reason = err, ); return Ok(()); - }*/ + } // Init services init.start_services().await; diff --git a/crates/migration/src/lib.rs b/crates/migration/src/lib.rs index fdf1f09a..1d9ee380 100644 --- a/crates/migration/src/lib.rs +++ b/crates/migration/src/lib.rs @@ -33,14 +33,14 @@ pub async fn try_migrate(server: &Server) -> trc::Result<()> { } Some(0..=4) => { abort(concat!( - "You must first upgrade to 0.15, please read ", + "You must first upgrade to version 0.15, please read ", "https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md" )); } Some(5) => { - if !std::env::var("MIGRATE").is_ok_and(|v| v == "1") { + if !server.registry().is_recovery_mode() { abort(concat!( - "Upgrading to 0.16 is a multi-step process, please read ", + "Upgrading to version 0.16 is a multi-step process, please read ", "https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md" )); } @@ -57,7 +57,7 @@ pub async fn try_migrate(server: &Server) -> trc::Result<()> { return Ok(()); } else { abort(concat!( - "You must first upgrade to 0.15, please read ", + "You must first upgrade to version 0.15, please read ", "https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md" )); } diff --git a/crates/migration/src/v016.rs b/crates/migration/src/v016.rs index 208254d6..8614d23e 100644 --- a/crates/migration/src/v016.rs +++ b/crates/migration/src/v016.rs @@ -39,7 +39,7 @@ pub async fn migrate_v0_16(server: &Server) -> trc::Result<()> { .search_store() .unindex( SearchQuery::new(SearchIndex::Tracing) - .with_filter(SearchFilter::ge(SearchField::Id, 0u64)), + .with_filter(SearchFilter::lt(SearchField::Id, u64::MAX)), ) .await .caused_by(trc::location!())?; @@ -74,10 +74,10 @@ pub async fn migrate_v0_16(server: &Server) -> trc::Result<()> { SUBSPACE_TELEMETRY_SPAN, SUBSPACE_TASK_QUEUE, ] { - destroy_subspace(server.store(), namespace).await?; + destroy_subspace(server.store(), namespace) + .await + .caused_by(trc::location!())?; } - destroy_subspace(server.metrics_store(), SUBSPACE_TELEMETRY_METRIC).await?; - destroy_subspace(server.tracing_store(), SUBSPACE_TELEMETRY_SPAN).await?; // Migrate blob links migrate_blob_links(server).await?; @@ -172,25 +172,26 @@ async fn migrate_blob_links(server: &Server) -> trc::Result<()> { const UNDELETE_LINK: u8 = 1; const SPAM_SAMPLE_LINK: u8 = 2; - let until = key.deserialize_be_u64(BLOB_HASH_LEN + U32_LEN)?; + if key.len() == TEMP_LINK && value.len() == 1 { + let until = key.deserialize_be_u64(BLOB_HASH_LEN + U32_LEN)?; + if until > now { + let account_id = key.deserialize_be_u32(BLOB_HASH_LEN)?; + let hash = types::blob_hash::BlobHash::try_from_hash_slice( + key.get(0..BLOB_HASH_LEN).ok_or_else(|| { + trc::Error::corrupted_key(key, None, trc::location!()) + })?, + ) + .unwrap(); - if key.len() == TEMP_LINK && value.len() == 1 && until > now { - let account_id = key.deserialize_be_u32(BLOB_HASH_LEN)?; - let hash = types::blob_hash::BlobHash::try_from_hash_slice( - key.get(0..BLOB_HASH_LEN).ok_or_else(|| { - trc::Error::corrupted_key(key, None, trc::location!()) - })?, - ) - .unwrap(); - - match value.first().copied() { - Some(UNDELETE_LINK) => { - archived_items.push((key.to_vec(), account_id, hash, until)); + match value.first().copied() { + Some(UNDELETE_LINK) => { + archived_items.push((key.to_vec(), account_id, hash, until)); + } + Some(SPAM_SAMPLE_LINK | QUOTA_LINK) => { + delete_keys.push(key.to_vec()); + } + _ => {} } - Some(SPAM_SAMPLE_LINK | QUOTA_LINK) => { - delete_keys.push(key.to_vec()); - } - _ => {} } } diff --git a/crates/registry/src/jmap/patch.rs b/crates/registry/src/jmap/patch.rs index 9b5731b3..13c695d3 100644 --- a/crates/registry/src/jmap/patch.rs +++ b/crates/registry/src/jmap/patch.rs @@ -379,7 +379,7 @@ impl RegistryJsonPatch for T { unpatched.append(property, value); } Ok(MaybeUnpatched::UnpatchedMany { properties }) => { - unpatched.extend(properties.into_iter()); + unpatched.extend(properties); } Err(mut e) => { if !e.path.is_empty() { diff --git a/crates/registry/src/schema/enums.rs b/crates/registry/src/schema/enums.rs new file mode 100644 index 00000000..c622de7d --- /dev/null +++ b/crates/registry/src/schema/enums.rs @@ -0,0 +1,3827 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AccountType { + #[default] + User = 0, + Group = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AcmeChallengeType { + #[default] + TlsAlpn01 = 0, + DnsPersist01 = 1, + Dns01 = 2, + Http01 = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AcmeRenewBefore { + #[default] + R12 = 0, + R23 = 1, + R34 = 2, + R45 = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ActionType { + #[default] + ReloadSettings = 0, + ReloadTlsCertificates = 1, + ReloadLookupStores = 2, + ReloadBlockedIps = 3, + UpdateApps = 4, + TroubleshootDmarc = 5, + ClassifySpam = 6, + InvalidateCaches = 7, + InvalidateNegativeCaches = 8, + PauseMtaQueue = 9, + ResumeMtaQueue = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AiModelType { + #[default] + Chat = 0, + Text = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AlertEmailType { + #[default] + Disabled = 0, + Enabled = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AlertEventType { + #[default] + Disabled = 0, + Enabled = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArchivedItemStatus { + #[default] + Archived = 0, + RequestRestore = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArchivedItemType { + #[default] + Email = 0, + FileNode = 1, + CalendarEvent = 2, + ContactCard = 3, + SieveScript = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArfAuthFailureType { + #[default] + Adsp = 0, + BodyHash = 1, + Revoked = 2, + Signature = 3, + Spf = 4, + Dmarc = 5, + Unspecified = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArfDeliveryResult { + #[default] + Delivered = 0, + Spam = 1, + Policy = 2, + Reject = 3, + Other = 4, + Unspecified = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArfFeedbackType { + #[default] + Abuse = 0, + AuthFailure = 1, + Fraud = 2, + NotSpam = 3, + Virus = 4, + Other = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ArfIdentityAlignment { + #[default] + None = 0, + Spf = 1, + Dkim = 2, + DkimSpf = 3, + Unspecified = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum AsnType { + #[default] + Disabled = 0, + Resource = 1, + Dns = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum BlobStoreBaseType { + #[default] + S3 = 0, + Azure = 1, + FileSystem = 2, + FoundationDb = 3, + PostgreSql = 4, + MySql = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum BlobStoreType { + #[default] + Default = 0, + Sharded = 1, + S3 = 2, + Azure = 3, + FileSystem = 4, + FoundationDb = 5, + PostgreSql = 6, + MySql = 7, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum BlockReason { + #[default] + RcptToFailure = 0, + AuthFailure = 1, + Loitering = 2, + PortScanning = 3, + Manual = 4, + Other = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CertificateManagementType { + #[default] + Manual = 0, + Automatic = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ClusterListenerGroupType { + #[default] + EnableAll = 0, + DisableAll = 1, + EnableSome = 2, + DisableSome = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ClusterNodeStatus { + #[default] + Active = 0, + Stale = 1, + Inactive = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ClusterTaskGroupType { + #[default] + EnableAll = 0, + DisableAll = 1, + EnableSome = 2, + DisableSome = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ClusterTaskType { + #[default] + StoreMaintenance = 0, + AccountMaintenance = 1, + MetricsCalculate = 2, + MetricsPush = 3, + PushNotifications = 4, + SearchIndexing = 5, + SpamClassifierTraining = 6, + OutboundMta = 7, + TaskQueueProcessing = 8, + TaskScheduler = 9, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CompressionAlgo { + #[default] + Lz4 = 0, + None = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CoordinatorType { + #[default] + Disabled = 0, + Default = 1, + Kafka = 2, + Nats = 3, + Zenoh = 4, + Redis = 5, + RedisCluster = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CredentialPermissionsType { + #[default] + Inherit = 0, + Disable = 1, + Replace = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CredentialType { + #[default] + Password = 0, + AppPassword = 1, + ApiKey = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum CronType { + #[default] + Daily = 0, + Weekly = 1, + Hourly = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DataStoreType { + #[default] + RocksDb = 0, + Sqlite = 1, + FoundationDb = 2, + PostgreSql = 3, + MySql = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DeliveryErrorType { + #[default] + DnsError = 0, + UnexpectedResponse = 1, + ConnectionError = 2, + TlsError = 3, + DaneError = 4, + MtaStsError = 5, + RateLimited = 6, + ConcurrencyLimited = 7, + Io = 8, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DirectoryBootstrapType { + #[default] + Internal = 0, + Ldap = 1, + Sql = 2, + Oidc = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DirectoryType { + #[default] + Ldap = 0, + Sql = 1, + Oidc = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimAuthResult { + #[default] + None = 0, + Pass = 1, + Fail = 2, + Policy = 3, + Neutral = 4, + TempError = 5, + PermError = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimCanonicalization { + #[default] + RelaxedRelaxed = 0, + SimpleSimple = 1, + RelaxedSimple = 2, + SimpleRelaxed = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimHash { + #[default] + Sha256 = 0, + Sha1 = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimManagementType { + #[default] + Automatic = 0, + Manual = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimRotationStage { + #[default] + Active = 0, + Pending = 1, + Retiring = 2, + Retired = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DkimSignatureType { + #[default] + Dkim1Ed25519Sha256 = 0, + Dkim1RsaSha256 = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcActionDisposition { + #[default] + None = 0, + Pass = 1, + Quarantine = 2, + Reject = 3, + Unspecified = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcAlignment { + #[default] + Relaxed = 0, + Strict = 1, + Unspecified = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcDisposition { + #[default] + None = 0, + Quarantine = 1, + Reject = 2, + Unspecified = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcPolicyOverride { + #[default] + Forwarded = 0, + SampledOut = 1, + TrustedForwarder = 2, + MailingList = 3, + LocalPolicy = 4, + Other = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcResult { + #[default] + Pass = 0, + Fail = 1, + Unspecified = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DmarcTroubleshootAuthResultType { + #[default] + Pass = 0, + Fail = 1, + SoftFail = 2, + TempError = 3, + PermError = 4, + Neutral = 5, + None = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsManagementType { + #[default] + Manual = 0, + Automatic = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsPublishStatus { + #[default] + Synced = 0, + Pending = 1, + Failed = 2, + Unknown = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsRecordType { + #[default] + Dkim = 0, + Tlsa = 1, + Spf = 2, + Mx = 3, + Dmarc = 4, + Srv = 5, + MtaSts = 6, + TlsRpt = 7, + Caa = 8, + AutoConfig = 9, + AutoConfigLegacy = 10, + AutoDiscover = 11, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsResolverProtocol { + #[default] + Tls = 0, + Udp = 1, + Tcp = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsResolverType { + #[default] + System = 0, + Custom = 1, + Cloudflare = 2, + Quad9 = 3, + Google = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsServerBootstrapType { + #[default] + Manual = 0, + Tsig = 1, + Sig0 = 2, + Cloudflare = 3, + DigitalOcean = 4, + DeSEC = 5, + Ovh = 6, + Bunny = 7, + Porkbun = 8, + Dnsimple = 9, + Spaceship = 10, + Route53 = 11, + GoogleCloudDns = 12, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum DnsServerType { + #[default] + Tsig = 0, + Sig0 = 1, + Cloudflare = 2, + DigitalOcean = 3, + DeSEC = 4, + Ovh = 5, + Bunny = 6, + Porkbun = 7, + Dnsimple = 8, + Spaceship = 9, + Route53 = 10, + GoogleCloudDns = 11, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum EncryptionAtRestType { + #[default] + Disabled = 0, + Aes128 = 1, + Aes256 = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum EventPolicy { + #[default] + Include = 0, + Exclude = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ExpressionConstant { + #[default] + Relaxed = 0, + Strict = 1, + Disable = 2, + Optional = 3, + Require = 4, + Ipv4Only = 5, + Ipv6Only = 6, + Ipv6ThenIpv4 = 7, + Ipv4ThenIpv6 = 8, + Hourly = 9, + Daily = 10, + Weekly = 11, + Login = 12, + Plain = 13, + Xoauth2 = 14, + Oauthbearer = 15, + Mixer = 16, + Stanag4406 = 17, + Nsep = 18, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ExpressionVariable { + #[default] + Asn = 0, + Attributes = 1, + AuthenticatedAs = 2, + Authority = 3, + Bcc = 4, + BccDomain = 5, + BccLocal = 6, + BccName = 7, + Body = 8, + BodyHtml = 9, + BodyRaw = 10, + BodyText = 11, + BodyWords = 12, + Cc = 13, + CcDomain = 14, + CcLocal = 15, + CcName = 16, + Country = 17, + Domain = 18, + Email = 19, + EmailLower = 20, + EnvFrom = 21, + EnvFromDomain = 22, + EnvFromLocal = 23, + EnvTo = 24, + ExpiresIn = 25, + From = 26, + FromDomain = 27, + FromLocal = 28, + FromName = 29, + Headers = 30, + HeloDomain = 31, + Host = 32, + Ip = 33, + IpReverse = 34, + IsTls = 35, + IsV4 = 36, + IsV6 = 37, + LastError = 38, + LastStatus = 39, + Listener = 40, + Local = 41, + LocalIp = 42, + LocalPort = 43, + Location = 44, + Method = 45, + Mx = 46, + Name = 47, + NameLower = 48, + NotifyNum = 49, + Octets = 50, + Path = 51, + PathQuery = 52, + Port = 53, + Priority = 54, + Protocol = 55, + Query = 56, + QueueAge = 57, + QueueName = 58, + Raw = 59, + RawLower = 60, + Rcpt = 61, + RcptDomain = 62, + ReceivedFromIp = 63, + ReceivedViaPort = 64, + Recipients = 65, + RemoteIp = 66, + RemoteIpPtr = 67, + RemotePort = 68, + ReplyTo = 69, + ReplyToDomain = 70, + ReplyToLocal = 71, + ReplyToName = 72, + RetryNum = 73, + ReverseIp = 74, + Scheme = 75, + Sender = 76, + SenderDomain = 77, + Size = 78, + Sld = 79, + Source = 80, + Subject = 81, + SubjectThread = 82, + SubjectWords = 83, + To = 84, + ToDomain = 85, + ToLocal = 86, + ToName = 87, + Url = 88, + Value = 89, + ValueLower = 90, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum FailureReportingOption { + #[default] + All = 0, + Any = 1, + DkimFailure = 2, + SpfFailure = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum HttpAuthType { + #[default] + Unauthenticated = 0, + Basic = 1, + Bearer = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum HttpLookupFormatType { + #[default] + Csv = 0, + List = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum InMemoryStoreBaseType { + #[default] + Redis = 0, + RedisCluster = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum InMemoryStoreType { + #[default] + Default = 0, + Sharded = 1, + Redis = 2, + RedisCluster = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum IndexDocumentType { + #[default] + Email = 0, + Calendar = 1, + Contacts = 2, + File = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum IpProtocol { + #[default] + Udp = 0, + Tcp = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum JwtSignatureAlgorithm { + #[default] + Es256 = 0, + Es384 = 1, + Ps256 = 2, + Ps384 = 3, + Ps512 = 4, + Rs256 = 5, + Rs384 = 6, + Rs512 = 7, + Hs256 = 8, + Hs384 = 9, + Hs512 = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum Locale { + #[default] + POSIX = 0, + AaDJ = 1, + AaER = 2, + AaERSaaho = 3, + AaET = 4, + AfZA = 5, + AgrPE = 6, + AkGH = 7, + AmET = 8, + AnES = 9, + AnpIN = 10, + ArAE = 11, + ArBH = 12, + ArDZ = 13, + ArEG = 14, + ArIN = 15, + ArIQ = 16, + ArJO = 17, + ArKW = 18, + ArLB = 19, + ArLY = 20, + ArMA = 21, + ArOM = 22, + ArQA = 23, + ArSA = 24, + ArSD = 25, + ArSS = 26, + ArSY = 27, + ArTN = 28, + ArYE = 29, + AsIN = 30, + AstES = 31, + AycPE = 32, + AzAZ = 33, + AzIR = 34, + BeBY = 35, + BeBYLatin = 36, + BemZM = 37, + BerDZ = 38, + BerMA = 39, + BgBG = 40, + BhbIN = 41, + BhoIN = 42, + BhoNP = 43, + BiVU = 44, + BnBD = 45, + BnIN = 46, + BoCN = 47, + BoIN = 48, + BrFR = 49, + BrFREuro = 50, + BrxIN = 51, + BsBA = 52, + BynER = 53, + CaAD = 54, + CaES = 55, + CaESEuro = 56, + CaESValencia = 57, + CaFR = 58, + CaIT = 59, + CeRU = 60, + ChrUS = 61, + CmnTW = 62, + CrhUA = 63, + CsCZ = 64, + CsbPL = 65, + CvRU = 66, + CyGB = 67, + DaDK = 68, + DeAT = 69, + DeATEuro = 70, + DeBE = 71, + DeBEEuro = 72, + DeCH = 73, + DeDE = 74, + DeDEEuro = 75, + DeIT = 76, + DeLI = 77, + DeLU = 78, + DeLUEuro = 79, + DoiIN = 80, + DsbDE = 81, + DvMV = 82, + DzBT = 83, + ElCY = 84, + ElGR = 85, + ElGREuro = 86, + EnAG = 87, + EnAU = 88, + EnBW = 89, + EnCA = 90, + EnDK = 91, + EnGB = 92, + EnHK = 93, + EnIE = 94, + EnIEEuro = 95, + EnIL = 96, + EnIN = 97, + EnNG = 98, + EnNZ = 99, + EnPH = 100, + EnSC = 101, + EnSG = 102, + EnUS = 103, + EnZA = 104, + EnZM = 105, + EnZW = 106, + Eo = 107, + EsAR = 108, + EsBO = 109, + EsCL = 110, + EsCO = 111, + EsCR = 112, + EsCU = 113, + EsDO = 114, + EsEC = 115, + EsES = 116, + EsESEuro = 117, + EsGT = 118, + EsHN = 119, + EsMX = 120, + EsNI = 121, + EsPA = 122, + EsPE = 123, + EsPR = 124, + EsPY = 125, + EsSV = 126, + EsUS = 127, + EsUY = 128, + EsVE = 129, + EtEE = 130, + EuES = 131, + EuESEuro = 132, + FaIR = 133, + FfSN = 134, + FiFI = 135, + FiFIEuro = 136, + FilPH = 137, + FoFO = 138, + FrBE = 139, + FrBEEuro = 140, + FrCA = 141, + FrCH = 142, + FrFR = 143, + FrFREuro = 144, + FrLU = 145, + FrLUEuro = 146, + FurIT = 147, + FyDE = 148, + FyNL = 149, + GaIE = 150, + GaIEEuro = 151, + GdGB = 152, + GezER = 153, + GezERAbegede = 154, + GezET = 155, + GezETAbegede = 156, + GlES = 157, + GlESEuro = 158, + GuIN = 159, + GvGB = 160, + HaNG = 161, + HakTW = 162, + HeIL = 163, + HiIN = 164, + HifFJ = 165, + HneIN = 166, + HrHR = 167, + HsbDE = 168, + HtHT = 169, + HuHU = 170, + HyAM = 171, + IaFR = 172, + IdID = 173, + IgNG = 174, + IkCA = 175, + IsIS = 176, + ItCH = 177, + ItIT = 178, + ItITEuro = 179, + IuCA = 180, + JaJP = 181, + KaGE = 182, + KabDZ = 183, + KkKZ = 184, + KlGL = 185, + KmKH = 186, + KnIN = 187, + KoKR = 188, + KokIN = 189, + KsIN = 190, + KsINDevanagari = 191, + KuTR = 192, + KwGB = 193, + KyKG = 194, + LbLU = 195, + LgUG = 196, + LiBE = 197, + LiNL = 198, + LijIT = 199, + LnCD = 200, + LoLA = 201, + LtLT = 202, + LvLV = 203, + LzhTW = 204, + MagIN = 205, + MaiIN = 206, + MaiNP = 207, + MfeMU = 208, + MgMG = 209, + MhrRU = 210, + MiNZ = 211, + MiqNI = 212, + MjwIN = 213, + MkMK = 214, + MlIN = 215, + MnMN = 216, + MniIN = 217, + MnwMM = 218, + MrIN = 219, + MsMY = 220, + MtMT = 221, + MyMM = 222, + NanTW = 223, + NanTWLatin = 224, + NbNO = 225, + NdsDE = 226, + NdsNL = 227, + NeNP = 228, + NhnMX = 229, + NiuNU = 230, + NiuNZ = 231, + NlAW = 232, + NlBE = 233, + NlBEEuro = 234, + NlNL = 235, + NlNLEuro = 236, + NnNO = 237, + NrZA = 238, + NsoZA = 239, + OcFR = 240, + OmET = 241, + OmKE = 242, + OrIN = 243, + OsRU = 244, + PaIN = 245, + PaPK = 246, + PapAW = 247, + PapCW = 248, + PlPL = 249, + PsAF = 250, + PtBR = 251, + PtPT = 252, + PtPTEuro = 253, + QuzPE = 254, + RajIN = 255, + RoRO = 256, + RuRU = 257, + RuUA = 258, + RwRW = 259, + SaIN = 260, + SahRU = 261, + SatIN = 262, + ScIT = 263, + SdIN = 264, + SdINDevanagari = 265, + SeNO = 266, + SgsLT = 267, + ShnMM = 268, + ShsCA = 269, + SiLK = 270, + SidET = 271, + SkSK = 272, + SlSI = 273, + SmWS = 274, + SoDJ = 275, + SoET = 276, + SoKE = 277, + SoSO = 278, + SqAL = 279, + SqMK = 280, + SrME = 281, + SrRS = 282, + SrRSLatin = 283, + SsZA = 284, + StZA = 285, + SvFI = 286, + SvFIEuro = 287, + SvSE = 288, + SwKE = 289, + SwTZ = 290, + SzlPL = 291, + TaIN = 292, + TaLK = 293, + TcyIN = 294, + TeIN = 295, + TgTJ = 296, + ThTH = 297, + TheNP = 298, + TiER = 299, + TiET = 300, + TigER = 301, + TkTM = 302, + TlPH = 303, + TnZA = 304, + ToTO = 305, + TpiPG = 306, + TrCY = 307, + TrTR = 308, + TsZA = 309, + TtRU = 310, + TtRUIqtelif = 311, + UgCN = 312, + UkUA = 313, + UnmUS = 314, + UrIN = 315, + UrPK = 316, + UzUZ = 317, + UzUZCyrillic = 318, + VeZA = 319, + ViVN = 320, + WaBE = 321, + WaBEEuro = 322, + WaeCH = 323, + WalET = 324, + WoSN = 325, + XhZA = 326, + YiUS = 327, + YoNG = 328, + YueHK = 329, + YuwPG = 330, + ZhCN = 331, + ZhHK = 332, + ZhSG = 333, + ZhTW = 334, + ZuZA = 335, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum LogRotateFrequency { + #[default] + Daily = 0, + Hourly = 1, + Minutely = 2, + Never = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum LookupStoreType { + #[default] + PostgreSql = 0, + MySql = 1, + Sqlite = 2, + Sharded = 3, + Redis = 4, + RedisCluster = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MessageFlag { + #[default] + Authenticated = 0, + Unauthenticated = 1, + UnauthenticatedDmarc = 2, + Dsn = 3, + Report = 4, + Autogenerated = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MetricType { + #[default] + Counter = 0, + Gauge = 1, + Histogram = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MetricsOtelType { + #[default] + Disabled = 0, + Http = 1, + Grpc = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MetricsPrometheusType { + #[default] + Disabled = 0, + Enabled = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MetricsStoreType { + #[default] + Disabled = 0, + Default = 1, + FoundationDb = 2, + PostgreSql = 3, + MySql = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MilterVersion { + #[default] + V2 = 0, + V6 = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ModelSize { + #[default] + V16 = 0, + V17 = 1, + V18 = 2, + V19 = 3, + V20 = 4, + V21 = 5, + V22 = 6, + V23 = 7, + V24 = 8, + V25 = 9, + V26 = 10, + V27 = 11, + V28 = 12, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaDeliveryExpirationType { + #[default] + Ttl = 0, + Attempts = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaDeliveryScheduleIntervalsOrDefaultType { + #[default] + Default = 0, + Custom = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaInboundThrottleKey { + #[default] + Listener = 0, + RemoteIp = 1, + LocalIp = 2, + AuthenticatedAs = 3, + HeloDomain = 4, + Sender = 5, + SenderDomain = 6, + Rcpt = 7, + RcptDomain = 8, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaIpStrategy { + #[default] + V4ThenV6 = 0, + V6ThenV4 = 1, + V4Only = 2, + V6Only = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaOutboundThrottleKey { + #[default] + Mx = 0, + RemoteIp = 1, + LocalIp = 2, + Sender = 3, + SenderDomain = 4, + RcptDomain = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaProtocol { + #[default] + Smtp = 0, + Lmtp = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaQueueQuotaKey { + #[default] + Sender = 0, + SenderDomain = 1, + Rcpt = 2, + RcptDomain = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaRequiredOrOptional { + #[default] + Optional = 0, + Require = 1, + Disable = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaRouteType { + #[default] + Mx = 0, + Relay = 1, + Local = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum MtaStage { + #[default] + Connect = 0, + Ehlo = 1, + Auth = 2, + Mail = 3, + Rcpt = 4, + Data = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum NetworkListenerProtocol { + #[default] + Smtp = 0, + Lmtp = 1, + Http = 2, + Imap = 3, + Pop3 = 4, + ManageSieve = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum OvhEndpoint { + #[default] + OvhEu = 0, + OvhCa = 1, + KimsufiEu = 2, + KimsufiCa = 3, + SoyoustartEu = 4, + SoyoustartCa = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PasswordHashAlgorithm { + #[default] + Argon2id = 0, + Bcrypt = 1, + Scrypt = 2, + Pbkdf2 = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PasswordStrength { + #[default] + Zero = 0, + One = 1, + Two = 2, + Three = 3, + Four = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum Permission { + #[default] + Authenticate = 0, + AuthenticateWithAlias = 1, + InteractAi = 2, + Impersonate = 3, + UnlimitedRequests = 4, + UnlimitedUploads = 5, + FetchAnyBlob = 6, + EmailSend = 7, + EmailReceive = 8, + CalendarAlarmsSend = 9, + CalendarSchedulingSend = 10, + CalendarSchedulingReceive = 11, + JmapPushSubscriptionGet = 12, + JmapPushSubscriptionCreate = 13, + JmapPushSubscriptionUpdate = 14, + JmapPushSubscriptionDestroy = 15, + JmapMailboxGet = 16, + JmapMailboxChanges = 17, + JmapMailboxQuery = 18, + JmapMailboxQueryChanges = 19, + JmapMailboxCreate = 20, + JmapMailboxUpdate = 21, + JmapMailboxDestroy = 22, + JmapThreadGet = 23, + JmapThreadChanges = 24, + JmapEmailGet = 25, + JmapEmailChanges = 26, + JmapEmailQuery = 27, + JmapEmailQueryChanges = 28, + JmapEmailCreate = 29, + JmapEmailUpdate = 30, + JmapEmailDestroy = 31, + JmapEmailCopy = 32, + JmapEmailImport = 33, + JmapEmailParse = 34, + JmapSearchSnippetGet = 35, + JmapIdentityGet = 36, + JmapIdentityChanges = 37, + JmapIdentityCreate = 38, + JmapIdentityUpdate = 39, + JmapIdentityDestroy = 40, + JmapEmailSubmissionGet = 41, + JmapEmailSubmissionChanges = 42, + JmapEmailSubmissionQuery = 43, + JmapEmailSubmissionQueryChanges = 44, + JmapEmailSubmissionCreate = 45, + JmapEmailSubmissionUpdate = 46, + JmapEmailSubmissionDestroy = 47, + JmapVacationResponseGet = 48, + JmapVacationResponseCreate = 49, + JmapVacationResponseUpdate = 50, + JmapVacationResponseDestroy = 51, + JmapSieveScriptGet = 52, + JmapSieveScriptQuery = 53, + JmapSieveScriptValidate = 54, + JmapSieveScriptCreate = 55, + JmapSieveScriptUpdate = 56, + JmapSieveScriptDestroy = 57, + JmapPrincipalGet = 58, + JmapPrincipalQuery = 59, + JmapPrincipalChanges = 60, + JmapPrincipalQueryChanges = 61, + JmapPrincipalGetAvailability = 62, + JmapPrincipalCreate = 63, + JmapPrincipalUpdate = 64, + JmapPrincipalDestroy = 65, + JmapQuotaGet = 66, + JmapQuotaChanges = 67, + JmapQuotaQuery = 68, + JmapQuotaQueryChanges = 69, + JmapBlobGet = 70, + JmapBlobCopy = 71, + JmapBlobLookup = 72, + JmapBlobUpload = 73, + JmapAddressBookGet = 74, + JmapAddressBookChanges = 75, + JmapAddressBookCreate = 76, + JmapAddressBookUpdate = 77, + JmapAddressBookDestroy = 78, + JmapContactCardGet = 79, + JmapContactCardChanges = 80, + JmapContactCardQuery = 81, + JmapContactCardQueryChanges = 82, + JmapContactCardCreate = 83, + JmapContactCardUpdate = 84, + JmapContactCardDestroy = 85, + JmapContactCardCopy = 86, + JmapContactCardParse = 87, + JmapFileNodeGet = 88, + JmapFileNodeChanges = 89, + JmapFileNodeQuery = 90, + JmapFileNodeQueryChanges = 91, + JmapFileNodeCreate = 92, + JmapFileNodeUpdate = 93, + JmapFileNodeDestroy = 94, + JmapShareNotificationGet = 95, + JmapShareNotificationChanges = 96, + JmapShareNotificationQuery = 97, + JmapShareNotificationQueryChanges = 98, + JmapShareNotificationCreate = 99, + JmapShareNotificationUpdate = 100, + JmapShareNotificationDestroy = 101, + JmapCalendarGet = 102, + JmapCalendarChanges = 103, + JmapCalendarCreate = 104, + JmapCalendarUpdate = 105, + JmapCalendarDestroy = 106, + JmapCalendarEventGet = 107, + JmapCalendarEventChanges = 108, + JmapCalendarEventQuery = 109, + JmapCalendarEventQueryChanges = 110, + JmapCalendarEventCreate = 111, + JmapCalendarEventUpdate = 112, + JmapCalendarEventDestroy = 113, + JmapCalendarEventCopy = 114, + JmapCalendarEventParse = 115, + JmapCalendarEventNotificationGet = 116, + JmapCalendarEventNotificationChanges = 117, + JmapCalendarEventNotificationQuery = 118, + JmapCalendarEventNotificationQueryChanges = 119, + JmapCalendarEventNotificationCreate = 120, + JmapCalendarEventNotificationUpdate = 121, + JmapCalendarEventNotificationDestroy = 122, + JmapParticipantIdentityGet = 123, + JmapParticipantIdentityChanges = 124, + JmapParticipantIdentityCreate = 125, + JmapParticipantIdentityUpdate = 126, + JmapParticipantIdentityDestroy = 127, + JmapCoreEcho = 128, + ImapAuthenticate = 129, + ImapAclGet = 130, + ImapAclSet = 131, + ImapMyRights = 132, + ImapListRights = 133, + ImapAppend = 134, + ImapCapability = 135, + ImapId = 136, + ImapCopy = 137, + ImapMove = 138, + ImapCreate = 139, + ImapDelete = 140, + ImapEnable = 141, + ImapExpunge = 142, + ImapFetch = 143, + ImapIdle = 144, + ImapList = 145, + ImapLsub = 146, + ImapNamespace = 147, + ImapRename = 148, + ImapSearch = 149, + ImapSort = 150, + ImapSelect = 151, + ImapExamine = 152, + ImapStatus = 153, + ImapStore = 154, + ImapSubscribe = 155, + ImapThread = 156, + Pop3Authenticate = 157, + Pop3List = 158, + Pop3Uidl = 159, + Pop3Stat = 160, + Pop3Retr = 161, + Pop3Dele = 162, + SieveAuthenticate = 163, + SieveListScripts = 164, + SieveSetActive = 165, + SieveGetScript = 166, + SievePutScript = 167, + SieveDeleteScript = 168, + SieveRenameScript = 169, + SieveCheckScript = 170, + SieveHaveSpace = 171, + DavSyncCollection = 172, + DavExpandProperty = 173, + DavPrincipalAcl = 174, + DavPrincipalList = 175, + DavPrincipalMatch = 176, + DavPrincipalSearch = 177, + DavPrincipalSearchPropSet = 178, + DavFilePropFind = 179, + DavFilePropPatch = 180, + DavFileGet = 181, + DavFileMkCol = 182, + DavFileDelete = 183, + DavFilePut = 184, + DavFileCopy = 185, + DavFileMove = 186, + DavFileLock = 187, + DavFileAcl = 188, + DavCardPropFind = 189, + DavCardPropPatch = 190, + DavCardGet = 191, + DavCardMkCol = 192, + DavCardDelete = 193, + DavCardPut = 194, + DavCardCopy = 195, + DavCardMove = 196, + DavCardLock = 197, + DavCardAcl = 198, + DavCardQuery = 199, + DavCardMultiGet = 200, + DavCalPropFind = 201, + DavCalPropPatch = 202, + DavCalGet = 203, + DavCalMkCol = 204, + DavCalDelete = 205, + DavCalPut = 206, + DavCalCopy = 207, + DavCalMove = 208, + DavCalLock = 209, + DavCalAcl = 210, + DavCalQuery = 211, + DavCalMultiGet = 212, + DavCalFreeBusyQuery = 213, + OAuthClientRegistration = 214, + OAuthClientOverride = 215, + LiveTracing = 216, + LiveMetrics = 217, + LiveDeliveryTest = 218, + SysAccountGet = 219, + SysAccountCreate = 220, + SysAccountUpdate = 221, + SysAccountDestroy = 222, + SysAccountQuery = 223, + SysAccountPasswordGet = 224, + SysAccountPasswordUpdate = 225, + SysAccountSettingsGet = 226, + SysAccountSettingsUpdate = 227, + SysAcmeProviderGet = 228, + SysAcmeProviderCreate = 229, + SysAcmeProviderUpdate = 230, + SysAcmeProviderDestroy = 231, + SysAcmeProviderQuery = 232, + ActionReloadSettings = 233, + ActionReloadTlsCertificates = 234, + ActionReloadLookupStores = 235, + ActionReloadBlockedIps = 236, + ActionUpdateApps = 237, + ActionTroubleshootDmarc = 238, + ActionClassifySpam = 239, + ActionInvalidateCaches = 240, + ActionInvalidateNegativeCaches = 241, + ActionPauseMtaQueue = 242, + ActionResumeMtaQueue = 243, + SysActionGet = 244, + SysActionCreate = 245, + SysActionUpdate = 246, + SysActionDestroy = 247, + SysActionQuery = 248, + SysAddressBookGet = 249, + SysAddressBookUpdate = 250, + SysAiModelGet = 251, + SysAiModelCreate = 252, + SysAiModelUpdate = 253, + SysAiModelDestroy = 254, + SysAiModelQuery = 255, + SysAlertGet = 256, + SysAlertCreate = 257, + SysAlertUpdate = 258, + SysAlertDestroy = 259, + SysAlertQuery = 260, + SysAllowedIpGet = 261, + SysAllowedIpCreate = 262, + SysAllowedIpUpdate = 263, + SysAllowedIpDestroy = 264, + SysAllowedIpQuery = 265, + SysApiKeyGet = 266, + SysApiKeyCreate = 267, + SysApiKeyUpdate = 268, + SysApiKeyDestroy = 269, + SysApiKeyQuery = 270, + SysAppPasswordGet = 271, + SysAppPasswordCreate = 272, + SysAppPasswordUpdate = 273, + SysAppPasswordDestroy = 274, + SysAppPasswordQuery = 275, + SysApplicationGet = 276, + SysApplicationCreate = 277, + SysApplicationUpdate = 278, + SysApplicationDestroy = 279, + SysApplicationQuery = 280, + SysArchivedItemGet = 281, + SysArchivedItemCreate = 282, + SysArchivedItemUpdate = 283, + SysArchivedItemDestroy = 284, + SysArchivedItemQuery = 285, + SysArfExternalReportGet = 286, + SysArfExternalReportCreate = 287, + SysArfExternalReportUpdate = 288, + SysArfExternalReportDestroy = 289, + SysArfExternalReportQuery = 290, + SysAsnGet = 291, + SysAsnUpdate = 292, + SysAuthenticationGet = 293, + SysAuthenticationUpdate = 294, + SysBlobStoreGet = 295, + SysBlobStoreUpdate = 296, + SysBlockedIpGet = 297, + SysBlockedIpCreate = 298, + SysBlockedIpUpdate = 299, + SysBlockedIpDestroy = 300, + SysBlockedIpQuery = 301, + SysBootstrapGet = 302, + SysBootstrapUpdate = 303, + SysCacheGet = 304, + SysCacheUpdate = 305, + SysCalendarGet = 306, + SysCalendarUpdate = 307, + SysCalendarAlarmGet = 308, + SysCalendarAlarmUpdate = 309, + SysCalendarSchedulingGet = 310, + SysCalendarSchedulingUpdate = 311, + SysCertificateGet = 312, + SysCertificateCreate = 313, + SysCertificateUpdate = 314, + SysCertificateDestroy = 315, + SysCertificateQuery = 316, + SysClusterNodeGet = 317, + SysClusterNodeCreate = 318, + SysClusterNodeUpdate = 319, + SysClusterNodeDestroy = 320, + SysClusterNodeQuery = 321, + SysClusterRoleGet = 322, + SysClusterRoleCreate = 323, + SysClusterRoleUpdate = 324, + SysClusterRoleDestroy = 325, + SysClusterRoleQuery = 326, + SysCoordinatorGet = 327, + SysCoordinatorUpdate = 328, + SysDataRetentionGet = 329, + SysDataRetentionUpdate = 330, + SysDataStoreGet = 331, + SysDataStoreUpdate = 332, + SysDirectoryGet = 333, + SysDirectoryCreate = 334, + SysDirectoryUpdate = 335, + SysDirectoryDestroy = 336, + SysDirectoryQuery = 337, + SysDkimReportSettingsGet = 338, + SysDkimReportSettingsUpdate = 339, + SysDkimSignatureGet = 340, + SysDkimSignatureCreate = 341, + SysDkimSignatureUpdate = 342, + SysDkimSignatureDestroy = 343, + SysDkimSignatureQuery = 344, + SysDmarcExternalReportGet = 345, + SysDmarcExternalReportCreate = 346, + SysDmarcExternalReportUpdate = 347, + SysDmarcExternalReportDestroy = 348, + SysDmarcExternalReportQuery = 349, + SysDmarcInternalReportGet = 350, + SysDmarcInternalReportCreate = 351, + SysDmarcInternalReportUpdate = 352, + SysDmarcInternalReportDestroy = 353, + SysDmarcInternalReportQuery = 354, + SysDmarcReportSettingsGet = 355, + SysDmarcReportSettingsUpdate = 356, + SysDnsResolverGet = 357, + SysDnsResolverUpdate = 358, + SysDnsServerGet = 359, + SysDnsServerCreate = 360, + SysDnsServerUpdate = 361, + SysDnsServerDestroy = 362, + SysDnsServerQuery = 363, + SysDomainGet = 364, + SysDomainCreate = 365, + SysDomainUpdate = 366, + SysDomainDestroy = 367, + SysDomainQuery = 368, + SysDsnReportSettingsGet = 369, + SysDsnReportSettingsUpdate = 370, + SysEmailGet = 371, + SysEmailUpdate = 372, + SysEnterpriseGet = 373, + SysEnterpriseUpdate = 374, + SysEventTracingLevelGet = 375, + SysEventTracingLevelCreate = 376, + SysEventTracingLevelUpdate = 377, + SysEventTracingLevelDestroy = 378, + SysEventTracingLevelQuery = 379, + SysFileStorageGet = 380, + SysFileStorageUpdate = 381, + SysHttpGet = 382, + SysHttpUpdate = 383, + SysHttpFormGet = 384, + SysHttpFormUpdate = 385, + SysHttpLookupGet = 386, + SysHttpLookupCreate = 387, + SysHttpLookupUpdate = 388, + SysHttpLookupDestroy = 389, + SysHttpLookupQuery = 390, + SysImapGet = 391, + SysImapUpdate = 392, + SysInMemoryStoreGet = 393, + SysInMemoryStoreUpdate = 394, + SysJmapGet = 395, + SysJmapUpdate = 396, + SysLogGet = 397, + SysLogCreate = 398, + SysLogUpdate = 399, + SysLogDestroy = 400, + SysLogQuery = 401, + SysMailingListGet = 402, + SysMailingListCreate = 403, + SysMailingListUpdate = 404, + SysMailingListDestroy = 405, + SysMailingListQuery = 406, + SysMaskedEmailGet = 407, + SysMaskedEmailCreate = 408, + SysMaskedEmailUpdate = 409, + SysMaskedEmailDestroy = 410, + SysMaskedEmailQuery = 411, + SysMemoryLookupKeyGet = 412, + SysMemoryLookupKeyCreate = 413, + SysMemoryLookupKeyUpdate = 414, + SysMemoryLookupKeyDestroy = 415, + SysMemoryLookupKeyQuery = 416, + SysMemoryLookupKeyValueGet = 417, + SysMemoryLookupKeyValueCreate = 418, + SysMemoryLookupKeyValueUpdate = 419, + SysMemoryLookupKeyValueDestroy = 420, + SysMemoryLookupKeyValueQuery = 421, + SysMetricGet = 422, + SysMetricCreate = 423, + SysMetricUpdate = 424, + SysMetricDestroy = 425, + SysMetricQuery = 426, + SysMetricsGet = 427, + SysMetricsUpdate = 428, + SysMetricsStoreGet = 429, + SysMetricsStoreUpdate = 430, + SysMtaConnectionStrategyGet = 431, + SysMtaConnectionStrategyCreate = 432, + SysMtaConnectionStrategyUpdate = 433, + SysMtaConnectionStrategyDestroy = 434, + SysMtaConnectionStrategyQuery = 435, + SysMtaDeliveryScheduleGet = 436, + SysMtaDeliveryScheduleCreate = 437, + SysMtaDeliveryScheduleUpdate = 438, + SysMtaDeliveryScheduleDestroy = 439, + SysMtaDeliveryScheduleQuery = 440, + SysMtaExtensionsGet = 441, + SysMtaExtensionsUpdate = 442, + SysMtaHookGet = 443, + SysMtaHookCreate = 444, + SysMtaHookUpdate = 445, + SysMtaHookDestroy = 446, + SysMtaHookQuery = 447, + SysMtaInboundSessionGet = 448, + SysMtaInboundSessionUpdate = 449, + SysMtaInboundThrottleGet = 450, + SysMtaInboundThrottleCreate = 451, + SysMtaInboundThrottleUpdate = 452, + SysMtaInboundThrottleDestroy = 453, + SysMtaInboundThrottleQuery = 454, + SysMtaMilterGet = 455, + SysMtaMilterCreate = 456, + SysMtaMilterUpdate = 457, + SysMtaMilterDestroy = 458, + SysMtaMilterQuery = 459, + SysMtaOutboundStrategyGet = 460, + SysMtaOutboundStrategyUpdate = 461, + SysMtaOutboundThrottleGet = 462, + SysMtaOutboundThrottleCreate = 463, + SysMtaOutboundThrottleUpdate = 464, + SysMtaOutboundThrottleDestroy = 465, + SysMtaOutboundThrottleQuery = 466, + SysMtaQueueQuotaGet = 467, + SysMtaQueueQuotaCreate = 468, + SysMtaQueueQuotaUpdate = 469, + SysMtaQueueQuotaDestroy = 470, + SysMtaQueueQuotaQuery = 471, + SysMtaRouteGet = 472, + SysMtaRouteCreate = 473, + SysMtaRouteUpdate = 474, + SysMtaRouteDestroy = 475, + SysMtaRouteQuery = 476, + SysMtaStageAuthGet = 477, + SysMtaStageAuthUpdate = 478, + SysMtaStageConnectGet = 479, + SysMtaStageConnectUpdate = 480, + SysMtaStageDataGet = 481, + SysMtaStageDataUpdate = 482, + SysMtaStageEhloGet = 483, + SysMtaStageEhloUpdate = 484, + SysMtaStageMailGet = 485, + SysMtaStageMailUpdate = 486, + SysMtaStageRcptGet = 487, + SysMtaStageRcptUpdate = 488, + SysMtaStsGet = 489, + SysMtaStsUpdate = 490, + SysMtaTlsStrategyGet = 491, + SysMtaTlsStrategyCreate = 492, + SysMtaTlsStrategyUpdate = 493, + SysMtaTlsStrategyDestroy = 494, + SysMtaTlsStrategyQuery = 495, + SysMtaVirtualQueueGet = 496, + SysMtaVirtualQueueCreate = 497, + SysMtaVirtualQueueUpdate = 498, + SysMtaVirtualQueueDestroy = 499, + SysMtaVirtualQueueQuery = 500, + SysNetworkListenerGet = 501, + SysNetworkListenerCreate = 502, + SysNetworkListenerUpdate = 503, + SysNetworkListenerDestroy = 504, + SysNetworkListenerQuery = 505, + SysOAuthClientGet = 506, + SysOAuthClientCreate = 507, + SysOAuthClientUpdate = 508, + SysOAuthClientDestroy = 509, + SysOAuthClientQuery = 510, + SysOidcProviderGet = 511, + SysOidcProviderUpdate = 512, + SysPublicKeyGet = 513, + SysPublicKeyCreate = 514, + SysPublicKeyUpdate = 515, + SysPublicKeyDestroy = 516, + SysPublicKeyQuery = 517, + SysQueuedMessageGet = 518, + SysQueuedMessageCreate = 519, + SysQueuedMessageUpdate = 520, + SysQueuedMessageDestroy = 521, + SysQueuedMessageQuery = 522, + SysReportSettingsGet = 523, + SysReportSettingsUpdate = 524, + SysRoleGet = 525, + SysRoleCreate = 526, + SysRoleUpdate = 527, + SysRoleDestroy = 528, + SysRoleQuery = 529, + SysSearchGet = 530, + SysSearchUpdate = 531, + SysSearchStoreGet = 532, + SysSearchStoreUpdate = 533, + SysSecurityGet = 534, + SysSecurityUpdate = 535, + SysSenderAuthGet = 536, + SysSenderAuthUpdate = 537, + SysSharingGet = 538, + SysSharingUpdate = 539, + SysSieveSystemInterpreterGet = 540, + SysSieveSystemInterpreterUpdate = 541, + SysSieveSystemScriptGet = 542, + SysSieveSystemScriptCreate = 543, + SysSieveSystemScriptUpdate = 544, + SysSieveSystemScriptDestroy = 545, + SysSieveSystemScriptQuery = 546, + SysSieveUserInterpreterGet = 547, + SysSieveUserInterpreterUpdate = 548, + SysSieveUserScriptGet = 549, + SysSieveUserScriptCreate = 550, + SysSieveUserScriptUpdate = 551, + SysSieveUserScriptDestroy = 552, + SysSieveUserScriptQuery = 553, + SysSpamClassifierGet = 554, + SysSpamClassifierUpdate = 555, + SysSpamDnsblServerGet = 556, + SysSpamDnsblServerCreate = 557, + SysSpamDnsblServerUpdate = 558, + SysSpamDnsblServerDestroy = 559, + SysSpamDnsblServerQuery = 560, + SysSpamDnsblSettingsGet = 561, + SysSpamDnsblSettingsUpdate = 562, + SysSpamFileExtensionGet = 563, + SysSpamFileExtensionCreate = 564, + SysSpamFileExtensionUpdate = 565, + SysSpamFileExtensionDestroy = 566, + SysSpamFileExtensionQuery = 567, + SysSpamLlmGet = 568, + SysSpamLlmUpdate = 569, + SysSpamPyzorGet = 570, + SysSpamPyzorUpdate = 571, + SysSpamRuleGet = 572, + SysSpamRuleCreate = 573, + SysSpamRuleUpdate = 574, + SysSpamRuleDestroy = 575, + SysSpamRuleQuery = 576, + SysSpamSettingsGet = 577, + SysSpamSettingsUpdate = 578, + SysSpamTagGet = 579, + SysSpamTagCreate = 580, + SysSpamTagUpdate = 581, + SysSpamTagDestroy = 582, + SysSpamTagQuery = 583, + SysSpamTrainingSampleGet = 584, + SysSpamTrainingSampleCreate = 585, + SysSpamTrainingSampleUpdate = 586, + SysSpamTrainingSampleDestroy = 587, + SysSpamTrainingSampleQuery = 588, + SysSpfReportSettingsGet = 589, + SysSpfReportSettingsUpdate = 590, + SysStoreLookupGet = 591, + SysStoreLookupCreate = 592, + SysStoreLookupUpdate = 593, + SysStoreLookupDestroy = 594, + SysStoreLookupQuery = 595, + SysSystemSettingsGet = 596, + SysSystemSettingsUpdate = 597, + TaskIndexDocument = 598, + TaskUnindexDocument = 599, + TaskIndexTrace = 600, + TaskCalendarAlarmEmail = 601, + TaskCalendarAlarmNotification = 602, + TaskCalendarItipMessage = 603, + TaskMergeThreads = 604, + TaskDmarcReport = 605, + TaskTlsReport = 606, + TaskRestoreArchivedItem = 607, + TaskDestroyAccount = 608, + TaskAccountMaintenance = 609, + TaskTenantMaintenance = 610, + TaskStoreMaintenance = 611, + TaskSpamFilterMaintenance = 612, + TaskAcmeRenewal = 613, + TaskDkimManagement = 614, + TaskDnsManagement = 615, + SysTaskGet = 616, + SysTaskCreate = 617, + SysTaskUpdate = 618, + SysTaskDestroy = 619, + SysTaskQuery = 620, + SysTaskManagerGet = 621, + SysTaskManagerUpdate = 622, + SysTenantGet = 623, + SysTenantCreate = 624, + SysTenantUpdate = 625, + SysTenantDestroy = 626, + SysTenantQuery = 627, + SysTlsExternalReportGet = 628, + SysTlsExternalReportCreate = 629, + SysTlsExternalReportUpdate = 630, + SysTlsExternalReportDestroy = 631, + SysTlsExternalReportQuery = 632, + SysTlsInternalReportGet = 633, + SysTlsInternalReportCreate = 634, + SysTlsInternalReportUpdate = 635, + SysTlsInternalReportDestroy = 636, + SysTlsInternalReportQuery = 637, + SysTlsReportSettingsGet = 638, + SysTlsReportSettingsUpdate = 639, + SysTraceGet = 640, + SysTraceCreate = 641, + SysTraceUpdate = 642, + SysTraceDestroy = 643, + SysTraceQuery = 644, + SysTracerGet = 645, + SysTracerCreate = 646, + SysTracerUpdate = 647, + SysTracerDestroy = 648, + SysTracerQuery = 649, + SysTracingStoreGet = 650, + SysTracingStoreUpdate = 651, + SysWebDavGet = 652, + SysWebDavUpdate = 653, + SysWebHookGet = 654, + SysWebHookCreate = 655, + SysWebHookUpdate = 656, + SysWebHookDestroy = 657, + SysWebHookQuery = 658, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PermissionsType { + #[default] + Inherit = 0, + Merge = 1, + Replace = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PolicyEnforcement { + #[default] + Enforce = 0, + Testing = 1, + Disable = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PostgreSqlRecyclingMethod { + #[default] + Fast = 0, + Verified = 1, + Clean = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ProviderInfo { + #[default] + ProviderName = 0, + ProviderShortName = 1, + UserDocumentation = 2, + DeveloperDocumentation = 3, + ContactUri = 4, + LogoUrl = 5, + LogoWidth = 6, + LogoHeight = 7, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum PublicTextType { + #[default] + Text = 0, + EnvironmentVariable = 1, + File = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum QueueExpiryType { + #[default] + Ttl = 0, + Attempts = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum RecipientFlag { + #[default] + DsnSent = 0, + SpamPayload = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum RecipientStatusType { + #[default] + Scheduled = 0, + Completed = 1, + TemporaryFailure = 2, + PermanentFailure = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum RedisProtocol { + #[default] + Resp2 = 0, + Resp3 = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum RolesType { + #[default] + Default = 0, + Custom = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum S3StoreRegionType { + #[default] + UsEast1 = 0, + UsEast2 = 1, + UsWest1 = 2, + UsWest2 = 3, + CaCentral1 = 4, + AfSouth1 = 5, + ApEast1 = 6, + ApSouth1 = 7, + ApNortheast1 = 8, + ApNortheast2 = 9, + ApNortheast3 = 10, + ApSoutheast1 = 11, + ApSoutheast2 = 12, + CnNorth1 = 13, + CnNorthwest1 = 14, + EuNorth1 = 15, + EuCentral1 = 16, + EuCentral2 = 17, + EuWest1 = 18, + EuWest2 = 19, + EuWest3 = 20, + IlCentral1 = 21, + MeSouth1 = 22, + SaEast1 = 23, + DoNyc3 = 24, + DoAms3 = 25, + DoSgp1 = 26, + DoFra1 = 27, + Yandex = 28, + WaUsEast1 = 29, + WaUsEast2 = 30, + WaUsCentral1 = 31, + WaUsWest1 = 32, + WaCaCentral1 = 33, + WaEuCentral1 = 34, + WaEuCentral2 = 35, + WaEuWest1 = 36, + WaEuWest2 = 37, + WaApNortheast1 = 38, + WaApNortheast2 = 39, + WaApSoutheast1 = 40, + WaApSoutheast2 = 41, + Custom = 42, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchCalendarField { + #[default] + Title = 0, + Description = 1, + Location = 2, + Owner = 3, + Attendee = 4, + Start = 5, + Uid = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchContactField { + #[default] + Member = 0, + Kind = 1, + Name = 2, + Nickname = 3, + Organization = 4, + Email = 5, + Phone = 6, + OnlineService = 7, + Address = 8, + Note = 9, + Uid = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchEmailField { + #[default] + From = 0, + To = 1, + Cc = 2, + Bcc = 3, + Subject = 4, + Body = 5, + Attachment = 6, + ReceivedAt = 7, + SentAt = 8, + Size = 9, + HasAttachment = 10, + Headers = 11, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchFileField { + #[default] + Name = 0, + Content = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchStoreType { + #[default] + Default = 0, + ElasticSearch = 1, + Meilisearch = 2, + FoundationDb = 3, + PostgreSql = 4, + MySql = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SearchTracingField { + #[default] + EventType = 0, + QueueId = 1, + Keywords = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SecretKeyOptionalType { + #[default] + None = 0, + Value = 1, + EnvironmentVariable = 2, + File = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SecretKeyType { + #[default] + Value = 0, + EnvironmentVariable = 1, + File = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SecretTextOptionalType { + #[default] + None = 0, + Text = 1, + EnvironmentVariable = 2, + File = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SecretTextType { + #[default] + Text = 0, + EnvironmentVariable = 1, + File = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ServiceProtocol { + #[default] + Jmap = 0, + Imap = 1, + Pop3 = 2, + Smtp = 3, + Caldav = 4, + Carddav = 5, + Webdav = 6, + Managesieve = 7, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SieveCapability { + #[default] + Envelope = 0, + EnvelopeDsn = 1, + EnvelopeDeliverby = 2, + Fileinto = 3, + EncodedCharacter = 4, + ComparatorElbonia = 5, + ComparatorIOctet = 6, + ComparatorIAsciiCasemap = 7, + ComparatorIAsciiNumeric = 8, + Body = 9, + Convert = 10, + Copy = 11, + Relational = 12, + Date = 13, + Index = 14, + Duplicate = 15, + Variables = 16, + Editheader = 17, + Foreverypart = 18, + Mime = 19, + Replace = 20, + Enclose = 21, + Extracttext = 22, + Enotify = 23, + RedirectDsn = 24, + RedirectDeliverby = 25, + Environment = 26, + Reject = 27, + Ereject = 28, + Extlists = 29, + Subaddress = 30, + Vacation = 31, + VacationSeconds = 32, + Fcc = 33, + Mailbox = 34, + Mailboxid = 35, + Mboxmetadata = 36, + Servermetadata = 37, + SpecialUse = 38, + Imap4flags = 39, + Ihave = 40, + Imapsieve = 41, + Include = 42, + Regex = 43, + Spamtest = 44, + Spamtestplus = 45, + Virustest = 46, + VndStalwartWhile = 47, + VndStalwartExpressions = 48, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum Sig0Algorithm { + #[default] + EcdsaP256Sha256 = 0, + EcdsaP384Sha384 = 1, + Ed25519 = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamClassifierModelType { + #[default] + FtrlFh = 0, + FtrlCcfh = 1, + Disabled = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamClassifyParameters { + #[default] + Bit7 = 0, + Bit8Mime8BitMIMEMessageContent = 1, + BinaryMime = 2, + SmtpUtf8 = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamClassifyResult { + #[default] + Spam = 0, + Ham = 1, + Reject = 2, + Discard = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamClassifyTagDisposition { + #[default] + Score = 0, + Reject = 1, + Discard = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamDnsblServerType { + #[default] + Any = 0, + Url = 1, + Domain = 2, + Email = 3, + Ip = 4, + Header = 5, + Body = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamLlmType { + #[default] + Disable = 0, + Enable = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamRuleType { + #[default] + Any = 0, + Url = 1, + Domain = 2, + Email = 3, + Ip = 4, + Header = 5, + Body = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpamTagType { + #[default] + Score = 0, + Discard = 1, + Reject = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpecialUse { + #[default] + Inbox = 0, + Trash = 1, + Junk = 2, + Drafts = 3, + Archive = 4, + Sent = 5, + Shared = 6, + Important = 7, + Memos = 8, + Scheduled = 9, + Snoozed = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpfAuthResult { + #[default] + None = 0, + Neutral = 1, + Pass = 2, + Fail = 3, + SoftFail = 4, + TempError = 5, + PermError = 6, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SpfDomainScope { + #[default] + Helo = 0, + MailFrom = 1, + Unspecified = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SqlAuthStoreType { + #[default] + Default = 0, + PostgreSql = 1, + MySql = 2, + Sqlite = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum StorageQuota { + #[default] + MaxEmails = 0, + MaxMailboxes = 1, + MaxEmailSubmissions = 2, + MaxEmailIdentities = 3, + MaxParticipantIdentities = 4, + MaxSieveScripts = 5, + MaxPushSubscriptions = 6, + MaxCalendars = 7, + MaxCalendarEvents = 8, + MaxCalendarEventNotifications = 9, + MaxAddressBooks = 10, + MaxContactCards = 11, + MaxFiles = 12, + MaxFolders = 13, + MaxMaskedAddresses = 14, + MaxAppPasswords = 15, + MaxApiKeys = 16, + MaxPublicKeys = 17, + MaxDiskQuota = 18, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum SubAddressingType { + #[default] + Enabled = 0, + Custom = 1, + Disabled = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskAccountMaintenanceType { + #[default] + Purge = 0, + Reindex = 1, + RecalculateImapUid = 2, + RecalculateQuota = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskRetryStrategyType { + #[default] + ExponentialBackoff = 0, + FixedDelay = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskSpamFilterMaintenanceType { + #[default] + Train = 0, + Retrain = 1, + Abort = 2, + Reset = 3, + UpdateRules = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskStatusType { + #[default] + Pending = 0, + Retry = 1, + Failed = 2, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskStoreMaintenanceType { + #[default] + ReindexAccounts = 0, + ReindexTelemetry = 1, + PurgeAccounts = 2, + PurgeData = 3, + PurgeBlob = 4, + ResetRateLimiters = 5, + ResetUserQuotas = 6, + ResetTenantQuotas = 7, + ResetBlobQuotas = 8, + RemoveAuthTokens = 9, + RemoveLockQueueMessage = 10, + RemoveLockTask = 11, + RemoveLockDav = 12, + RemoveSieveId = 13, + RemoveGreylist = 14, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskTenantMaintenanceType { + #[default] + RecalculateQuota = 0, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TaskType { + #[default] + IndexDocument = 0, + UnindexDocument = 1, + IndexTrace = 2, + CalendarAlarmEmail = 3, + CalendarAlarmNotification = 4, + CalendarItipMessage = 5, + MergeThreads = 6, + DmarcReport = 7, + TlsReport = 8, + RestoreArchivedItem = 9, + DestroyAccount = 10, + AccountMaintenance = 11, + TenantMaintenance = 12, + StoreMaintenance = 13, + SpamFilterMaintenance = 14, + AcmeRenewal = 15, + DkimManagement = 16, + DnsManagement = 17, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TenantStorageQuota { + #[default] + MaxAccounts = 0, + MaxGroups = 1, + MaxDomains = 2, + MaxMailingLists = 3, + MaxRoles = 4, + MaxOauthClients = 5, + MaxDkimKeys = 6, + MaxDnsServers = 7, + MaxDirectories = 8, + MaxAcmeProviders = 9, + MaxDiskQuota = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TimeZone { + #[default] + AfricaAbidjan = 0, + AfricaAccra = 1, + AfricaAddisAbaba = 2, + AfricaAlgiers = 3, + AfricaAsmara = 4, + AfricaAsmera = 5, + AfricaBamako = 6, + AfricaBangui = 7, + AfricaBanjul = 8, + AfricaBissau = 9, + AfricaBlantyre = 10, + AfricaBrazzaville = 11, + AfricaBujumbura = 12, + AfricaCairo = 13, + AfricaCasablanca = 14, + AfricaCeuta = 15, + AfricaConakry = 16, + AfricaDakar = 17, + AfricaDarEsSalaam = 18, + AfricaDjibouti = 19, + AfricaDouala = 20, + AfricaElAaiun = 21, + AfricaFreetown = 22, + AfricaGaborone = 23, + AfricaHarare = 24, + AfricaJohannesburg = 25, + AfricaJuba = 26, + AfricaKampala = 27, + AfricaKhartoum = 28, + AfricaKigali = 29, + AfricaKinshasa = 30, + AfricaLagos = 31, + AfricaLibreville = 32, + AfricaLome = 33, + AfricaLuanda = 34, + AfricaLubumbashi = 35, + AfricaLusaka = 36, + AfricaMalabo = 37, + AfricaMaputo = 38, + AfricaMaseru = 39, + AfricaMbabane = 40, + AfricaMogadishu = 41, + AfricaMonrovia = 42, + AfricaNairobi = 43, + AfricaNdjamena = 44, + AfricaNiamey = 45, + AfricaNouakchott = 46, + AfricaOuagadougou = 47, + AfricaPortoNovo = 48, + AfricaSaoTome = 49, + AfricaTimbuktu = 50, + AfricaTripoli = 51, + AfricaTunis = 52, + AfricaWindhoek = 53, + AmericaAdak = 54, + AmericaAnchorage = 55, + AmericaAnguilla = 56, + AmericaAntigua = 57, + AmericaAraguaina = 58, + AmericaArgentinaBuenosAires = 59, + AmericaArgentinaCatamarca = 60, + AmericaArgentinaComodRivadavia = 61, + AmericaArgentinaCordoba = 62, + AmericaArgentinaJujuy = 63, + AmericaArgentinaLaRioja = 64, + AmericaArgentinaMendoza = 65, + AmericaArgentinaRioGallegos = 66, + AmericaArgentinaSalta = 67, + AmericaArgentinaSanJuan = 68, + AmericaArgentinaSanLuis = 69, + AmericaArgentinaTucuman = 70, + AmericaArgentinaUshuaia = 71, + AmericaAruba = 72, + AmericaAsuncion = 73, + AmericaAtikokan = 74, + AmericaAtka = 75, + AmericaBahia = 76, + AmericaBahiaBanderas = 77, + AmericaBarbados = 78, + AmericaBelem = 79, + AmericaBelize = 80, + AmericaBlancSablon = 81, + AmericaBoaVista = 82, + AmericaBogota = 83, + AmericaBoise = 84, + AmericaBuenosAires = 85, + AmericaCambridgeBay = 86, + AmericaCampoGrande = 87, + AmericaCancun = 88, + AmericaCaracas = 89, + AmericaCatamarca = 90, + AmericaCayenne = 91, + AmericaCayman = 92, + AmericaChicago = 93, + AmericaChihuahua = 94, + AmericaCiudadJuarez = 95, + AmericaCoralHarbour = 96, + AmericaCordoba = 97, + AmericaCostaRica = 98, + AmericaCoyhaique = 99, + AmericaCreston = 100, + AmericaCuiaba = 101, + AmericaCuracao = 102, + AmericaDanmarkshavn = 103, + AmericaDawson = 104, + AmericaDawsonCreek = 105, + AmericaDenver = 106, + AmericaDetroit = 107, + AmericaDominica = 108, + AmericaEdmonton = 109, + AmericaEirunepe = 110, + AmericaElSalvador = 111, + AmericaEnsenada = 112, + AmericaFortNelson = 113, + AmericaFortWayne = 114, + AmericaFortaleza = 115, + AmericaGlaceBay = 116, + AmericaGodthab = 117, + AmericaGooseBay = 118, + AmericaGrandTurk = 119, + AmericaGrenada = 120, + AmericaGuadeloupe = 121, + AmericaGuatemala = 122, + AmericaGuayaquil = 123, + AmericaGuyana = 124, + AmericaHalifax = 125, + AmericaHavana = 126, + AmericaHermosillo = 127, + AmericaIndianaIndianapolis = 128, + AmericaIndianaKnox = 129, + AmericaIndianaMarengo = 130, + AmericaIndianaPetersburg = 131, + AmericaIndianaTellCity = 132, + AmericaIndianaVevay = 133, + AmericaIndianaVincennes = 134, + AmericaIndianaWinamac = 135, + AmericaIndianapolis = 136, + AmericaInuvik = 137, + AmericaIqaluit = 138, + AmericaJamaica = 139, + AmericaJujuy = 140, + AmericaJuneau = 141, + AmericaKentuckyLouisville = 142, + AmericaKentuckyMonticello = 143, + AmericaKnoxIN = 144, + AmericaKralendijk = 145, + AmericaLaPaz = 146, + AmericaLima = 147, + AmericaLosAngeles = 148, + AmericaLouisville = 149, + AmericaLowerPrinces = 150, + AmericaMaceio = 151, + AmericaManagua = 152, + AmericaManaus = 153, + AmericaMarigot = 154, + AmericaMartinique = 155, + AmericaMatamoros = 156, + AmericaMazatlan = 157, + AmericaMendoza = 158, + AmericaMenominee = 159, + AmericaMerida = 160, + AmericaMetlakatla = 161, + AmericaMexicoCity = 162, + AmericaMiquelon = 163, + AmericaMoncton = 164, + AmericaMonterrey = 165, + AmericaMontevideo = 166, + AmericaMontreal = 167, + AmericaMontserrat = 168, + AmericaNassau = 169, + AmericaNewYork = 170, + AmericaNipigon = 171, + AmericaNome = 172, + AmericaNoronha = 173, + AmericaNorthDakotaBeulah = 174, + AmericaNorthDakotaCenter = 175, + AmericaNorthDakotaNewSalem = 176, + AmericaNuuk = 177, + AmericaOjinaga = 178, + AmericaPanama = 179, + AmericaPangnirtung = 180, + AmericaParamaribo = 181, + AmericaPhoenix = 182, + AmericaPortAuPrince = 183, + AmericaPortOfSpain = 184, + AmericaPortoAcre = 185, + AmericaPortoVelho = 186, + AmericaPuertoRico = 187, + AmericaPuntaArenas = 188, + AmericaRainyRiver = 189, + AmericaRankinInlet = 190, + AmericaRecife = 191, + AmericaRegina = 192, + AmericaResolute = 193, + AmericaRioBranco = 194, + AmericaRosario = 195, + AmericaSantaIsabel = 196, + AmericaSantarem = 197, + AmericaSantiago = 198, + AmericaSantoDomingo = 199, + AmericaSaoPaulo = 200, + AmericaScoresbysund = 201, + AmericaShiprock = 202, + AmericaSitka = 203, + AmericaStBarthelemy = 204, + AmericaStJohns = 205, + AmericaStKitts = 206, + AmericaStLucia = 207, + AmericaStThomas = 208, + AmericaStVincent = 209, + AmericaSwiftCurrent = 210, + AmericaTegucigalpa = 211, + AmericaThule = 212, + AmericaThunderBay = 213, + AmericaTijuana = 214, + AmericaToronto = 215, + AmericaTortola = 216, + AmericaVancouver = 217, + AmericaVirgin = 218, + AmericaWhitehorse = 219, + AmericaWinnipeg = 220, + AmericaYakutat = 221, + AmericaYellowknife = 222, + AntarcticaCasey = 223, + AntarcticaDavis = 224, + AntarcticaDumontDUrville = 225, + AntarcticaMacquarie = 226, + AntarcticaMawson = 227, + AntarcticaMcMurdo = 228, + AntarcticaPalmer = 229, + AntarcticaRothera = 230, + AntarcticaSouthPole = 231, + AntarcticaSyowa = 232, + AntarcticaTroll = 233, + AntarcticaVostok = 234, + ArcticLongyearbyen = 235, + AsiaAden = 236, + AsiaAlmaty = 237, + AsiaAmman = 238, + AsiaAnadyr = 239, + AsiaAqtau = 240, + AsiaAqtobe = 241, + AsiaAshgabat = 242, + AsiaAshkhabad = 243, + AsiaAtyrau = 244, + AsiaBaghdad = 245, + AsiaBahrain = 246, + AsiaBaku = 247, + AsiaBangkok = 248, + AsiaBarnaul = 249, + AsiaBeirut = 250, + AsiaBishkek = 251, + AsiaBrunei = 252, + AsiaCalcutta = 253, + AsiaChita = 254, + AsiaChoibalsan = 255, + AsiaChongqing = 256, + AsiaChungking = 257, + AsiaColombo = 258, + AsiaDacca = 259, + AsiaDamascus = 260, + AsiaDhaka = 261, + AsiaDili = 262, + AsiaDubai = 263, + AsiaDushanbe = 264, + AsiaFamagusta = 265, + AsiaGaza = 266, + AsiaHarbin = 267, + AsiaHebron = 268, + AsiaHoChiMinh = 269, + AsiaHongKong = 270, + AsiaHovd = 271, + AsiaIrkutsk = 272, + AsiaIstanbul = 273, + AsiaJakarta = 274, + AsiaJayapura = 275, + AsiaJerusalem = 276, + AsiaKabul = 277, + AsiaKamchatka = 278, + AsiaKarachi = 279, + AsiaKashgar = 280, + AsiaKathmandu = 281, + AsiaKatmandu = 282, + AsiaKhandyga = 283, + AsiaKolkata = 284, + AsiaKrasnoyarsk = 285, + AsiaKualaLumpur = 286, + AsiaKuching = 287, + AsiaKuwait = 288, + AsiaMacao = 289, + AsiaMacau = 290, + AsiaMagadan = 291, + AsiaMakassar = 292, + AsiaManila = 293, + AsiaMuscat = 294, + AsiaNicosia = 295, + AsiaNovokuznetsk = 296, + AsiaNovosibirsk = 297, + AsiaOmsk = 298, + AsiaOral = 299, + AsiaPhnomPenh = 300, + AsiaPontianak = 301, + AsiaPyongyang = 302, + AsiaQatar = 303, + AsiaQostanay = 304, + AsiaQyzylorda = 305, + AsiaRangoon = 306, + AsiaRiyadh = 307, + AsiaSaigon = 308, + AsiaSakhalin = 309, + AsiaSamarkand = 310, + AsiaSeoul = 311, + AsiaShanghai = 312, + AsiaSingapore = 313, + AsiaSrednekolymsk = 314, + AsiaTaipei = 315, + AsiaTashkent = 316, + AsiaTbilisi = 317, + AsiaTehran = 318, + AsiaTelAviv = 319, + AsiaThimbu = 320, + AsiaThimphu = 321, + AsiaTokyo = 322, + AsiaTomsk = 323, + AsiaUjungPandang = 324, + AsiaUlaanbaatar = 325, + AsiaUlanBator = 326, + AsiaUrumqi = 327, + AsiaUstNera = 328, + AsiaVientiane = 329, + AsiaVladivostok = 330, + AsiaYakutsk = 331, + AsiaYangon = 332, + AsiaYekaterinburg = 333, + AsiaYerevan = 334, + AtlanticAzores = 335, + AtlanticBermuda = 336, + AtlanticCanary = 337, + AtlanticCapeVerde = 338, + AtlanticFaeroe = 339, + AtlanticFaroe = 340, + AtlanticJanMayen = 341, + AtlanticMadeira = 342, + AtlanticReykjavik = 343, + AtlanticSouthGeorgia = 344, + AtlanticStHelena = 345, + AtlanticStanley = 346, + AustraliaACT = 347, + AustraliaAdelaide = 348, + AustraliaBrisbane = 349, + AustraliaBrokenHill = 350, + AustraliaCanberra = 351, + AustraliaCurrie = 352, + AustraliaDarwin = 353, + AustraliaEucla = 354, + AustraliaHobart = 355, + AustraliaLHI = 356, + AustraliaLindeman = 357, + AustraliaLordHowe = 358, + AustraliaMelbourne = 359, + AustraliaNSW = 360, + AustraliaNorth = 361, + AustraliaPerth = 362, + AustraliaQueensland = 363, + AustraliaSouth = 364, + AustraliaSydney = 365, + AustraliaTasmania = 366, + AustraliaVictoria = 367, + AustraliaWest = 368, + AustraliaYancowinna = 369, + BrazilAcre = 370, + BrazilDeNoronha = 371, + BrazilEast = 372, + BrazilWest = 373, + CET = 374, + CST6CDT = 375, + CanadaAtlantic = 376, + CanadaCentral = 377, + CanadaEastern = 378, + CanadaMountain = 379, + CanadaNewfoundland = 380, + CanadaPacific = 381, + CanadaSaskatchewan = 382, + CanadaYukon = 383, + ChileContinental = 384, + ChileEasterIsland = 385, + Cuba = 386, + EET = 387, + EST = 388, + EST5EDT = 389, + Egypt = 390, + Eire = 391, + EtcGMT = 392, + EtcGMTPlus0 = 393, + EtcGMTPlus1 = 394, + EtcGMTPlus10 = 395, + EtcGMTPlus11 = 396, + EtcGMTPlus12 = 397, + EtcGMTPlus2 = 398, + EtcGMTPlus3 = 399, + EtcGMTPlus4 = 400, + EtcGMTPlus5 = 401, + EtcGMTPlus6 = 402, + EtcGMTPlus7 = 403, + EtcGMTPlus8 = 404, + EtcGMTPlus9 = 405, + EtcGMTMinus0 = 406, + EtcGMTMinus1 = 407, + EtcGMTMinus10 = 408, + EtcGMTMinus11 = 409, + EtcGMTMinus12 = 410, + EtcGMTMinus13 = 411, + EtcGMTMinus14 = 412, + EtcGMTMinus2 = 413, + EtcGMTMinus3 = 414, + EtcGMTMinus4 = 415, + EtcGMTMinus5 = 416, + EtcGMTMinus6 = 417, + EtcGMTMinus7 = 418, + EtcGMTMinus8 = 419, + EtcGMTMinus9 = 420, + EtcGMT0 = 421, + EtcGreenwich = 422, + EtcUCT = 423, + EtcUTC = 424, + EtcUniversal = 425, + EtcZulu = 426, + EuropeAmsterdam = 427, + EuropeAndorra = 428, + EuropeAstrakhan = 429, + EuropeAthens = 430, + EuropeBelfast = 431, + EuropeBelgrade = 432, + EuropeBerlin = 433, + EuropeBratislava = 434, + EuropeBrussels = 435, + EuropeBucharest = 436, + EuropeBudapest = 437, + EuropeBusingen = 438, + EuropeChisinau = 439, + EuropeCopenhagen = 440, + EuropeDublin = 441, + EuropeGibraltar = 442, + EuropeGuernsey = 443, + EuropeHelsinki = 444, + EuropeIsleOfMan = 445, + EuropeIstanbul = 446, + EuropeJersey = 447, + EuropeKaliningrad = 448, + EuropeKiev = 449, + EuropeKirov = 450, + EuropeKyiv = 451, + EuropeLisbon = 452, + EuropeLjubljana = 453, + EuropeLondon = 454, + EuropeLuxembourg = 455, + EuropeMadrid = 456, + EuropeMalta = 457, + EuropeMariehamn = 458, + EuropeMinsk = 459, + EuropeMonaco = 460, + EuropeMoscow = 461, + EuropeNicosia = 462, + EuropeOslo = 463, + EuropeParis = 464, + EuropePodgorica = 465, + EuropePrague = 466, + EuropeRiga = 467, + EuropeRome = 468, + EuropeSamara = 469, + EuropeSanMarino = 470, + EuropeSarajevo = 471, + EuropeSaratov = 472, + EuropeSimferopol = 473, + EuropeSkopje = 474, + EuropeSofia = 475, + EuropeStockholm = 476, + EuropeTallinn = 477, + EuropeTirane = 478, + EuropeTiraspol = 479, + EuropeUlyanovsk = 480, + EuropeUzhgorod = 481, + EuropeVaduz = 482, + EuropeVatican = 483, + EuropeVienna = 484, + EuropeVilnius = 485, + EuropeVolgograd = 486, + EuropeWarsaw = 487, + EuropeZagreb = 488, + EuropeZaporozhye = 489, + EuropeZurich = 490, + Factory = 491, + GB = 492, + GBEire = 493, + GMT = 494, + GMTPlus0 = 495, + GMTMinus0 = 496, + GMT0 = 497, + Greenwich = 498, + HST = 499, + Hongkong = 500, + Iceland = 501, + IndianAntananarivo = 502, + IndianChagos = 503, + IndianChristmas = 504, + IndianCocos = 505, + IndianComoro = 506, + IndianKerguelen = 507, + IndianMahe = 508, + IndianMaldives = 509, + IndianMauritius = 510, + IndianMayotte = 511, + IndianReunion = 512, + Iran = 513, + Israel = 514, + Jamaica = 515, + Japan = 516, + Kwajalein = 517, + Libya = 518, + MET = 519, + MST = 520, + MST7MDT = 521, + MexicoBajaNorte = 522, + MexicoBajaSur = 523, + MexicoGeneral = 524, + NZ = 525, + NZCHAT = 526, + Navajo = 527, + PRC = 528, + PST8PDT = 529, + PacificApia = 530, + PacificAuckland = 531, + PacificBougainville = 532, + PacificChatham = 533, + PacificChuuk = 534, + PacificEaster = 535, + PacificEfate = 536, + PacificEnderbury = 537, + PacificFakaofo = 538, + PacificFiji = 539, + PacificFunafuti = 540, + PacificGalapagos = 541, + PacificGambier = 542, + PacificGuadalcanal = 543, + PacificGuam = 544, + PacificHonolulu = 545, + PacificJohnston = 546, + PacificKanton = 547, + PacificKiritimati = 548, + PacificKosrae = 549, + PacificKwajalein = 550, + PacificMajuro = 551, + PacificMarquesas = 552, + PacificMidway = 553, + PacificNauru = 554, + PacificNiue = 555, + PacificNorfolk = 556, + PacificNoumea = 557, + PacificPagoPago = 558, + PacificPalau = 559, + PacificPitcairn = 560, + PacificPohnpei = 561, + PacificPonape = 562, + PacificPortMoresby = 563, + PacificRarotonga = 564, + PacificSaipan = 565, + PacificSamoa = 566, + PacificTahiti = 567, + PacificTarawa = 568, + PacificTongatapu = 569, + PacificTruk = 570, + PacificWake = 571, + PacificWallis = 572, + PacificYap = 573, + Poland = 574, + Portugal = 575, + ROC = 576, + ROK = 577, + Singapore = 578, + Turkey = 579, + UCT = 580, + USAlaska = 581, + USAleutian = 582, + USArizona = 583, + USCentral = 584, + USEastIndiana = 585, + USEastern = 586, + USHawaii = 587, + USIndianaStarke = 588, + USMichigan = 589, + USMountain = 590, + USPacific = 591, + USSamoa = 592, + UTC = 593, + Universal = 594, + WSU = 595, + WET = 596, + Zulu = 597, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TlsCipherSuite { + #[default] + Tls13Aes256GcmSha384 = 0, + Tls13Aes128GcmSha256 = 1, + Tls13Chacha20Poly1305Sha256 = 2, + TlsEcdheEcdsaWithAes256GcmSha384 = 3, + TlsEcdheEcdsaWithAes128GcmSha256 = 4, + TlsEcdheEcdsaWithChacha20Poly1305Sha256 = 5, + TlsEcdheRsaWithAes256GcmSha384 = 6, + TlsEcdheRsaWithAes128GcmSha256 = 7, + TlsEcdheRsaWithChacha20Poly1305Sha256 = 8, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TlsPolicyType { + #[default] + Tlsa = 0, + Sts = 1, + NoPolicyFound = 2, + Other = 3, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TlsResultType { + #[default] + StartTlsNotSupported = 0, + CertificateHostMismatch = 1, + CertificateExpired = 2, + CertificateNotTrusted = 3, + ValidationFailure = 4, + TlsaInvalid = 5, + DnssecInvalid = 6, + DaneRequired = 7, + StsPolicyFetchError = 8, + StsPolicyInvalid = 9, + StsWebpkiInvalid = 10, + Other = 11, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TlsVersion { + #[default] + Tls12 = 0, + Tls13 = 1, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TraceValueType { + #[default] + String = 0, + UnsignedInt = 1, + Integer = 2, + Boolean = 3, + Float = 4, + UTCDateTime = 5, + Duration = 6, + IpAddr = 7, + List = 8, + Event = 9, + Null = 10, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TracerType { + #[default] + Log = 0, + Stdout = 1, + Journal = 2, + OtelHttp = 3, + OtelGrpc = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TracingLevel { + #[default] + Error = 0, + Warn = 1, + Info = 2, + Debug = 3, + Trace = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TracingLevelOpt { + #[default] + Disable = 0, + Error = 1, + Warn = 2, + Info = 3, + Debug = 4, + Trace = 5, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TracingStoreType { + #[default] + Disabled = 0, + Default = 1, + FoundationDb = 2, + PostgreSql = 3, + MySql = 4, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum TsigAlgorithm { + #[default] + HmacMd5 = 0, + Gss = 1, + HmacSha1 = 2, + HmacSha224 = 3, + HmacSha256 = 4, + HmacSha256128 = 5, + HmacSha384 = 6, + HmacSha384192 = 7, + HmacSha512 = 8, + HmacSha512256 = 9, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum UserRolesType { + #[default] + User = 0, + Admin = 1, + Custom = 2, +} + +pub static HTTP_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Listener, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemotePort, + ExpressionVariable::LocalIp, + ExpressionVariable::LocalPort, + ExpressionVariable::Protocol, + ExpressionVariable::IsTls, + ExpressionVariable::Url, + ExpressionVariable::Path, + ExpressionVariable::Headers, + ExpressionVariable::Method, +]; + +pub static MTA_CONNECTION_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Listener, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemotePort, + ExpressionVariable::LocalIp, + ExpressionVariable::LocalPort, + ExpressionVariable::Protocol, + ExpressionVariable::IsTls, + ExpressionVariable::Asn, + ExpressionVariable::Country, +]; + +pub static MTA_EHLO_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Listener, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemotePort, + ExpressionVariable::LocalIp, + ExpressionVariable::LocalPort, + ExpressionVariable::Protocol, + ExpressionVariable::IsTls, + ExpressionVariable::HeloDomain, + ExpressionVariable::Asn, + ExpressionVariable::Country, +]; + +pub static MTA_MAIL_FROM_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Listener, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemotePort, + ExpressionVariable::LocalIp, + ExpressionVariable::LocalPort, + ExpressionVariable::Protocol, + ExpressionVariable::IsTls, + ExpressionVariable::Sender, + ExpressionVariable::SenderDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, +]; + +pub static MTA_QUEUE_HOST_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Sender, + ExpressionVariable::SenderDomain, + ExpressionVariable::RcptDomain, + ExpressionVariable::Rcpt, + ExpressionVariable::Recipients, + ExpressionVariable::Mx, + ExpressionVariable::Priority, + ExpressionVariable::RemoteIp, + ExpressionVariable::LocalIp, + ExpressionVariable::RetryNum, + ExpressionVariable::NotifyNum, + ExpressionVariable::ExpiresIn, + ExpressionVariable::LastStatus, + ExpressionVariable::LastError, + ExpressionVariable::QueueName, + ExpressionVariable::QueueAge, + ExpressionVariable::ReceivedFromIp, + ExpressionVariable::ReceivedViaPort, + ExpressionVariable::Source, + ExpressionVariable::Size, +]; + +pub static MTA_QUEUE_RCPT_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Rcpt, + ExpressionVariable::RcptDomain, + ExpressionVariable::Recipients, + ExpressionVariable::Sender, + ExpressionVariable::SenderDomain, + ExpressionVariable::Priority, + ExpressionVariable::RetryNum, + ExpressionVariable::NotifyNum, + ExpressionVariable::ExpiresIn, + ExpressionVariable::LastStatus, + ExpressionVariable::LastError, + ExpressionVariable::QueueName, + ExpressionVariable::QueueAge, + ExpressionVariable::ReceivedFromIp, + ExpressionVariable::ReceivedViaPort, + ExpressionVariable::Source, + ExpressionVariable::Size, +]; + +pub static MTA_QUEUE_SENDER_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Sender, + ExpressionVariable::SenderDomain, + ExpressionVariable::Priority, + ExpressionVariable::RetryNum, + ExpressionVariable::NotifyNum, + ExpressionVariable::ExpiresIn, + ExpressionVariable::LastStatus, + ExpressionVariable::LastError, +]; + +pub static MTA_RCPT_DOMAIN_VARIABLE: &[ExpressionVariable] = &[ExpressionVariable::RcptDomain]; + +pub static MTA_RCPT_TO_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Sender, + ExpressionVariable::SenderDomain, + ExpressionVariable::Recipients, + ExpressionVariable::Rcpt, + ExpressionVariable::RcptDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Listener, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemotePort, + ExpressionVariable::LocalIp, + ExpressionVariable::LocalPort, + ExpressionVariable::Protocol, + ExpressionVariable::IsTls, + ExpressionVariable::Priority, + ExpressionVariable::HeloDomain, + ExpressionVariable::Asn, + ExpressionVariable::Country, +]; + +pub static MTA_RCPT_VARIABLE: &[ExpressionVariable] = &[ExpressionVariable::Rcpt]; + +pub static SPAM_DEFAULT_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static SPAM_EMAIL_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Email, + ExpressionVariable::Value, + ExpressionVariable::Name, + ExpressionVariable::Local, + ExpressionVariable::Domain, + ExpressionVariable::Sld, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static SPAM_GENERIC_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Value, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static SPAM_HEADER_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Name, + ExpressionVariable::NameLower, + ExpressionVariable::Value, + ExpressionVariable::ValueLower, + ExpressionVariable::Attributes, + ExpressionVariable::Raw, + ExpressionVariable::RawLower, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static SPAM_IP_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Ip, + ExpressionVariable::Value, + ExpressionVariable::ReverseIp, + ExpressionVariable::IpReverse, + ExpressionVariable::Octets, + ExpressionVariable::IsV4, + ExpressionVariable::IsV6, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static SPAM_URL_VARIABLE: &[ExpressionVariable] = &[ + ExpressionVariable::Url, + ExpressionVariable::Value, + ExpressionVariable::PathQuery, + ExpressionVariable::Path, + ExpressionVariable::Query, + ExpressionVariable::Scheme, + ExpressionVariable::Authority, + ExpressionVariable::Host, + ExpressionVariable::Sld, + ExpressionVariable::Port, + ExpressionVariable::RemoteIp, + ExpressionVariable::RemoteIpPtr, + ExpressionVariable::HeloDomain, + ExpressionVariable::AuthenticatedAs, + ExpressionVariable::Asn, + ExpressionVariable::Country, + ExpressionVariable::IsTls, + ExpressionVariable::EnvFrom, + ExpressionVariable::EnvFromLocal, + ExpressionVariable::EnvFromDomain, + ExpressionVariable::EnvTo, + ExpressionVariable::From, + ExpressionVariable::FromName, + ExpressionVariable::FromLocal, + ExpressionVariable::FromDomain, + ExpressionVariable::ReplyTo, + ExpressionVariable::ReplyToName, + ExpressionVariable::ReplyToLocal, + ExpressionVariable::ReplyToDomain, + ExpressionVariable::To, + ExpressionVariable::ToName, + ExpressionVariable::ToLocal, + ExpressionVariable::ToDomain, + ExpressionVariable::Cc, + ExpressionVariable::CcName, + ExpressionVariable::CcLocal, + ExpressionVariable::CcDomain, + ExpressionVariable::Bcc, + ExpressionVariable::BccName, + ExpressionVariable::BccLocal, + ExpressionVariable::BccDomain, + ExpressionVariable::Body, + ExpressionVariable::BodyText, + ExpressionVariable::BodyHtml, + ExpressionVariable::BodyWords, + ExpressionVariable::BodyRaw, + ExpressionVariable::Subject, + ExpressionVariable::SubjectThread, + ExpressionVariable::SubjectWords, + ExpressionVariable::Location, +]; + +pub static MTA_AGGREGATE_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Hourly, + ExpressionConstant::Daily, + ExpressionConstant::Weekly, + ExpressionConstant::Disable, +]; + +pub static MTA_AUTH_TYPE_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Login, + ExpressionConstant::Plain, + ExpressionConstant::Xoauth2, + ExpressionConstant::Oauthbearer, +]; + +pub static MTA_IP_STRATEGY_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Ipv4Only, + ExpressionConstant::Ipv6Only, + ExpressionConstant::Ipv6ThenIpv4, + ExpressionConstant::Ipv4ThenIpv6, +]; + +pub static MTA_PRIORITY_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Mixer, + ExpressionConstant::Stanag4406, + ExpressionConstant::Nsep, +]; + +pub static MTA_REQUIRE_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Optional, + ExpressionConstant::Require, + ExpressionConstant::Disable, +]; + +pub static MTA_VERIFY_CONSTANT: &[ExpressionConstant] = &[ + ExpressionConstant::Relaxed, + ExpressionConstant::Strict, + ExpressionConstant::Disable, +]; diff --git a/crates/registry/src/schema/enums_impl.rs b/crates/registry/src/schema/enums_impl.rs new file mode 100644 index 00000000..9612f457 --- /dev/null +++ b/crates/registry/src/schema/enums_impl.rs @@ -0,0 +1,13891 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +use crate::schema::prelude::*; + +impl EnumImpl for AccountType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"User" => AccountType::User, + b"Group" => AccountType::Group, + } + } + + fn as_str(&self) -> &'static str { + match self { + AccountType::User => "User", + AccountType::Group => "Group", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AccountType::User), + 1 => Some(AccountType::Group), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for AccountType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AccountType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AcmeChallengeType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"TlsAlpn01" => AcmeChallengeType::TlsAlpn01, + b"DnsPersist01" => AcmeChallengeType::DnsPersist01, + b"Dns01" => AcmeChallengeType::Dns01, + b"Http01" => AcmeChallengeType::Http01, + } + } + + fn as_str(&self) -> &'static str { + match self { + AcmeChallengeType::TlsAlpn01 => "TlsAlpn01", + AcmeChallengeType::DnsPersist01 => "DnsPersist01", + AcmeChallengeType::Dns01 => "Dns01", + AcmeChallengeType::Http01 => "Http01", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AcmeChallengeType::TlsAlpn01), + 1 => Some(AcmeChallengeType::DnsPersist01), + 2 => Some(AcmeChallengeType::Dns01), + 3 => Some(AcmeChallengeType::Http01), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for AcmeChallengeType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AcmeChallengeType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AcmeRenewBefore { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"R12" => AcmeRenewBefore::R12, + b"R23" => AcmeRenewBefore::R23, + b"R34" => AcmeRenewBefore::R34, + b"R45" => AcmeRenewBefore::R45, + } + } + + fn as_str(&self) -> &'static str { + match self { + AcmeRenewBefore::R12 => "R12", + AcmeRenewBefore::R23 => "R23", + AcmeRenewBefore::R34 => "R34", + AcmeRenewBefore::R45 => "R45", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AcmeRenewBefore::R12), + 1 => Some(AcmeRenewBefore::R23), + 2 => Some(AcmeRenewBefore::R34), + 3 => Some(AcmeRenewBefore::R45), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for AcmeRenewBefore { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AcmeRenewBefore { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ActionType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"ReloadSettings" => ActionType::ReloadSettings, + b"ReloadTlsCertificates" => ActionType::ReloadTlsCertificates, + b"ReloadLookupStores" => ActionType::ReloadLookupStores, + b"ReloadBlockedIps" => ActionType::ReloadBlockedIps, + b"UpdateApps" => ActionType::UpdateApps, + b"TroubleshootDmarc" => ActionType::TroubleshootDmarc, + b"ClassifySpam" => ActionType::ClassifySpam, + b"InvalidateCaches" => ActionType::InvalidateCaches, + b"InvalidateNegativeCaches" => ActionType::InvalidateNegativeCaches, + b"PauseMtaQueue" => ActionType::PauseMtaQueue, + b"ResumeMtaQueue" => ActionType::ResumeMtaQueue, + } + } + + fn as_str(&self) -> &'static str { + match self { + ActionType::ReloadSettings => "ReloadSettings", + ActionType::ReloadTlsCertificates => "ReloadTlsCertificates", + ActionType::ReloadLookupStores => "ReloadLookupStores", + ActionType::ReloadBlockedIps => "ReloadBlockedIps", + ActionType::UpdateApps => "UpdateApps", + ActionType::TroubleshootDmarc => "TroubleshootDmarc", + ActionType::ClassifySpam => "ClassifySpam", + ActionType::InvalidateCaches => "InvalidateCaches", + ActionType::InvalidateNegativeCaches => "InvalidateNegativeCaches", + ActionType::PauseMtaQueue => "PauseMtaQueue", + ActionType::ResumeMtaQueue => "ResumeMtaQueue", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ActionType::ReloadSettings), + 1 => Some(ActionType::ReloadTlsCertificates), + 2 => Some(ActionType::ReloadLookupStores), + 3 => Some(ActionType::ReloadBlockedIps), + 4 => Some(ActionType::UpdateApps), + 5 => Some(ActionType::TroubleshootDmarc), + 6 => Some(ActionType::ClassifySpam), + 7 => Some(ActionType::InvalidateCaches), + 8 => Some(ActionType::InvalidateNegativeCaches), + 9 => Some(ActionType::PauseMtaQueue), + 10 => Some(ActionType::ResumeMtaQueue), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for ActionType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ActionType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AiModelType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Chat" => AiModelType::Chat, + b"Text" => AiModelType::Text, + } + } + + fn as_str(&self) -> &'static str { + match self { + AiModelType::Chat => "Chat", + AiModelType::Text => "Text", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AiModelType::Chat), + 1 => Some(AiModelType::Text), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for AiModelType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AiModelType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AlertEmailType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => AlertEmailType::Disabled, + b"Enabled" => AlertEmailType::Enabled, + } + } + + fn as_str(&self) -> &'static str { + match self { + AlertEmailType::Disabled => "Disabled", + AlertEmailType::Enabled => "Enabled", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AlertEmailType::Disabled), + 1 => Some(AlertEmailType::Enabled), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for AlertEmailType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AlertEmailType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AlertEventType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => AlertEventType::Disabled, + b"Enabled" => AlertEventType::Enabled, + } + } + + fn as_str(&self) -> &'static str { + match self { + AlertEventType::Disabled => "Disabled", + AlertEventType::Enabled => "Enabled", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AlertEventType::Disabled), + 1 => Some(AlertEventType::Enabled), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for AlertEventType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AlertEventType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArchivedItemStatus { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"archived" => ArchivedItemStatus::Archived, + b"requestRestore" => ArchivedItemStatus::RequestRestore, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArchivedItemStatus::Archived => "archived", + ArchivedItemStatus::RequestRestore => "requestRestore", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArchivedItemStatus::Archived), + 1 => Some(ArchivedItemStatus::RequestRestore), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for ArchivedItemStatus { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArchivedItemStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArchivedItemType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Email" => ArchivedItemType::Email, + b"FileNode" => ArchivedItemType::FileNode, + b"CalendarEvent" => ArchivedItemType::CalendarEvent, + b"ContactCard" => ArchivedItemType::ContactCard, + b"SieveScript" => ArchivedItemType::SieveScript, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArchivedItemType::Email => "Email", + ArchivedItemType::FileNode => "FileNode", + ArchivedItemType::CalendarEvent => "CalendarEvent", + ArchivedItemType::ContactCard => "ContactCard", + ArchivedItemType::SieveScript => "SieveScript", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArchivedItemType::Email), + 1 => Some(ArchivedItemType::FileNode), + 2 => Some(ArchivedItemType::CalendarEvent), + 3 => Some(ArchivedItemType::ContactCard), + 4 => Some(ArchivedItemType::SieveScript), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for ArchivedItemType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArchivedItemType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArfAuthFailureType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"adsp" => ArfAuthFailureType::Adsp, + b"bodyHash" => ArfAuthFailureType::BodyHash, + b"revoked" => ArfAuthFailureType::Revoked, + b"signature" => ArfAuthFailureType::Signature, + b"spf" => ArfAuthFailureType::Spf, + b"dmarc" => ArfAuthFailureType::Dmarc, + b"unspecified" => ArfAuthFailureType::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArfAuthFailureType::Adsp => "adsp", + ArfAuthFailureType::BodyHash => "bodyHash", + ArfAuthFailureType::Revoked => "revoked", + ArfAuthFailureType::Signature => "signature", + ArfAuthFailureType::Spf => "spf", + ArfAuthFailureType::Dmarc => "dmarc", + ArfAuthFailureType::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArfAuthFailureType::Adsp), + 1 => Some(ArfAuthFailureType::BodyHash), + 2 => Some(ArfAuthFailureType::Revoked), + 3 => Some(ArfAuthFailureType::Signature), + 4 => Some(ArfAuthFailureType::Spf), + 5 => Some(ArfAuthFailureType::Dmarc), + 6 => Some(ArfAuthFailureType::Unspecified), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for ArfAuthFailureType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArfAuthFailureType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArfDeliveryResult { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"delivered" => ArfDeliveryResult::Delivered, + b"spam" => ArfDeliveryResult::Spam, + b"policy" => ArfDeliveryResult::Policy, + b"reject" => ArfDeliveryResult::Reject, + b"other" => ArfDeliveryResult::Other, + b"unspecified" => ArfDeliveryResult::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArfDeliveryResult::Delivered => "delivered", + ArfDeliveryResult::Spam => "spam", + ArfDeliveryResult::Policy => "policy", + ArfDeliveryResult::Reject => "reject", + ArfDeliveryResult::Other => "other", + ArfDeliveryResult::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArfDeliveryResult::Delivered), + 1 => Some(ArfDeliveryResult::Spam), + 2 => Some(ArfDeliveryResult::Policy), + 3 => Some(ArfDeliveryResult::Reject), + 4 => Some(ArfDeliveryResult::Other), + 5 => Some(ArfDeliveryResult::Unspecified), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for ArfDeliveryResult { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArfDeliveryResult { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArfFeedbackType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"abuse" => ArfFeedbackType::Abuse, + b"authFailure" => ArfFeedbackType::AuthFailure, + b"fraud" => ArfFeedbackType::Fraud, + b"notSpam" => ArfFeedbackType::NotSpam, + b"virus" => ArfFeedbackType::Virus, + b"other" => ArfFeedbackType::Other, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArfFeedbackType::Abuse => "abuse", + ArfFeedbackType::AuthFailure => "authFailure", + ArfFeedbackType::Fraud => "fraud", + ArfFeedbackType::NotSpam => "notSpam", + ArfFeedbackType::Virus => "virus", + ArfFeedbackType::Other => "other", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArfFeedbackType::Abuse), + 1 => Some(ArfFeedbackType::AuthFailure), + 2 => Some(ArfFeedbackType::Fraud), + 3 => Some(ArfFeedbackType::NotSpam), + 4 => Some(ArfFeedbackType::Virus), + 5 => Some(ArfFeedbackType::Other), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for ArfFeedbackType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArfFeedbackType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ArfIdentityAlignment { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"none" => ArfIdentityAlignment::None, + b"spf" => ArfIdentityAlignment::Spf, + b"dkim" => ArfIdentityAlignment::Dkim, + b"dkimSpf" => ArfIdentityAlignment::DkimSpf, + b"unspecified" => ArfIdentityAlignment::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + ArfIdentityAlignment::None => "none", + ArfIdentityAlignment::Spf => "spf", + ArfIdentityAlignment::Dkim => "dkim", + ArfIdentityAlignment::DkimSpf => "dkimSpf", + ArfIdentityAlignment::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ArfIdentityAlignment::None), + 1 => Some(ArfIdentityAlignment::Spf), + 2 => Some(ArfIdentityAlignment::Dkim), + 3 => Some(ArfIdentityAlignment::DkimSpf), + 4 => Some(ArfIdentityAlignment::Unspecified), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for ArfIdentityAlignment { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ArfIdentityAlignment { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for AsnType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => AsnType::Disabled, + b"Resource" => AsnType::Resource, + b"Dns" => AsnType::Dns, + } + } + + fn as_str(&self) -> &'static str { + match self { + AsnType::Disabled => "Disabled", + AsnType::Resource => "Resource", + AsnType::Dns => "Dns", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(AsnType::Disabled), + 1 => Some(AsnType::Resource), + 2 => Some(AsnType::Dns), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for AsnType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for AsnType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for BlobStoreBaseType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"S3" => BlobStoreBaseType::S3, + b"Azure" => BlobStoreBaseType::Azure, + b"FileSystem" => BlobStoreBaseType::FileSystem, + b"FoundationDb" => BlobStoreBaseType::FoundationDb, + b"PostgreSql" => BlobStoreBaseType::PostgreSql, + b"MySql" => BlobStoreBaseType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + BlobStoreBaseType::S3 => "S3", + BlobStoreBaseType::Azure => "Azure", + BlobStoreBaseType::FileSystem => "FileSystem", + BlobStoreBaseType::FoundationDb => "FoundationDb", + BlobStoreBaseType::PostgreSql => "PostgreSql", + BlobStoreBaseType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(BlobStoreBaseType::S3), + 1 => Some(BlobStoreBaseType::Azure), + 2 => Some(BlobStoreBaseType::FileSystem), + 3 => Some(BlobStoreBaseType::FoundationDb), + 4 => Some(BlobStoreBaseType::PostgreSql), + 5 => Some(BlobStoreBaseType::MySql), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for BlobStoreBaseType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for BlobStoreBaseType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for BlobStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => BlobStoreType::Default, + b"Sharded" => BlobStoreType::Sharded, + b"S3" => BlobStoreType::S3, + b"Azure" => BlobStoreType::Azure, + b"FileSystem" => BlobStoreType::FileSystem, + b"FoundationDb" => BlobStoreType::FoundationDb, + b"PostgreSql" => BlobStoreType::PostgreSql, + b"MySql" => BlobStoreType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + BlobStoreType::Default => "Default", + BlobStoreType::Sharded => "Sharded", + BlobStoreType::S3 => "S3", + BlobStoreType::Azure => "Azure", + BlobStoreType::FileSystem => "FileSystem", + BlobStoreType::FoundationDb => "FoundationDb", + BlobStoreType::PostgreSql => "PostgreSql", + BlobStoreType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(BlobStoreType::Default), + 1 => Some(BlobStoreType::Sharded), + 2 => Some(BlobStoreType::S3), + 3 => Some(BlobStoreType::Azure), + 4 => Some(BlobStoreType::FileSystem), + 5 => Some(BlobStoreType::FoundationDb), + 6 => Some(BlobStoreType::PostgreSql), + 7 => Some(BlobStoreType::MySql), + _ => None, + } + } + + const COUNT: usize = 8; +} + +impl serde::Serialize for BlobStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for BlobStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for BlockReason { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"rcptToFailure" => BlockReason::RcptToFailure, + b"authFailure" => BlockReason::AuthFailure, + b"loitering" => BlockReason::Loitering, + b"portScanning" => BlockReason::PortScanning, + b"manual" => BlockReason::Manual, + b"other" => BlockReason::Other, + } + } + + fn as_str(&self) -> &'static str { + match self { + BlockReason::RcptToFailure => "rcptToFailure", + BlockReason::AuthFailure => "authFailure", + BlockReason::Loitering => "loitering", + BlockReason::PortScanning => "portScanning", + BlockReason::Manual => "manual", + BlockReason::Other => "other", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(BlockReason::RcptToFailure), + 1 => Some(BlockReason::AuthFailure), + 2 => Some(BlockReason::Loitering), + 3 => Some(BlockReason::PortScanning), + 4 => Some(BlockReason::Manual), + 5 => Some(BlockReason::Other), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for BlockReason { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for BlockReason { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CertificateManagementType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Manual" => CertificateManagementType::Manual, + b"Automatic" => CertificateManagementType::Automatic, + } + } + + fn as_str(&self) -> &'static str { + match self { + CertificateManagementType::Manual => "Manual", + CertificateManagementType::Automatic => "Automatic", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CertificateManagementType::Manual), + 1 => Some(CertificateManagementType::Automatic), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for CertificateManagementType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CertificateManagementType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ClusterListenerGroupType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"EnableAll" => ClusterListenerGroupType::EnableAll, + b"DisableAll" => ClusterListenerGroupType::DisableAll, + b"EnableSome" => ClusterListenerGroupType::EnableSome, + b"DisableSome" => ClusterListenerGroupType::DisableSome, + } + } + + fn as_str(&self) -> &'static str { + match self { + ClusterListenerGroupType::EnableAll => "EnableAll", + ClusterListenerGroupType::DisableAll => "DisableAll", + ClusterListenerGroupType::EnableSome => "EnableSome", + ClusterListenerGroupType::DisableSome => "DisableSome", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ClusterListenerGroupType::EnableAll), + 1 => Some(ClusterListenerGroupType::DisableAll), + 2 => Some(ClusterListenerGroupType::EnableSome), + 3 => Some(ClusterListenerGroupType::DisableSome), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for ClusterListenerGroupType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ClusterListenerGroupType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ClusterNodeStatus { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"active" => ClusterNodeStatus::Active, + b"stale" => ClusterNodeStatus::Stale, + b"inactive" => ClusterNodeStatus::Inactive, + } + } + + fn as_str(&self) -> &'static str { + match self { + ClusterNodeStatus::Active => "active", + ClusterNodeStatus::Stale => "stale", + ClusterNodeStatus::Inactive => "inactive", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ClusterNodeStatus::Active), + 1 => Some(ClusterNodeStatus::Stale), + 2 => Some(ClusterNodeStatus::Inactive), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for ClusterNodeStatus { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ClusterNodeStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ClusterTaskGroupType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"EnableAll" => ClusterTaskGroupType::EnableAll, + b"DisableAll" => ClusterTaskGroupType::DisableAll, + b"EnableSome" => ClusterTaskGroupType::EnableSome, + b"DisableSome" => ClusterTaskGroupType::DisableSome, + } + } + + fn as_str(&self) -> &'static str { + match self { + ClusterTaskGroupType::EnableAll => "EnableAll", + ClusterTaskGroupType::DisableAll => "DisableAll", + ClusterTaskGroupType::EnableSome => "EnableSome", + ClusterTaskGroupType::DisableSome => "DisableSome", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ClusterTaskGroupType::EnableAll), + 1 => Some(ClusterTaskGroupType::DisableAll), + 2 => Some(ClusterTaskGroupType::EnableSome), + 3 => Some(ClusterTaskGroupType::DisableSome), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for ClusterTaskGroupType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ClusterTaskGroupType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ClusterTaskType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"storeMaintenance" => ClusterTaskType::StoreMaintenance, + b"accountMaintenance" => ClusterTaskType::AccountMaintenance, + b"metricsCalculate" => ClusterTaskType::MetricsCalculate, + b"metricsPush" => ClusterTaskType::MetricsPush, + b"pushNotifications" => ClusterTaskType::PushNotifications, + b"searchIndexing" => ClusterTaskType::SearchIndexing, + b"spamClassifierTraining" => ClusterTaskType::SpamClassifierTraining, + b"outboundMta" => ClusterTaskType::OutboundMta, + b"taskQueueProcessing" => ClusterTaskType::TaskQueueProcessing, + b"taskScheduler" => ClusterTaskType::TaskScheduler, + } + } + + fn as_str(&self) -> &'static str { + match self { + ClusterTaskType::StoreMaintenance => "storeMaintenance", + ClusterTaskType::AccountMaintenance => "accountMaintenance", + ClusterTaskType::MetricsCalculate => "metricsCalculate", + ClusterTaskType::MetricsPush => "metricsPush", + ClusterTaskType::PushNotifications => "pushNotifications", + ClusterTaskType::SearchIndexing => "searchIndexing", + ClusterTaskType::SpamClassifierTraining => "spamClassifierTraining", + ClusterTaskType::OutboundMta => "outboundMta", + ClusterTaskType::TaskQueueProcessing => "taskQueueProcessing", + ClusterTaskType::TaskScheduler => "taskScheduler", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ClusterTaskType::StoreMaintenance), + 1 => Some(ClusterTaskType::AccountMaintenance), + 2 => Some(ClusterTaskType::MetricsCalculate), + 3 => Some(ClusterTaskType::MetricsPush), + 4 => Some(ClusterTaskType::PushNotifications), + 5 => Some(ClusterTaskType::SearchIndexing), + 6 => Some(ClusterTaskType::SpamClassifierTraining), + 7 => Some(ClusterTaskType::OutboundMta), + 8 => Some(ClusterTaskType::TaskQueueProcessing), + 9 => Some(ClusterTaskType::TaskScheduler), + _ => None, + } + } + + const COUNT: usize = 10; +} + +impl serde::Serialize for ClusterTaskType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ClusterTaskType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CompressionAlgo { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"lz4" => CompressionAlgo::Lz4, + b"none" => CompressionAlgo::None, + } + } + + fn as_str(&self) -> &'static str { + match self { + CompressionAlgo::Lz4 => "lz4", + CompressionAlgo::None => "none", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CompressionAlgo::Lz4), + 1 => Some(CompressionAlgo::None), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for CompressionAlgo { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CompressionAlgo { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CoordinatorType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => CoordinatorType::Disabled, + b"Default" => CoordinatorType::Default, + b"Kafka" => CoordinatorType::Kafka, + b"Nats" => CoordinatorType::Nats, + b"Zenoh" => CoordinatorType::Zenoh, + b"Redis" => CoordinatorType::Redis, + b"RedisCluster" => CoordinatorType::RedisCluster, + } + } + + fn as_str(&self) -> &'static str { + match self { + CoordinatorType::Disabled => "Disabled", + CoordinatorType::Default => "Default", + CoordinatorType::Kafka => "Kafka", + CoordinatorType::Nats => "Nats", + CoordinatorType::Zenoh => "Zenoh", + CoordinatorType::Redis => "Redis", + CoordinatorType::RedisCluster => "RedisCluster", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CoordinatorType::Disabled), + 1 => Some(CoordinatorType::Default), + 2 => Some(CoordinatorType::Kafka), + 3 => Some(CoordinatorType::Nats), + 4 => Some(CoordinatorType::Zenoh), + 5 => Some(CoordinatorType::Redis), + 6 => Some(CoordinatorType::RedisCluster), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for CoordinatorType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CoordinatorType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CredentialPermissionsType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Inherit" => CredentialPermissionsType::Inherit, + b"Disable" => CredentialPermissionsType::Disable, + b"Replace" => CredentialPermissionsType::Replace, + } + } + + fn as_str(&self) -> &'static str { + match self { + CredentialPermissionsType::Inherit => "Inherit", + CredentialPermissionsType::Disable => "Disable", + CredentialPermissionsType::Replace => "Replace", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CredentialPermissionsType::Inherit), + 1 => Some(CredentialPermissionsType::Disable), + 2 => Some(CredentialPermissionsType::Replace), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for CredentialPermissionsType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CredentialPermissionsType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CredentialType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Password" => CredentialType::Password, + b"AppPassword" => CredentialType::AppPassword, + b"ApiKey" => CredentialType::ApiKey, + } + } + + fn as_str(&self) -> &'static str { + match self { + CredentialType::Password => "Password", + CredentialType::AppPassword => "AppPassword", + CredentialType::ApiKey => "ApiKey", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CredentialType::Password), + 1 => Some(CredentialType::AppPassword), + 2 => Some(CredentialType::ApiKey), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for CredentialType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CredentialType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for CronType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Daily" => CronType::Daily, + b"Weekly" => CronType::Weekly, + b"Hourly" => CronType::Hourly, + } + } + + fn as_str(&self) -> &'static str { + match self { + CronType::Daily => "Daily", + CronType::Weekly => "Weekly", + CronType::Hourly => "Hourly", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(CronType::Daily), + 1 => Some(CronType::Weekly), + 2 => Some(CronType::Hourly), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for CronType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for CronType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DataStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"RocksDb" => DataStoreType::RocksDb, + b"Sqlite" => DataStoreType::Sqlite, + b"FoundationDb" => DataStoreType::FoundationDb, + b"PostgreSql" => DataStoreType::PostgreSql, + b"MySql" => DataStoreType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + DataStoreType::RocksDb => "RocksDb", + DataStoreType::Sqlite => "Sqlite", + DataStoreType::FoundationDb => "FoundationDb", + DataStoreType::PostgreSql => "PostgreSql", + DataStoreType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DataStoreType::RocksDb), + 1 => Some(DataStoreType::Sqlite), + 2 => Some(DataStoreType::FoundationDb), + 3 => Some(DataStoreType::PostgreSql), + 4 => Some(DataStoreType::MySql), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for DataStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DataStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DeliveryErrorType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"dnsError" => DeliveryErrorType::DnsError, + b"unexpectedResponse" => DeliveryErrorType::UnexpectedResponse, + b"connectionError" => DeliveryErrorType::ConnectionError, + b"tlsError" => DeliveryErrorType::TlsError, + b"daneError" => DeliveryErrorType::DaneError, + b"mtaStsError" => DeliveryErrorType::MtaStsError, + b"rateLimited" => DeliveryErrorType::RateLimited, + b"concurrencyLimited" => DeliveryErrorType::ConcurrencyLimited, + b"io" => DeliveryErrorType::Io, + } + } + + fn as_str(&self) -> &'static str { + match self { + DeliveryErrorType::DnsError => "dnsError", + DeliveryErrorType::UnexpectedResponse => "unexpectedResponse", + DeliveryErrorType::ConnectionError => "connectionError", + DeliveryErrorType::TlsError => "tlsError", + DeliveryErrorType::DaneError => "daneError", + DeliveryErrorType::MtaStsError => "mtaStsError", + DeliveryErrorType::RateLimited => "rateLimited", + DeliveryErrorType::ConcurrencyLimited => "concurrencyLimited", + DeliveryErrorType::Io => "io", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DeliveryErrorType::DnsError), + 1 => Some(DeliveryErrorType::UnexpectedResponse), + 2 => Some(DeliveryErrorType::ConnectionError), + 3 => Some(DeliveryErrorType::TlsError), + 4 => Some(DeliveryErrorType::DaneError), + 5 => Some(DeliveryErrorType::MtaStsError), + 6 => Some(DeliveryErrorType::RateLimited), + 7 => Some(DeliveryErrorType::ConcurrencyLimited), + 8 => Some(DeliveryErrorType::Io), + _ => None, + } + } + + const COUNT: usize = 9; +} + +impl serde::Serialize for DeliveryErrorType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DeliveryErrorType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DirectoryBootstrapType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Internal" => DirectoryBootstrapType::Internal, + b"Ldap" => DirectoryBootstrapType::Ldap, + b"Sql" => DirectoryBootstrapType::Sql, + b"Oidc" => DirectoryBootstrapType::Oidc, + } + } + + fn as_str(&self) -> &'static str { + match self { + DirectoryBootstrapType::Internal => "Internal", + DirectoryBootstrapType::Ldap => "Ldap", + DirectoryBootstrapType::Sql => "Sql", + DirectoryBootstrapType::Oidc => "Oidc", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DirectoryBootstrapType::Internal), + 1 => Some(DirectoryBootstrapType::Ldap), + 2 => Some(DirectoryBootstrapType::Sql), + 3 => Some(DirectoryBootstrapType::Oidc), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for DirectoryBootstrapType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DirectoryBootstrapType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DirectoryType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Ldap" => DirectoryType::Ldap, + b"Sql" => DirectoryType::Sql, + b"Oidc" => DirectoryType::Oidc, + } + } + + fn as_str(&self) -> &'static str { + match self { + DirectoryType::Ldap => "Ldap", + DirectoryType::Sql => "Sql", + DirectoryType::Oidc => "Oidc", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DirectoryType::Ldap), + 1 => Some(DirectoryType::Sql), + 2 => Some(DirectoryType::Oidc), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for DirectoryType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DirectoryType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimAuthResult { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"none" => DkimAuthResult::None, + b"pass" => DkimAuthResult::Pass, + b"fail" => DkimAuthResult::Fail, + b"policy" => DkimAuthResult::Policy, + b"neutral" => DkimAuthResult::Neutral, + b"tempError" => DkimAuthResult::TempError, + b"permError" => DkimAuthResult::PermError, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimAuthResult::None => "none", + DkimAuthResult::Pass => "pass", + DkimAuthResult::Fail => "fail", + DkimAuthResult::Policy => "policy", + DkimAuthResult::Neutral => "neutral", + DkimAuthResult::TempError => "tempError", + DkimAuthResult::PermError => "permError", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimAuthResult::None), + 1 => Some(DkimAuthResult::Pass), + 2 => Some(DkimAuthResult::Fail), + 3 => Some(DkimAuthResult::Policy), + 4 => Some(DkimAuthResult::Neutral), + 5 => Some(DkimAuthResult::TempError), + 6 => Some(DkimAuthResult::PermError), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for DkimAuthResult { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimAuthResult { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimCanonicalization { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"relaxed/relaxed" => DkimCanonicalization::RelaxedRelaxed, + b"simple/simple" => DkimCanonicalization::SimpleSimple, + b"relaxed/simple" => DkimCanonicalization::RelaxedSimple, + b"simple/relaxed" => DkimCanonicalization::SimpleRelaxed, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimCanonicalization::RelaxedRelaxed => "relaxed/relaxed", + DkimCanonicalization::SimpleSimple => "simple/simple", + DkimCanonicalization::RelaxedSimple => "relaxed/simple", + DkimCanonicalization::SimpleRelaxed => "simple/relaxed", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimCanonicalization::RelaxedRelaxed), + 1 => Some(DkimCanonicalization::SimpleSimple), + 2 => Some(DkimCanonicalization::RelaxedSimple), + 3 => Some(DkimCanonicalization::SimpleRelaxed), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for DkimCanonicalization { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimCanonicalization { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimHash { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"sha256" => DkimHash::Sha256, + b"sha1" => DkimHash::Sha1, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimHash::Sha256 => "sha256", + DkimHash::Sha1 => "sha1", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimHash::Sha256), + 1 => Some(DkimHash::Sha1), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for DkimHash { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimHash { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimManagementType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Automatic" => DkimManagementType::Automatic, + b"Manual" => DkimManagementType::Manual, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimManagementType::Automatic => "Automatic", + DkimManagementType::Manual => "Manual", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimManagementType::Automatic), + 1 => Some(DkimManagementType::Manual), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for DkimManagementType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimManagementType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimRotationStage { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"active" => DkimRotationStage::Active, + b"pending" => DkimRotationStage::Pending, + b"retiring" => DkimRotationStage::Retiring, + b"retired" => DkimRotationStage::Retired, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimRotationStage::Active => "active", + DkimRotationStage::Pending => "pending", + DkimRotationStage::Retiring => "retiring", + DkimRotationStage::Retired => "retired", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimRotationStage::Active), + 1 => Some(DkimRotationStage::Pending), + 2 => Some(DkimRotationStage::Retiring), + 3 => Some(DkimRotationStage::Retired), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for DkimRotationStage { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimRotationStage { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DkimSignatureType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Dkim1Ed25519Sha256" => DkimSignatureType::Dkim1Ed25519Sha256, + b"Dkim1RsaSha256" => DkimSignatureType::Dkim1RsaSha256, + } + } + + fn as_str(&self) -> &'static str { + match self { + DkimSignatureType::Dkim1Ed25519Sha256 => "Dkim1Ed25519Sha256", + DkimSignatureType::Dkim1RsaSha256 => "Dkim1RsaSha256", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DkimSignatureType::Dkim1Ed25519Sha256), + 1 => Some(DkimSignatureType::Dkim1RsaSha256), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for DkimSignatureType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DkimSignatureType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcActionDisposition { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"none" => DmarcActionDisposition::None, + b"pass" => DmarcActionDisposition::Pass, + b"quarantine" => DmarcActionDisposition::Quarantine, + b"reject" => DmarcActionDisposition::Reject, + b"unspecified" => DmarcActionDisposition::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcActionDisposition::None => "none", + DmarcActionDisposition::Pass => "pass", + DmarcActionDisposition::Quarantine => "quarantine", + DmarcActionDisposition::Reject => "reject", + DmarcActionDisposition::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcActionDisposition::None), + 1 => Some(DmarcActionDisposition::Pass), + 2 => Some(DmarcActionDisposition::Quarantine), + 3 => Some(DmarcActionDisposition::Reject), + 4 => Some(DmarcActionDisposition::Unspecified), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for DmarcActionDisposition { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcActionDisposition { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcAlignment { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"relaxed" => DmarcAlignment::Relaxed, + b"strict" => DmarcAlignment::Strict, + b"unspecified" => DmarcAlignment::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcAlignment::Relaxed => "relaxed", + DmarcAlignment::Strict => "strict", + DmarcAlignment::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcAlignment::Relaxed), + 1 => Some(DmarcAlignment::Strict), + 2 => Some(DmarcAlignment::Unspecified), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for DmarcAlignment { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcAlignment { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcDisposition { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"none" => DmarcDisposition::None, + b"quarantine" => DmarcDisposition::Quarantine, + b"reject" => DmarcDisposition::Reject, + b"unspecified" => DmarcDisposition::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcDisposition::None => "none", + DmarcDisposition::Quarantine => "quarantine", + DmarcDisposition::Reject => "reject", + DmarcDisposition::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcDisposition::None), + 1 => Some(DmarcDisposition::Quarantine), + 2 => Some(DmarcDisposition::Reject), + 3 => Some(DmarcDisposition::Unspecified), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for DmarcDisposition { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcDisposition { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcPolicyOverride { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Forwarded" => DmarcPolicyOverride::Forwarded, + b"SampledOut" => DmarcPolicyOverride::SampledOut, + b"TrustedForwarder" => DmarcPolicyOverride::TrustedForwarder, + b"MailingList" => DmarcPolicyOverride::MailingList, + b"LocalPolicy" => DmarcPolicyOverride::LocalPolicy, + b"Other" => DmarcPolicyOverride::Other, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcPolicyOverride::Forwarded => "Forwarded", + DmarcPolicyOverride::SampledOut => "SampledOut", + DmarcPolicyOverride::TrustedForwarder => "TrustedForwarder", + DmarcPolicyOverride::MailingList => "MailingList", + DmarcPolicyOverride::LocalPolicy => "LocalPolicy", + DmarcPolicyOverride::Other => "Other", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcPolicyOverride::Forwarded), + 1 => Some(DmarcPolicyOverride::SampledOut), + 2 => Some(DmarcPolicyOverride::TrustedForwarder), + 3 => Some(DmarcPolicyOverride::MailingList), + 4 => Some(DmarcPolicyOverride::LocalPolicy), + 5 => Some(DmarcPolicyOverride::Other), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for DmarcPolicyOverride { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcPolicyOverride { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcResult { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"pass" => DmarcResult::Pass, + b"fail" => DmarcResult::Fail, + b"unspecified" => DmarcResult::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcResult::Pass => "pass", + DmarcResult::Fail => "fail", + DmarcResult::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcResult::Pass), + 1 => Some(DmarcResult::Fail), + 2 => Some(DmarcResult::Unspecified), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for DmarcResult { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcResult { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DmarcTroubleshootAuthResultType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Pass" => DmarcTroubleshootAuthResultType::Pass, + b"Fail" => DmarcTroubleshootAuthResultType::Fail, + b"SoftFail" => DmarcTroubleshootAuthResultType::SoftFail, + b"TempError" => DmarcTroubleshootAuthResultType::TempError, + b"PermError" => DmarcTroubleshootAuthResultType::PermError, + b"Neutral" => DmarcTroubleshootAuthResultType::Neutral, + b"None" => DmarcTroubleshootAuthResultType::None, + } + } + + fn as_str(&self) -> &'static str { + match self { + DmarcTroubleshootAuthResultType::Pass => "Pass", + DmarcTroubleshootAuthResultType::Fail => "Fail", + DmarcTroubleshootAuthResultType::SoftFail => "SoftFail", + DmarcTroubleshootAuthResultType::TempError => "TempError", + DmarcTroubleshootAuthResultType::PermError => "PermError", + DmarcTroubleshootAuthResultType::Neutral => "Neutral", + DmarcTroubleshootAuthResultType::None => "None", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DmarcTroubleshootAuthResultType::Pass), + 1 => Some(DmarcTroubleshootAuthResultType::Fail), + 2 => Some(DmarcTroubleshootAuthResultType::SoftFail), + 3 => Some(DmarcTroubleshootAuthResultType::TempError), + 4 => Some(DmarcTroubleshootAuthResultType::PermError), + 5 => Some(DmarcTroubleshootAuthResultType::Neutral), + 6 => Some(DmarcTroubleshootAuthResultType::None), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for DmarcTroubleshootAuthResultType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DmarcTroubleshootAuthResultType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsManagementType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Manual" => DnsManagementType::Manual, + b"Automatic" => DnsManagementType::Automatic, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsManagementType::Manual => "Manual", + DnsManagementType::Automatic => "Automatic", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsManagementType::Manual), + 1 => Some(DnsManagementType::Automatic), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for DnsManagementType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsManagementType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsPublishStatus { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"synced" => DnsPublishStatus::Synced, + b"pending" => DnsPublishStatus::Pending, + b"failed" => DnsPublishStatus::Failed, + b"unknown" => DnsPublishStatus::Unknown, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsPublishStatus::Synced => "synced", + DnsPublishStatus::Pending => "pending", + DnsPublishStatus::Failed => "failed", + DnsPublishStatus::Unknown => "unknown", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsPublishStatus::Synced), + 1 => Some(DnsPublishStatus::Pending), + 2 => Some(DnsPublishStatus::Failed), + 3 => Some(DnsPublishStatus::Unknown), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for DnsPublishStatus { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsPublishStatus { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsRecordType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"dkim" => DnsRecordType::Dkim, + b"tlsa" => DnsRecordType::Tlsa, + b"spf" => DnsRecordType::Spf, + b"mx" => DnsRecordType::Mx, + b"dmarc" => DnsRecordType::Dmarc, + b"srv" => DnsRecordType::Srv, + b"mtaSts" => DnsRecordType::MtaSts, + b"tlsRpt" => DnsRecordType::TlsRpt, + b"caa" => DnsRecordType::Caa, + b"autoConfig" => DnsRecordType::AutoConfig, + b"autoConfigLegacy" => DnsRecordType::AutoConfigLegacy, + b"autoDiscover" => DnsRecordType::AutoDiscover, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsRecordType::Dkim => "dkim", + DnsRecordType::Tlsa => "tlsa", + DnsRecordType::Spf => "spf", + DnsRecordType::Mx => "mx", + DnsRecordType::Dmarc => "dmarc", + DnsRecordType::Srv => "srv", + DnsRecordType::MtaSts => "mtaSts", + DnsRecordType::TlsRpt => "tlsRpt", + DnsRecordType::Caa => "caa", + DnsRecordType::AutoConfig => "autoConfig", + DnsRecordType::AutoConfigLegacy => "autoConfigLegacy", + DnsRecordType::AutoDiscover => "autoDiscover", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsRecordType::Dkim), + 1 => Some(DnsRecordType::Tlsa), + 2 => Some(DnsRecordType::Spf), + 3 => Some(DnsRecordType::Mx), + 4 => Some(DnsRecordType::Dmarc), + 5 => Some(DnsRecordType::Srv), + 6 => Some(DnsRecordType::MtaSts), + 7 => Some(DnsRecordType::TlsRpt), + 8 => Some(DnsRecordType::Caa), + 9 => Some(DnsRecordType::AutoConfig), + 10 => Some(DnsRecordType::AutoConfigLegacy), + 11 => Some(DnsRecordType::AutoDiscover), + _ => None, + } + } + + const COUNT: usize = 12; +} + +impl serde::Serialize for DnsRecordType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsRecordType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsResolverProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"tls" => DnsResolverProtocol::Tls, + b"udp" => DnsResolverProtocol::Udp, + b"tcp" => DnsResolverProtocol::Tcp, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsResolverProtocol::Tls => "tls", + DnsResolverProtocol::Udp => "udp", + DnsResolverProtocol::Tcp => "tcp", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsResolverProtocol::Tls), + 1 => Some(DnsResolverProtocol::Udp), + 2 => Some(DnsResolverProtocol::Tcp), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for DnsResolverProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsResolverProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsResolverType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"System" => DnsResolverType::System, + b"Custom" => DnsResolverType::Custom, + b"Cloudflare" => DnsResolverType::Cloudflare, + b"Quad9" => DnsResolverType::Quad9, + b"Google" => DnsResolverType::Google, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsResolverType::System => "System", + DnsResolverType::Custom => "Custom", + DnsResolverType::Cloudflare => "Cloudflare", + DnsResolverType::Quad9 => "Quad9", + DnsResolverType::Google => "Google", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsResolverType::System), + 1 => Some(DnsResolverType::Custom), + 2 => Some(DnsResolverType::Cloudflare), + 3 => Some(DnsResolverType::Quad9), + 4 => Some(DnsResolverType::Google), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for DnsResolverType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsResolverType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsServerBootstrapType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Manual" => DnsServerBootstrapType::Manual, + b"Tsig" => DnsServerBootstrapType::Tsig, + b"Sig0" => DnsServerBootstrapType::Sig0, + b"Cloudflare" => DnsServerBootstrapType::Cloudflare, + b"DigitalOcean" => DnsServerBootstrapType::DigitalOcean, + b"DeSEC" => DnsServerBootstrapType::DeSEC, + b"Ovh" => DnsServerBootstrapType::Ovh, + b"Bunny" => DnsServerBootstrapType::Bunny, + b"Porkbun" => DnsServerBootstrapType::Porkbun, + b"Dnsimple" => DnsServerBootstrapType::Dnsimple, + b"Spaceship" => DnsServerBootstrapType::Spaceship, + b"Route53" => DnsServerBootstrapType::Route53, + b"GoogleCloudDns" => DnsServerBootstrapType::GoogleCloudDns, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsServerBootstrapType::Manual => "Manual", + DnsServerBootstrapType::Tsig => "Tsig", + DnsServerBootstrapType::Sig0 => "Sig0", + DnsServerBootstrapType::Cloudflare => "Cloudflare", + DnsServerBootstrapType::DigitalOcean => "DigitalOcean", + DnsServerBootstrapType::DeSEC => "DeSEC", + DnsServerBootstrapType::Ovh => "Ovh", + DnsServerBootstrapType::Bunny => "Bunny", + DnsServerBootstrapType::Porkbun => "Porkbun", + DnsServerBootstrapType::Dnsimple => "Dnsimple", + DnsServerBootstrapType::Spaceship => "Spaceship", + DnsServerBootstrapType::Route53 => "Route53", + DnsServerBootstrapType::GoogleCloudDns => "GoogleCloudDns", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsServerBootstrapType::Manual), + 1 => Some(DnsServerBootstrapType::Tsig), + 2 => Some(DnsServerBootstrapType::Sig0), + 3 => Some(DnsServerBootstrapType::Cloudflare), + 4 => Some(DnsServerBootstrapType::DigitalOcean), + 5 => Some(DnsServerBootstrapType::DeSEC), + 6 => Some(DnsServerBootstrapType::Ovh), + 7 => Some(DnsServerBootstrapType::Bunny), + 8 => Some(DnsServerBootstrapType::Porkbun), + 9 => Some(DnsServerBootstrapType::Dnsimple), + 10 => Some(DnsServerBootstrapType::Spaceship), + 11 => Some(DnsServerBootstrapType::Route53), + 12 => Some(DnsServerBootstrapType::GoogleCloudDns), + _ => None, + } + } + + const COUNT: usize = 13; +} + +impl serde::Serialize for DnsServerBootstrapType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsServerBootstrapType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for DnsServerType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Tsig" => DnsServerType::Tsig, + b"Sig0" => DnsServerType::Sig0, + b"Cloudflare" => DnsServerType::Cloudflare, + b"DigitalOcean" => DnsServerType::DigitalOcean, + b"DeSEC" => DnsServerType::DeSEC, + b"Ovh" => DnsServerType::Ovh, + b"Bunny" => DnsServerType::Bunny, + b"Porkbun" => DnsServerType::Porkbun, + b"Dnsimple" => DnsServerType::Dnsimple, + b"Spaceship" => DnsServerType::Spaceship, + b"Route53" => DnsServerType::Route53, + b"GoogleCloudDns" => DnsServerType::GoogleCloudDns, + } + } + + fn as_str(&self) -> &'static str { + match self { + DnsServerType::Tsig => "Tsig", + DnsServerType::Sig0 => "Sig0", + DnsServerType::Cloudflare => "Cloudflare", + DnsServerType::DigitalOcean => "DigitalOcean", + DnsServerType::DeSEC => "DeSEC", + DnsServerType::Ovh => "Ovh", + DnsServerType::Bunny => "Bunny", + DnsServerType::Porkbun => "Porkbun", + DnsServerType::Dnsimple => "Dnsimple", + DnsServerType::Spaceship => "Spaceship", + DnsServerType::Route53 => "Route53", + DnsServerType::GoogleCloudDns => "GoogleCloudDns", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(DnsServerType::Tsig), + 1 => Some(DnsServerType::Sig0), + 2 => Some(DnsServerType::Cloudflare), + 3 => Some(DnsServerType::DigitalOcean), + 4 => Some(DnsServerType::DeSEC), + 5 => Some(DnsServerType::Ovh), + 6 => Some(DnsServerType::Bunny), + 7 => Some(DnsServerType::Porkbun), + 8 => Some(DnsServerType::Dnsimple), + 9 => Some(DnsServerType::Spaceship), + 10 => Some(DnsServerType::Route53), + 11 => Some(DnsServerType::GoogleCloudDns), + _ => None, + } + } + + const COUNT: usize = 12; +} + +impl serde::Serialize for DnsServerType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for DnsServerType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for EncryptionAtRestType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => EncryptionAtRestType::Disabled, + b"Aes128" => EncryptionAtRestType::Aes128, + b"Aes256" => EncryptionAtRestType::Aes256, + } + } + + fn as_str(&self) -> &'static str { + match self { + EncryptionAtRestType::Disabled => "Disabled", + EncryptionAtRestType::Aes128 => "Aes128", + EncryptionAtRestType::Aes256 => "Aes256", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(EncryptionAtRestType::Disabled), + 1 => Some(EncryptionAtRestType::Aes128), + 2 => Some(EncryptionAtRestType::Aes256), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for EncryptionAtRestType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for EncryptionAtRestType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for EventPolicy { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"include" => EventPolicy::Include, + b"exclude" => EventPolicy::Exclude, + } + } + + fn as_str(&self) -> &'static str { + match self { + EventPolicy::Include => "include", + EventPolicy::Exclude => "exclude", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(EventPolicy::Include), + 1 => Some(EventPolicy::Exclude), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for EventPolicy { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for EventPolicy { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ExpressionConstant { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"relaxed" => ExpressionConstant::Relaxed, + b"strict" => ExpressionConstant::Strict, + b"disable" => ExpressionConstant::Disable, + b"optional" => ExpressionConstant::Optional, + b"require" => ExpressionConstant::Require, + b"ipv4_only" => ExpressionConstant::Ipv4Only, + b"ipv6_only" => ExpressionConstant::Ipv6Only, + b"ipv6_then_ipv4" => ExpressionConstant::Ipv6ThenIpv4, + b"ipv4_then_ipv6" => ExpressionConstant::Ipv4ThenIpv6, + b"hourly" => ExpressionConstant::Hourly, + b"daily" => ExpressionConstant::Daily, + b"weekly" => ExpressionConstant::Weekly, + b"login" => ExpressionConstant::Login, + b"plain" => ExpressionConstant::Plain, + b"xoauth2" => ExpressionConstant::Xoauth2, + b"oauthbearer" => ExpressionConstant::Oauthbearer, + b"mixer" => ExpressionConstant::Mixer, + b"stanag4406" => ExpressionConstant::Stanag4406, + b"nsep" => ExpressionConstant::Nsep, + } + } + + fn as_str(&self) -> &'static str { + match self { + ExpressionConstant::Relaxed => "relaxed", + ExpressionConstant::Strict => "strict", + ExpressionConstant::Disable => "disable", + ExpressionConstant::Optional => "optional", + ExpressionConstant::Require => "require", + ExpressionConstant::Ipv4Only => "ipv4_only", + ExpressionConstant::Ipv6Only => "ipv6_only", + ExpressionConstant::Ipv6ThenIpv4 => "ipv6_then_ipv4", + ExpressionConstant::Ipv4ThenIpv6 => "ipv4_then_ipv6", + ExpressionConstant::Hourly => "hourly", + ExpressionConstant::Daily => "daily", + ExpressionConstant::Weekly => "weekly", + ExpressionConstant::Login => "login", + ExpressionConstant::Plain => "plain", + ExpressionConstant::Xoauth2 => "xoauth2", + ExpressionConstant::Oauthbearer => "oauthbearer", + ExpressionConstant::Mixer => "mixer", + ExpressionConstant::Stanag4406 => "stanag4406", + ExpressionConstant::Nsep => "nsep", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ExpressionConstant::Relaxed), + 1 => Some(ExpressionConstant::Strict), + 2 => Some(ExpressionConstant::Disable), + 3 => Some(ExpressionConstant::Optional), + 4 => Some(ExpressionConstant::Require), + 5 => Some(ExpressionConstant::Ipv4Only), + 6 => Some(ExpressionConstant::Ipv6Only), + 7 => Some(ExpressionConstant::Ipv6ThenIpv4), + 8 => Some(ExpressionConstant::Ipv4ThenIpv6), + 9 => Some(ExpressionConstant::Hourly), + 10 => Some(ExpressionConstant::Daily), + 11 => Some(ExpressionConstant::Weekly), + 12 => Some(ExpressionConstant::Login), + 13 => Some(ExpressionConstant::Plain), + 14 => Some(ExpressionConstant::Xoauth2), + 15 => Some(ExpressionConstant::Oauthbearer), + 16 => Some(ExpressionConstant::Mixer), + 17 => Some(ExpressionConstant::Stanag4406), + 18 => Some(ExpressionConstant::Nsep), + _ => None, + } + } + + const COUNT: usize = 19; +} + +impl serde::Serialize for ExpressionConstant { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ExpressionConstant { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ExpressionVariable { + fn parse(value: &str) -> Option { + hashify::map! { + value.as_bytes(), + ExpressionVariable, + b"asn" => ExpressionVariable::Asn, + b"attributes" => ExpressionVariable::Attributes, + b"authenticated_as" => ExpressionVariable::AuthenticatedAs, + b"authority" => ExpressionVariable::Authority, + b"bcc" => ExpressionVariable::Bcc, + b"bcc.domain" => ExpressionVariable::BccDomain, + b"bcc.local" => ExpressionVariable::BccLocal, + b"bcc.name" => ExpressionVariable::BccName, + b"body" => ExpressionVariable::Body, + b"body.html" => ExpressionVariable::BodyHtml, + b"body.raw" => ExpressionVariable::BodyRaw, + b"body.text" => ExpressionVariable::BodyText, + b"body.words" => ExpressionVariable::BodyWords, + b"cc" => ExpressionVariable::Cc, + b"cc.domain" => ExpressionVariable::CcDomain, + b"cc.local" => ExpressionVariable::CcLocal, + b"cc.name" => ExpressionVariable::CcName, + b"country" => ExpressionVariable::Country, + b"domain" => ExpressionVariable::Domain, + b"email" => ExpressionVariable::Email, + b"email_lower" => ExpressionVariable::EmailLower, + b"env_from" => ExpressionVariable::EnvFrom, + b"env_from.domain" => ExpressionVariable::EnvFromDomain, + b"env_from.local" => ExpressionVariable::EnvFromLocal, + b"env_to" => ExpressionVariable::EnvTo, + b"expires_in" => ExpressionVariable::ExpiresIn, + b"from" => ExpressionVariable::From, + b"from.domain" => ExpressionVariable::FromDomain, + b"from.local" => ExpressionVariable::FromLocal, + b"from.name" => ExpressionVariable::FromName, + b"headers" => ExpressionVariable::Headers, + b"helo_domain" => ExpressionVariable::HeloDomain, + b"host" => ExpressionVariable::Host, + b"ip" => ExpressionVariable::Ip, + b"ip_reverse" => ExpressionVariable::IpReverse, + b"is_tls" => ExpressionVariable::IsTls, + b"is_v4" => ExpressionVariable::IsV4, + b"is_v6" => ExpressionVariable::IsV6, + b"last_error" => ExpressionVariable::LastError, + b"last_status" => ExpressionVariable::LastStatus, + b"listener" => ExpressionVariable::Listener, + b"local" => ExpressionVariable::Local, + b"local_ip" => ExpressionVariable::LocalIp, + b"local_port" => ExpressionVariable::LocalPort, + b"location" => ExpressionVariable::Location, + b"method" => ExpressionVariable::Method, + b"mx" => ExpressionVariable::Mx, + b"name" => ExpressionVariable::Name, + b"name_lower" => ExpressionVariable::NameLower, + b"notify_num" => ExpressionVariable::NotifyNum, + b"octets" => ExpressionVariable::Octets, + b"path" => ExpressionVariable::Path, + b"path_query" => ExpressionVariable::PathQuery, + b"port" => ExpressionVariable::Port, + b"priority" => ExpressionVariable::Priority, + b"protocol" => ExpressionVariable::Protocol, + b"query" => ExpressionVariable::Query, + b"queue_age" => ExpressionVariable::QueueAge, + b"queue_name" => ExpressionVariable::QueueName, + b"raw" => ExpressionVariable::Raw, + b"raw_lower" => ExpressionVariable::RawLower, + b"rcpt" => ExpressionVariable::Rcpt, + b"rcpt_domain" => ExpressionVariable::RcptDomain, + b"received_from_ip" => ExpressionVariable::ReceivedFromIp, + b"received_via_port" => ExpressionVariable::ReceivedViaPort, + b"recipients" => ExpressionVariable::Recipients, + b"remote_ip" => ExpressionVariable::RemoteIp, + b"remote_ip.ptr" => ExpressionVariable::RemoteIpPtr, + b"remote_port" => ExpressionVariable::RemotePort, + b"reply_to" => ExpressionVariable::ReplyTo, + b"reply_to.domain" => ExpressionVariable::ReplyToDomain, + b"reply_to.local" => ExpressionVariable::ReplyToLocal, + b"reply_to.name" => ExpressionVariable::ReplyToName, + b"retry_num" => ExpressionVariable::RetryNum, + b"reverse_ip" => ExpressionVariable::ReverseIp, + b"scheme" => ExpressionVariable::Scheme, + b"sender" => ExpressionVariable::Sender, + b"sender_domain" => ExpressionVariable::SenderDomain, + b"size" => ExpressionVariable::Size, + b"sld" => ExpressionVariable::Sld, + b"source" => ExpressionVariable::Source, + b"subject" => ExpressionVariable::Subject, + b"subject.thread" => ExpressionVariable::SubjectThread, + b"subject.words" => ExpressionVariable::SubjectWords, + b"to" => ExpressionVariable::To, + b"to.domain" => ExpressionVariable::ToDomain, + b"to.local" => ExpressionVariable::ToLocal, + b"to.name" => ExpressionVariable::ToName, + b"url" => ExpressionVariable::Url, + b"value" => ExpressionVariable::Value, + b"value_lower" => ExpressionVariable::ValueLower, + } + .copied() + } + + fn as_str(&self) -> &'static str { + match self { + ExpressionVariable::Asn => "asn", + ExpressionVariable::Attributes => "attributes", + ExpressionVariable::AuthenticatedAs => "authenticated_as", + ExpressionVariable::Authority => "authority", + ExpressionVariable::Bcc => "bcc", + ExpressionVariable::BccDomain => "bcc.domain", + ExpressionVariable::BccLocal => "bcc.local", + ExpressionVariable::BccName => "bcc.name", + ExpressionVariable::Body => "body", + ExpressionVariable::BodyHtml => "body.html", + ExpressionVariable::BodyRaw => "body.raw", + ExpressionVariable::BodyText => "body.text", + ExpressionVariable::BodyWords => "body.words", + ExpressionVariable::Cc => "cc", + ExpressionVariable::CcDomain => "cc.domain", + ExpressionVariable::CcLocal => "cc.local", + ExpressionVariable::CcName => "cc.name", + ExpressionVariable::Country => "country", + ExpressionVariable::Domain => "domain", + ExpressionVariable::Email => "email", + ExpressionVariable::EmailLower => "email_lower", + ExpressionVariable::EnvFrom => "env_from", + ExpressionVariable::EnvFromDomain => "env_from.domain", + ExpressionVariable::EnvFromLocal => "env_from.local", + ExpressionVariable::EnvTo => "env_to", + ExpressionVariable::ExpiresIn => "expires_in", + ExpressionVariable::From => "from", + ExpressionVariable::FromDomain => "from.domain", + ExpressionVariable::FromLocal => "from.local", + ExpressionVariable::FromName => "from.name", + ExpressionVariable::Headers => "headers", + ExpressionVariable::HeloDomain => "helo_domain", + ExpressionVariable::Host => "host", + ExpressionVariable::Ip => "ip", + ExpressionVariable::IpReverse => "ip_reverse", + ExpressionVariable::IsTls => "is_tls", + ExpressionVariable::IsV4 => "is_v4", + ExpressionVariable::IsV6 => "is_v6", + ExpressionVariable::LastError => "last_error", + ExpressionVariable::LastStatus => "last_status", + ExpressionVariable::Listener => "listener", + ExpressionVariable::Local => "local", + ExpressionVariable::LocalIp => "local_ip", + ExpressionVariable::LocalPort => "local_port", + ExpressionVariable::Location => "location", + ExpressionVariable::Method => "method", + ExpressionVariable::Mx => "mx", + ExpressionVariable::Name => "name", + ExpressionVariable::NameLower => "name_lower", + ExpressionVariable::NotifyNum => "notify_num", + ExpressionVariable::Octets => "octets", + ExpressionVariable::Path => "path", + ExpressionVariable::PathQuery => "path_query", + ExpressionVariable::Port => "port", + ExpressionVariable::Priority => "priority", + ExpressionVariable::Protocol => "protocol", + ExpressionVariable::Query => "query", + ExpressionVariable::QueueAge => "queue_age", + ExpressionVariable::QueueName => "queue_name", + ExpressionVariable::Raw => "raw", + ExpressionVariable::RawLower => "raw_lower", + ExpressionVariable::Rcpt => "rcpt", + ExpressionVariable::RcptDomain => "rcpt_domain", + ExpressionVariable::ReceivedFromIp => "received_from_ip", + ExpressionVariable::ReceivedViaPort => "received_via_port", + ExpressionVariable::Recipients => "recipients", + ExpressionVariable::RemoteIp => "remote_ip", + ExpressionVariable::RemoteIpPtr => "remote_ip.ptr", + ExpressionVariable::RemotePort => "remote_port", + ExpressionVariable::ReplyTo => "reply_to", + ExpressionVariable::ReplyToDomain => "reply_to.domain", + ExpressionVariable::ReplyToLocal => "reply_to.local", + ExpressionVariable::ReplyToName => "reply_to.name", + ExpressionVariable::RetryNum => "retry_num", + ExpressionVariable::ReverseIp => "reverse_ip", + ExpressionVariable::Scheme => "scheme", + ExpressionVariable::Sender => "sender", + ExpressionVariable::SenderDomain => "sender_domain", + ExpressionVariable::Size => "size", + ExpressionVariable::Sld => "sld", + ExpressionVariable::Source => "source", + ExpressionVariable::Subject => "subject", + ExpressionVariable::SubjectThread => "subject.thread", + ExpressionVariable::SubjectWords => "subject.words", + ExpressionVariable::To => "to", + ExpressionVariable::ToDomain => "to.domain", + ExpressionVariable::ToLocal => "to.local", + ExpressionVariable::ToName => "to.name", + ExpressionVariable::Url => "url", + ExpressionVariable::Value => "value", + ExpressionVariable::ValueLower => "value_lower", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ExpressionVariable::Asn), + 1 => Some(ExpressionVariable::Attributes), + 2 => Some(ExpressionVariable::AuthenticatedAs), + 3 => Some(ExpressionVariable::Authority), + 4 => Some(ExpressionVariable::Bcc), + 5 => Some(ExpressionVariable::BccDomain), + 6 => Some(ExpressionVariable::BccLocal), + 7 => Some(ExpressionVariable::BccName), + 8 => Some(ExpressionVariable::Body), + 9 => Some(ExpressionVariable::BodyHtml), + 10 => Some(ExpressionVariable::BodyRaw), + 11 => Some(ExpressionVariable::BodyText), + 12 => Some(ExpressionVariable::BodyWords), + 13 => Some(ExpressionVariable::Cc), + 14 => Some(ExpressionVariable::CcDomain), + 15 => Some(ExpressionVariable::CcLocal), + 16 => Some(ExpressionVariable::CcName), + 17 => Some(ExpressionVariable::Country), + 18 => Some(ExpressionVariable::Domain), + 19 => Some(ExpressionVariable::Email), + 20 => Some(ExpressionVariable::EmailLower), + 21 => Some(ExpressionVariable::EnvFrom), + 22 => Some(ExpressionVariable::EnvFromDomain), + 23 => Some(ExpressionVariable::EnvFromLocal), + 24 => Some(ExpressionVariable::EnvTo), + 25 => Some(ExpressionVariable::ExpiresIn), + 26 => Some(ExpressionVariable::From), + 27 => Some(ExpressionVariable::FromDomain), + 28 => Some(ExpressionVariable::FromLocal), + 29 => Some(ExpressionVariable::FromName), + 30 => Some(ExpressionVariable::Headers), + 31 => Some(ExpressionVariable::HeloDomain), + 32 => Some(ExpressionVariable::Host), + 33 => Some(ExpressionVariable::Ip), + 34 => Some(ExpressionVariable::IpReverse), + 35 => Some(ExpressionVariable::IsTls), + 36 => Some(ExpressionVariable::IsV4), + 37 => Some(ExpressionVariable::IsV6), + 38 => Some(ExpressionVariable::LastError), + 39 => Some(ExpressionVariable::LastStatus), + 40 => Some(ExpressionVariable::Listener), + 41 => Some(ExpressionVariable::Local), + 42 => Some(ExpressionVariable::LocalIp), + 43 => Some(ExpressionVariable::LocalPort), + 44 => Some(ExpressionVariable::Location), + 45 => Some(ExpressionVariable::Method), + 46 => Some(ExpressionVariable::Mx), + 47 => Some(ExpressionVariable::Name), + 48 => Some(ExpressionVariable::NameLower), + 49 => Some(ExpressionVariable::NotifyNum), + 50 => Some(ExpressionVariable::Octets), + 51 => Some(ExpressionVariable::Path), + 52 => Some(ExpressionVariable::PathQuery), + 53 => Some(ExpressionVariable::Port), + 54 => Some(ExpressionVariable::Priority), + 55 => Some(ExpressionVariable::Protocol), + 56 => Some(ExpressionVariable::Query), + 57 => Some(ExpressionVariable::QueueAge), + 58 => Some(ExpressionVariable::QueueName), + 59 => Some(ExpressionVariable::Raw), + 60 => Some(ExpressionVariable::RawLower), + 61 => Some(ExpressionVariable::Rcpt), + 62 => Some(ExpressionVariable::RcptDomain), + 63 => Some(ExpressionVariable::ReceivedFromIp), + 64 => Some(ExpressionVariable::ReceivedViaPort), + 65 => Some(ExpressionVariable::Recipients), + 66 => Some(ExpressionVariable::RemoteIp), + 67 => Some(ExpressionVariable::RemoteIpPtr), + 68 => Some(ExpressionVariable::RemotePort), + 69 => Some(ExpressionVariable::ReplyTo), + 70 => Some(ExpressionVariable::ReplyToDomain), + 71 => Some(ExpressionVariable::ReplyToLocal), + 72 => Some(ExpressionVariable::ReplyToName), + 73 => Some(ExpressionVariable::RetryNum), + 74 => Some(ExpressionVariable::ReverseIp), + 75 => Some(ExpressionVariable::Scheme), + 76 => Some(ExpressionVariable::Sender), + 77 => Some(ExpressionVariable::SenderDomain), + 78 => Some(ExpressionVariable::Size), + 79 => Some(ExpressionVariable::Sld), + 80 => Some(ExpressionVariable::Source), + 81 => Some(ExpressionVariable::Subject), + 82 => Some(ExpressionVariable::SubjectThread), + 83 => Some(ExpressionVariable::SubjectWords), + 84 => Some(ExpressionVariable::To), + 85 => Some(ExpressionVariable::ToDomain), + 86 => Some(ExpressionVariable::ToLocal), + 87 => Some(ExpressionVariable::ToName), + 88 => Some(ExpressionVariable::Url), + 89 => Some(ExpressionVariable::Value), + 90 => Some(ExpressionVariable::ValueLower), + _ => None, + } + } + + const COUNT: usize = 91; +} + +impl serde::Serialize for ExpressionVariable { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ExpressionVariable { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for FailureReportingOption { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"all" => FailureReportingOption::All, + b"any" => FailureReportingOption::Any, + b"dkimFailure" => FailureReportingOption::DkimFailure, + b"spfFailure" => FailureReportingOption::SpfFailure, + } + } + + fn as_str(&self) -> &'static str { + match self { + FailureReportingOption::All => "all", + FailureReportingOption::Any => "any", + FailureReportingOption::DkimFailure => "dkimFailure", + FailureReportingOption::SpfFailure => "spfFailure", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(FailureReportingOption::All), + 1 => Some(FailureReportingOption::Any), + 2 => Some(FailureReportingOption::DkimFailure), + 3 => Some(FailureReportingOption::SpfFailure), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for FailureReportingOption { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for FailureReportingOption { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for HttpAuthType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Unauthenticated" => HttpAuthType::Unauthenticated, + b"Basic" => HttpAuthType::Basic, + b"Bearer" => HttpAuthType::Bearer, + } + } + + fn as_str(&self) -> &'static str { + match self { + HttpAuthType::Unauthenticated => "Unauthenticated", + HttpAuthType::Basic => "Basic", + HttpAuthType::Bearer => "Bearer", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(HttpAuthType::Unauthenticated), + 1 => Some(HttpAuthType::Basic), + 2 => Some(HttpAuthType::Bearer), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for HttpAuthType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for HttpAuthType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for HttpLookupFormatType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Csv" => HttpLookupFormatType::Csv, + b"List" => HttpLookupFormatType::List, + } + } + + fn as_str(&self) -> &'static str { + match self { + HttpLookupFormatType::Csv => "Csv", + HttpLookupFormatType::List => "List", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(HttpLookupFormatType::Csv), + 1 => Some(HttpLookupFormatType::List), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for HttpLookupFormatType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for HttpLookupFormatType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for InMemoryStoreBaseType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Redis" => InMemoryStoreBaseType::Redis, + b"RedisCluster" => InMemoryStoreBaseType::RedisCluster, + } + } + + fn as_str(&self) -> &'static str { + match self { + InMemoryStoreBaseType::Redis => "Redis", + InMemoryStoreBaseType::RedisCluster => "RedisCluster", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(InMemoryStoreBaseType::Redis), + 1 => Some(InMemoryStoreBaseType::RedisCluster), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for InMemoryStoreBaseType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for InMemoryStoreBaseType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for InMemoryStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => InMemoryStoreType::Default, + b"Sharded" => InMemoryStoreType::Sharded, + b"Redis" => InMemoryStoreType::Redis, + b"RedisCluster" => InMemoryStoreType::RedisCluster, + } + } + + fn as_str(&self) -> &'static str { + match self { + InMemoryStoreType::Default => "Default", + InMemoryStoreType::Sharded => "Sharded", + InMemoryStoreType::Redis => "Redis", + InMemoryStoreType::RedisCluster => "RedisCluster", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(InMemoryStoreType::Default), + 1 => Some(InMemoryStoreType::Sharded), + 2 => Some(InMemoryStoreType::Redis), + 3 => Some(InMemoryStoreType::RedisCluster), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for InMemoryStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for InMemoryStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for IndexDocumentType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"email" => IndexDocumentType::Email, + b"calendar" => IndexDocumentType::Calendar, + b"contacts" => IndexDocumentType::Contacts, + b"file" => IndexDocumentType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + IndexDocumentType::Email => "email", + IndexDocumentType::Calendar => "calendar", + IndexDocumentType::Contacts => "contacts", + IndexDocumentType::File => "file", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(IndexDocumentType::Email), + 1 => Some(IndexDocumentType::Calendar), + 2 => Some(IndexDocumentType::Contacts), + 3 => Some(IndexDocumentType::File), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for IndexDocumentType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for IndexDocumentType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for IpProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"udp" => IpProtocol::Udp, + b"tcp" => IpProtocol::Tcp, + } + } + + fn as_str(&self) -> &'static str { + match self { + IpProtocol::Udp => "udp", + IpProtocol::Tcp => "tcp", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(IpProtocol::Udp), + 1 => Some(IpProtocol::Tcp), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for IpProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for IpProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for JwtSignatureAlgorithm { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"es256" => JwtSignatureAlgorithm::Es256, + b"es384" => JwtSignatureAlgorithm::Es384, + b"ps256" => JwtSignatureAlgorithm::Ps256, + b"ps384" => JwtSignatureAlgorithm::Ps384, + b"ps512" => JwtSignatureAlgorithm::Ps512, + b"rs256" => JwtSignatureAlgorithm::Rs256, + b"rs384" => JwtSignatureAlgorithm::Rs384, + b"rs512" => JwtSignatureAlgorithm::Rs512, + b"hs256" => JwtSignatureAlgorithm::Hs256, + b"hs384" => JwtSignatureAlgorithm::Hs384, + b"hs512" => JwtSignatureAlgorithm::Hs512, + } + } + + fn as_str(&self) -> &'static str { + match self { + JwtSignatureAlgorithm::Es256 => "es256", + JwtSignatureAlgorithm::Es384 => "es384", + JwtSignatureAlgorithm::Ps256 => "ps256", + JwtSignatureAlgorithm::Ps384 => "ps384", + JwtSignatureAlgorithm::Ps512 => "ps512", + JwtSignatureAlgorithm::Rs256 => "rs256", + JwtSignatureAlgorithm::Rs384 => "rs384", + JwtSignatureAlgorithm::Rs512 => "rs512", + JwtSignatureAlgorithm::Hs256 => "hs256", + JwtSignatureAlgorithm::Hs384 => "hs384", + JwtSignatureAlgorithm::Hs512 => "hs512", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(JwtSignatureAlgorithm::Es256), + 1 => Some(JwtSignatureAlgorithm::Es384), + 2 => Some(JwtSignatureAlgorithm::Ps256), + 3 => Some(JwtSignatureAlgorithm::Ps384), + 4 => Some(JwtSignatureAlgorithm::Ps512), + 5 => Some(JwtSignatureAlgorithm::Rs256), + 6 => Some(JwtSignatureAlgorithm::Rs384), + 7 => Some(JwtSignatureAlgorithm::Rs512), + 8 => Some(JwtSignatureAlgorithm::Hs256), + 9 => Some(JwtSignatureAlgorithm::Hs384), + 10 => Some(JwtSignatureAlgorithm::Hs512), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for JwtSignatureAlgorithm { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for JwtSignatureAlgorithm { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for Locale { + fn parse(value: &str) -> Option { + hashify::map! { + value.as_bytes(), + Locale, + b"POSIX" => Locale::POSIX, + b"aa_DJ" => Locale::AaDJ, + b"aa_ER" => Locale::AaER, + b"aa_ER@saaho" => Locale::AaERSaaho, + b"aa_ET" => Locale::AaET, + b"af_ZA" => Locale::AfZA, + b"agr_PE" => Locale::AgrPE, + b"ak_GH" => Locale::AkGH, + b"am_ET" => Locale::AmET, + b"an_ES" => Locale::AnES, + b"anp_IN" => Locale::AnpIN, + b"ar_AE" => Locale::ArAE, + b"ar_BH" => Locale::ArBH, + b"ar_DZ" => Locale::ArDZ, + b"ar_EG" => Locale::ArEG, + b"ar_IN" => Locale::ArIN, + b"ar_IQ" => Locale::ArIQ, + b"ar_JO" => Locale::ArJO, + b"ar_KW" => Locale::ArKW, + b"ar_LB" => Locale::ArLB, + b"ar_LY" => Locale::ArLY, + b"ar_MA" => Locale::ArMA, + b"ar_OM" => Locale::ArOM, + b"ar_QA" => Locale::ArQA, + b"ar_SA" => Locale::ArSA, + b"ar_SD" => Locale::ArSD, + b"ar_SS" => Locale::ArSS, + b"ar_SY" => Locale::ArSY, + b"ar_TN" => Locale::ArTN, + b"ar_YE" => Locale::ArYE, + b"as_IN" => Locale::AsIN, + b"ast_ES" => Locale::AstES, + b"ayc_PE" => Locale::AycPE, + b"az_AZ" => Locale::AzAZ, + b"az_IR" => Locale::AzIR, + b"be_BY" => Locale::BeBY, + b"be_BY@latin" => Locale::BeBYLatin, + b"bem_ZM" => Locale::BemZM, + b"ber_DZ" => Locale::BerDZ, + b"ber_MA" => Locale::BerMA, + b"bg_BG" => Locale::BgBG, + b"bhb_IN" => Locale::BhbIN, + b"bho_IN" => Locale::BhoIN, + b"bho_NP" => Locale::BhoNP, + b"bi_VU" => Locale::BiVU, + b"bn_BD" => Locale::BnBD, + b"bn_IN" => Locale::BnIN, + b"bo_CN" => Locale::BoCN, + b"bo_IN" => Locale::BoIN, + b"br_FR" => Locale::BrFR, + b"br_FR@euro" => Locale::BrFREuro, + b"brx_IN" => Locale::BrxIN, + b"bs_BA" => Locale::BsBA, + b"byn_ER" => Locale::BynER, + b"ca_AD" => Locale::CaAD, + b"ca_ES" => Locale::CaES, + b"ca_ES@euro" => Locale::CaESEuro, + b"ca_ES@valencia" => Locale::CaESValencia, + b"ca_FR" => Locale::CaFR, + b"ca_IT" => Locale::CaIT, + b"ce_RU" => Locale::CeRU, + b"chr_US" => Locale::ChrUS, + b"cmn_TW" => Locale::CmnTW, + b"crh_UA" => Locale::CrhUA, + b"cs_CZ" => Locale::CsCZ, + b"csb_PL" => Locale::CsbPL, + b"cv_RU" => Locale::CvRU, + b"cy_GB" => Locale::CyGB, + b"da_DK" => Locale::DaDK, + b"de_AT" => Locale::DeAT, + b"de_AT@euro" => Locale::DeATEuro, + b"de_BE" => Locale::DeBE, + b"de_BE@euro" => Locale::DeBEEuro, + b"de_CH" => Locale::DeCH, + b"de_DE" => Locale::DeDE, + b"de_DE@euro" => Locale::DeDEEuro, + b"de_IT" => Locale::DeIT, + b"de_LI" => Locale::DeLI, + b"de_LU" => Locale::DeLU, + b"de_LU@euro" => Locale::DeLUEuro, + b"doi_IN" => Locale::DoiIN, + b"dsb_DE" => Locale::DsbDE, + b"dv_MV" => Locale::DvMV, + b"dz_BT" => Locale::DzBT, + b"el_CY" => Locale::ElCY, + b"el_GR" => Locale::ElGR, + b"el_GR@euro" => Locale::ElGREuro, + b"en_AG" => Locale::EnAG, + b"en_AU" => Locale::EnAU, + b"en_BW" => Locale::EnBW, + b"en_CA" => Locale::EnCA, + b"en_DK" => Locale::EnDK, + b"en_GB" => Locale::EnGB, + b"en_HK" => Locale::EnHK, + b"en_IE" => Locale::EnIE, + b"en_IE@euro" => Locale::EnIEEuro, + b"en_IL" => Locale::EnIL, + b"en_IN" => Locale::EnIN, + b"en_NG" => Locale::EnNG, + b"en_NZ" => Locale::EnNZ, + b"en_PH" => Locale::EnPH, + b"en_SC" => Locale::EnSC, + b"en_SG" => Locale::EnSG, + b"en_US" => Locale::EnUS, + b"en_ZA" => Locale::EnZA, + b"en_ZM" => Locale::EnZM, + b"en_ZW" => Locale::EnZW, + b"eo" => Locale::Eo, + b"es_AR" => Locale::EsAR, + b"es_BO" => Locale::EsBO, + b"es_CL" => Locale::EsCL, + b"es_CO" => Locale::EsCO, + b"es_CR" => Locale::EsCR, + b"es_CU" => Locale::EsCU, + b"es_DO" => Locale::EsDO, + b"es_EC" => Locale::EsEC, + b"es_ES" => Locale::EsES, + b"es_ES@euro" => Locale::EsESEuro, + b"es_GT" => Locale::EsGT, + b"es_HN" => Locale::EsHN, + b"es_MX" => Locale::EsMX, + b"es_NI" => Locale::EsNI, + b"es_PA" => Locale::EsPA, + b"es_PE" => Locale::EsPE, + b"es_PR" => Locale::EsPR, + b"es_PY" => Locale::EsPY, + b"es_SV" => Locale::EsSV, + b"es_US" => Locale::EsUS, + b"es_UY" => Locale::EsUY, + b"es_VE" => Locale::EsVE, + b"et_EE" => Locale::EtEE, + b"eu_ES" => Locale::EuES, + b"eu_ES@euro" => Locale::EuESEuro, + b"fa_IR" => Locale::FaIR, + b"ff_SN" => Locale::FfSN, + b"fi_FI" => Locale::FiFI, + b"fi_FI@euro" => Locale::FiFIEuro, + b"fil_PH" => Locale::FilPH, + b"fo_FO" => Locale::FoFO, + b"fr_BE" => Locale::FrBE, + b"fr_BE@euro" => Locale::FrBEEuro, + b"fr_CA" => Locale::FrCA, + b"fr_CH" => Locale::FrCH, + b"fr_FR" => Locale::FrFR, + b"fr_FR@euro" => Locale::FrFREuro, + b"fr_LU" => Locale::FrLU, + b"fr_LU@euro" => Locale::FrLUEuro, + b"fur_IT" => Locale::FurIT, + b"fy_DE" => Locale::FyDE, + b"fy_NL" => Locale::FyNL, + b"ga_IE" => Locale::GaIE, + b"ga_IE@euro" => Locale::GaIEEuro, + b"gd_GB" => Locale::GdGB, + b"gez_ER" => Locale::GezER, + b"gez_ER@abegede" => Locale::GezERAbegede, + b"gez_ET" => Locale::GezET, + b"gez_ET@abegede" => Locale::GezETAbegede, + b"gl_ES" => Locale::GlES, + b"gl_ES@euro" => Locale::GlESEuro, + b"gu_IN" => Locale::GuIN, + b"gv_GB" => Locale::GvGB, + b"ha_NG" => Locale::HaNG, + b"hak_TW" => Locale::HakTW, + b"he_IL" => Locale::HeIL, + b"hi_IN" => Locale::HiIN, + b"hif_FJ" => Locale::HifFJ, + b"hne_IN" => Locale::HneIN, + b"hr_HR" => Locale::HrHR, + b"hsb_DE" => Locale::HsbDE, + b"ht_HT" => Locale::HtHT, + b"hu_HU" => Locale::HuHU, + b"hy_AM" => Locale::HyAM, + b"ia_FR" => Locale::IaFR, + b"id_ID" => Locale::IdID, + b"ig_NG" => Locale::IgNG, + b"ik_CA" => Locale::IkCA, + b"is_IS" => Locale::IsIS, + b"it_CH" => Locale::ItCH, + b"it_IT" => Locale::ItIT, + b"it_IT@euro" => Locale::ItITEuro, + b"iu_CA" => Locale::IuCA, + b"ja_JP" => Locale::JaJP, + b"ka_GE" => Locale::KaGE, + b"kab_DZ" => Locale::KabDZ, + b"kk_KZ" => Locale::KkKZ, + b"kl_GL" => Locale::KlGL, + b"km_KH" => Locale::KmKH, + b"kn_IN" => Locale::KnIN, + b"ko_KR" => Locale::KoKR, + b"kok_IN" => Locale::KokIN, + b"ks_IN" => Locale::KsIN, + b"ks_IN@devanagari" => Locale::KsINDevanagari, + b"ku_TR" => Locale::KuTR, + b"kw_GB" => Locale::KwGB, + b"ky_KG" => Locale::KyKG, + b"lb_LU" => Locale::LbLU, + b"lg_UG" => Locale::LgUG, + b"li_BE" => Locale::LiBE, + b"li_NL" => Locale::LiNL, + b"lij_IT" => Locale::LijIT, + b"ln_CD" => Locale::LnCD, + b"lo_LA" => Locale::LoLA, + b"lt_LT" => Locale::LtLT, + b"lv_LV" => Locale::LvLV, + b"lzh_TW" => Locale::LzhTW, + b"mag_IN" => Locale::MagIN, + b"mai_IN" => Locale::MaiIN, + b"mai_NP" => Locale::MaiNP, + b"mfe_MU" => Locale::MfeMU, + b"mg_MG" => Locale::MgMG, + b"mhr_RU" => Locale::MhrRU, + b"mi_NZ" => Locale::MiNZ, + b"miq_NI" => Locale::MiqNI, + b"mjw_IN" => Locale::MjwIN, + b"mk_MK" => Locale::MkMK, + b"ml_IN" => Locale::MlIN, + b"mn_MN" => Locale::MnMN, + b"mni_IN" => Locale::MniIN, + b"mnw_MM" => Locale::MnwMM, + b"mr_IN" => Locale::MrIN, + b"ms_MY" => Locale::MsMY, + b"mt_MT" => Locale::MtMT, + b"my_MM" => Locale::MyMM, + b"nan_TW" => Locale::NanTW, + b"nan_TW@latin" => Locale::NanTWLatin, + b"nb_NO" => Locale::NbNO, + b"nds_DE" => Locale::NdsDE, + b"nds_NL" => Locale::NdsNL, + b"ne_NP" => Locale::NeNP, + b"nhn_MX" => Locale::NhnMX, + b"niu_NU" => Locale::NiuNU, + b"niu_NZ" => Locale::NiuNZ, + b"nl_AW" => Locale::NlAW, + b"nl_BE" => Locale::NlBE, + b"nl_BE@euro" => Locale::NlBEEuro, + b"nl_NL" => Locale::NlNL, + b"nl_NL@euro" => Locale::NlNLEuro, + b"nn_NO" => Locale::NnNO, + b"nr_ZA" => Locale::NrZA, + b"nso_ZA" => Locale::NsoZA, + b"oc_FR" => Locale::OcFR, + b"om_ET" => Locale::OmET, + b"om_KE" => Locale::OmKE, + b"or_IN" => Locale::OrIN, + b"os_RU" => Locale::OsRU, + b"pa_IN" => Locale::PaIN, + b"pa_PK" => Locale::PaPK, + b"pap_AW" => Locale::PapAW, + b"pap_CW" => Locale::PapCW, + b"pl_PL" => Locale::PlPL, + b"ps_AF" => Locale::PsAF, + b"pt_BR" => Locale::PtBR, + b"pt_PT" => Locale::PtPT, + b"pt_PT@euro" => Locale::PtPTEuro, + b"quz_PE" => Locale::QuzPE, + b"raj_IN" => Locale::RajIN, + b"ro_RO" => Locale::RoRO, + b"ru_RU" => Locale::RuRU, + b"ru_UA" => Locale::RuUA, + b"rw_RW" => Locale::RwRW, + b"sa_IN" => Locale::SaIN, + b"sah_RU" => Locale::SahRU, + b"sat_IN" => Locale::SatIN, + b"sc_IT" => Locale::ScIT, + b"sd_IN" => Locale::SdIN, + b"sd_IN@devanagari" => Locale::SdINDevanagari, + b"se_NO" => Locale::SeNO, + b"sgs_LT" => Locale::SgsLT, + b"shn_MM" => Locale::ShnMM, + b"shs_CA" => Locale::ShsCA, + b"si_LK" => Locale::SiLK, + b"sid_ET" => Locale::SidET, + b"sk_SK" => Locale::SkSK, + b"sl_SI" => Locale::SlSI, + b"sm_WS" => Locale::SmWS, + b"so_DJ" => Locale::SoDJ, + b"so_ET" => Locale::SoET, + b"so_KE" => Locale::SoKE, + b"so_SO" => Locale::SoSO, + b"sq_AL" => Locale::SqAL, + b"sq_MK" => Locale::SqMK, + b"sr_ME" => Locale::SrME, + b"sr_RS" => Locale::SrRS, + b"sr_RS@latin" => Locale::SrRSLatin, + b"ss_ZA" => Locale::SsZA, + b"st_ZA" => Locale::StZA, + b"sv_FI" => Locale::SvFI, + b"sv_FI@euro" => Locale::SvFIEuro, + b"sv_SE" => Locale::SvSE, + b"sw_KE" => Locale::SwKE, + b"sw_TZ" => Locale::SwTZ, + b"szl_PL" => Locale::SzlPL, + b"ta_IN" => Locale::TaIN, + b"ta_LK" => Locale::TaLK, + b"tcy_IN" => Locale::TcyIN, + b"te_IN" => Locale::TeIN, + b"tg_TJ" => Locale::TgTJ, + b"th_TH" => Locale::ThTH, + b"the_NP" => Locale::TheNP, + b"ti_ER" => Locale::TiER, + b"ti_ET" => Locale::TiET, + b"tig_ER" => Locale::TigER, + b"tk_TM" => Locale::TkTM, + b"tl_PH" => Locale::TlPH, + b"tn_ZA" => Locale::TnZA, + b"to_TO" => Locale::ToTO, + b"tpi_PG" => Locale::TpiPG, + b"tr_CY" => Locale::TrCY, + b"tr_TR" => Locale::TrTR, + b"ts_ZA" => Locale::TsZA, + b"tt_RU" => Locale::TtRU, + b"tt_RU@iqtelif" => Locale::TtRUIqtelif, + b"ug_CN" => Locale::UgCN, + b"uk_UA" => Locale::UkUA, + b"unm_US" => Locale::UnmUS, + b"ur_IN" => Locale::UrIN, + b"ur_PK" => Locale::UrPK, + b"uz_UZ" => Locale::UzUZ, + b"uz_UZ@cyrillic" => Locale::UzUZCyrillic, + b"ve_ZA" => Locale::VeZA, + b"vi_VN" => Locale::ViVN, + b"wa_BE" => Locale::WaBE, + b"wa_BE@euro" => Locale::WaBEEuro, + b"wae_CH" => Locale::WaeCH, + b"wal_ET" => Locale::WalET, + b"wo_SN" => Locale::WoSN, + b"xh_ZA" => Locale::XhZA, + b"yi_US" => Locale::YiUS, + b"yo_NG" => Locale::YoNG, + b"yue_HK" => Locale::YueHK, + b"yuw_PG" => Locale::YuwPG, + b"zh_CN" => Locale::ZhCN, + b"zh_HK" => Locale::ZhHK, + b"zh_SG" => Locale::ZhSG, + b"zh_TW" => Locale::ZhTW, + b"zu_ZA" => Locale::ZuZA, + } + .copied() + } + + fn as_str(&self) -> &'static str { + match self { + Locale::POSIX => "POSIX", + Locale::AaDJ => "aa_DJ", + Locale::AaER => "aa_ER", + Locale::AaERSaaho => "aa_ER@saaho", + Locale::AaET => "aa_ET", + Locale::AfZA => "af_ZA", + Locale::AgrPE => "agr_PE", + Locale::AkGH => "ak_GH", + Locale::AmET => "am_ET", + Locale::AnES => "an_ES", + Locale::AnpIN => "anp_IN", + Locale::ArAE => "ar_AE", + Locale::ArBH => "ar_BH", + Locale::ArDZ => "ar_DZ", + Locale::ArEG => "ar_EG", + Locale::ArIN => "ar_IN", + Locale::ArIQ => "ar_IQ", + Locale::ArJO => "ar_JO", + Locale::ArKW => "ar_KW", + Locale::ArLB => "ar_LB", + Locale::ArLY => "ar_LY", + Locale::ArMA => "ar_MA", + Locale::ArOM => "ar_OM", + Locale::ArQA => "ar_QA", + Locale::ArSA => "ar_SA", + Locale::ArSD => "ar_SD", + Locale::ArSS => "ar_SS", + Locale::ArSY => "ar_SY", + Locale::ArTN => "ar_TN", + Locale::ArYE => "ar_YE", + Locale::AsIN => "as_IN", + Locale::AstES => "ast_ES", + Locale::AycPE => "ayc_PE", + Locale::AzAZ => "az_AZ", + Locale::AzIR => "az_IR", + Locale::BeBY => "be_BY", + Locale::BeBYLatin => "be_BY@latin", + Locale::BemZM => "bem_ZM", + Locale::BerDZ => "ber_DZ", + Locale::BerMA => "ber_MA", + Locale::BgBG => "bg_BG", + Locale::BhbIN => "bhb_IN", + Locale::BhoIN => "bho_IN", + Locale::BhoNP => "bho_NP", + Locale::BiVU => "bi_VU", + Locale::BnBD => "bn_BD", + Locale::BnIN => "bn_IN", + Locale::BoCN => "bo_CN", + Locale::BoIN => "bo_IN", + Locale::BrFR => "br_FR", + Locale::BrFREuro => "br_FR@euro", + Locale::BrxIN => "brx_IN", + Locale::BsBA => "bs_BA", + Locale::BynER => "byn_ER", + Locale::CaAD => "ca_AD", + Locale::CaES => "ca_ES", + Locale::CaESEuro => "ca_ES@euro", + Locale::CaESValencia => "ca_ES@valencia", + Locale::CaFR => "ca_FR", + Locale::CaIT => "ca_IT", + Locale::CeRU => "ce_RU", + Locale::ChrUS => "chr_US", + Locale::CmnTW => "cmn_TW", + Locale::CrhUA => "crh_UA", + Locale::CsCZ => "cs_CZ", + Locale::CsbPL => "csb_PL", + Locale::CvRU => "cv_RU", + Locale::CyGB => "cy_GB", + Locale::DaDK => "da_DK", + Locale::DeAT => "de_AT", + Locale::DeATEuro => "de_AT@euro", + Locale::DeBE => "de_BE", + Locale::DeBEEuro => "de_BE@euro", + Locale::DeCH => "de_CH", + Locale::DeDE => "de_DE", + Locale::DeDEEuro => "de_DE@euro", + Locale::DeIT => "de_IT", + Locale::DeLI => "de_LI", + Locale::DeLU => "de_LU", + Locale::DeLUEuro => "de_LU@euro", + Locale::DoiIN => "doi_IN", + Locale::DsbDE => "dsb_DE", + Locale::DvMV => "dv_MV", + Locale::DzBT => "dz_BT", + Locale::ElCY => "el_CY", + Locale::ElGR => "el_GR", + Locale::ElGREuro => "el_GR@euro", + Locale::EnAG => "en_AG", + Locale::EnAU => "en_AU", + Locale::EnBW => "en_BW", + Locale::EnCA => "en_CA", + Locale::EnDK => "en_DK", + Locale::EnGB => "en_GB", + Locale::EnHK => "en_HK", + Locale::EnIE => "en_IE", + Locale::EnIEEuro => "en_IE@euro", + Locale::EnIL => "en_IL", + Locale::EnIN => "en_IN", + Locale::EnNG => "en_NG", + Locale::EnNZ => "en_NZ", + Locale::EnPH => "en_PH", + Locale::EnSC => "en_SC", + Locale::EnSG => "en_SG", + Locale::EnUS => "en_US", + Locale::EnZA => "en_ZA", + Locale::EnZM => "en_ZM", + Locale::EnZW => "en_ZW", + Locale::Eo => "eo", + Locale::EsAR => "es_AR", + Locale::EsBO => "es_BO", + Locale::EsCL => "es_CL", + Locale::EsCO => "es_CO", + Locale::EsCR => "es_CR", + Locale::EsCU => "es_CU", + Locale::EsDO => "es_DO", + Locale::EsEC => "es_EC", + Locale::EsES => "es_ES", + Locale::EsESEuro => "es_ES@euro", + Locale::EsGT => "es_GT", + Locale::EsHN => "es_HN", + Locale::EsMX => "es_MX", + Locale::EsNI => "es_NI", + Locale::EsPA => "es_PA", + Locale::EsPE => "es_PE", + Locale::EsPR => "es_PR", + Locale::EsPY => "es_PY", + Locale::EsSV => "es_SV", + Locale::EsUS => "es_US", + Locale::EsUY => "es_UY", + Locale::EsVE => "es_VE", + Locale::EtEE => "et_EE", + Locale::EuES => "eu_ES", + Locale::EuESEuro => "eu_ES@euro", + Locale::FaIR => "fa_IR", + Locale::FfSN => "ff_SN", + Locale::FiFI => "fi_FI", + Locale::FiFIEuro => "fi_FI@euro", + Locale::FilPH => "fil_PH", + Locale::FoFO => "fo_FO", + Locale::FrBE => "fr_BE", + Locale::FrBEEuro => "fr_BE@euro", + Locale::FrCA => "fr_CA", + Locale::FrCH => "fr_CH", + Locale::FrFR => "fr_FR", + Locale::FrFREuro => "fr_FR@euro", + Locale::FrLU => "fr_LU", + Locale::FrLUEuro => "fr_LU@euro", + Locale::FurIT => "fur_IT", + Locale::FyDE => "fy_DE", + Locale::FyNL => "fy_NL", + Locale::GaIE => "ga_IE", + Locale::GaIEEuro => "ga_IE@euro", + Locale::GdGB => "gd_GB", + Locale::GezER => "gez_ER", + Locale::GezERAbegede => "gez_ER@abegede", + Locale::GezET => "gez_ET", + Locale::GezETAbegede => "gez_ET@abegede", + Locale::GlES => "gl_ES", + Locale::GlESEuro => "gl_ES@euro", + Locale::GuIN => "gu_IN", + Locale::GvGB => "gv_GB", + Locale::HaNG => "ha_NG", + Locale::HakTW => "hak_TW", + Locale::HeIL => "he_IL", + Locale::HiIN => "hi_IN", + Locale::HifFJ => "hif_FJ", + Locale::HneIN => "hne_IN", + Locale::HrHR => "hr_HR", + Locale::HsbDE => "hsb_DE", + Locale::HtHT => "ht_HT", + Locale::HuHU => "hu_HU", + Locale::HyAM => "hy_AM", + Locale::IaFR => "ia_FR", + Locale::IdID => "id_ID", + Locale::IgNG => "ig_NG", + Locale::IkCA => "ik_CA", + Locale::IsIS => "is_IS", + Locale::ItCH => "it_CH", + Locale::ItIT => "it_IT", + Locale::ItITEuro => "it_IT@euro", + Locale::IuCA => "iu_CA", + Locale::JaJP => "ja_JP", + Locale::KaGE => "ka_GE", + Locale::KabDZ => "kab_DZ", + Locale::KkKZ => "kk_KZ", + Locale::KlGL => "kl_GL", + Locale::KmKH => "km_KH", + Locale::KnIN => "kn_IN", + Locale::KoKR => "ko_KR", + Locale::KokIN => "kok_IN", + Locale::KsIN => "ks_IN", + Locale::KsINDevanagari => "ks_IN@devanagari", + Locale::KuTR => "ku_TR", + Locale::KwGB => "kw_GB", + Locale::KyKG => "ky_KG", + Locale::LbLU => "lb_LU", + Locale::LgUG => "lg_UG", + Locale::LiBE => "li_BE", + Locale::LiNL => "li_NL", + Locale::LijIT => "lij_IT", + Locale::LnCD => "ln_CD", + Locale::LoLA => "lo_LA", + Locale::LtLT => "lt_LT", + Locale::LvLV => "lv_LV", + Locale::LzhTW => "lzh_TW", + Locale::MagIN => "mag_IN", + Locale::MaiIN => "mai_IN", + Locale::MaiNP => "mai_NP", + Locale::MfeMU => "mfe_MU", + Locale::MgMG => "mg_MG", + Locale::MhrRU => "mhr_RU", + Locale::MiNZ => "mi_NZ", + Locale::MiqNI => "miq_NI", + Locale::MjwIN => "mjw_IN", + Locale::MkMK => "mk_MK", + Locale::MlIN => "ml_IN", + Locale::MnMN => "mn_MN", + Locale::MniIN => "mni_IN", + Locale::MnwMM => "mnw_MM", + Locale::MrIN => "mr_IN", + Locale::MsMY => "ms_MY", + Locale::MtMT => "mt_MT", + Locale::MyMM => "my_MM", + Locale::NanTW => "nan_TW", + Locale::NanTWLatin => "nan_TW@latin", + Locale::NbNO => "nb_NO", + Locale::NdsDE => "nds_DE", + Locale::NdsNL => "nds_NL", + Locale::NeNP => "ne_NP", + Locale::NhnMX => "nhn_MX", + Locale::NiuNU => "niu_NU", + Locale::NiuNZ => "niu_NZ", + Locale::NlAW => "nl_AW", + Locale::NlBE => "nl_BE", + Locale::NlBEEuro => "nl_BE@euro", + Locale::NlNL => "nl_NL", + Locale::NlNLEuro => "nl_NL@euro", + Locale::NnNO => "nn_NO", + Locale::NrZA => "nr_ZA", + Locale::NsoZA => "nso_ZA", + Locale::OcFR => "oc_FR", + Locale::OmET => "om_ET", + Locale::OmKE => "om_KE", + Locale::OrIN => "or_IN", + Locale::OsRU => "os_RU", + Locale::PaIN => "pa_IN", + Locale::PaPK => "pa_PK", + Locale::PapAW => "pap_AW", + Locale::PapCW => "pap_CW", + Locale::PlPL => "pl_PL", + Locale::PsAF => "ps_AF", + Locale::PtBR => "pt_BR", + Locale::PtPT => "pt_PT", + Locale::PtPTEuro => "pt_PT@euro", + Locale::QuzPE => "quz_PE", + Locale::RajIN => "raj_IN", + Locale::RoRO => "ro_RO", + Locale::RuRU => "ru_RU", + Locale::RuUA => "ru_UA", + Locale::RwRW => "rw_RW", + Locale::SaIN => "sa_IN", + Locale::SahRU => "sah_RU", + Locale::SatIN => "sat_IN", + Locale::ScIT => "sc_IT", + Locale::SdIN => "sd_IN", + Locale::SdINDevanagari => "sd_IN@devanagari", + Locale::SeNO => "se_NO", + Locale::SgsLT => "sgs_LT", + Locale::ShnMM => "shn_MM", + Locale::ShsCA => "shs_CA", + Locale::SiLK => "si_LK", + Locale::SidET => "sid_ET", + Locale::SkSK => "sk_SK", + Locale::SlSI => "sl_SI", + Locale::SmWS => "sm_WS", + Locale::SoDJ => "so_DJ", + Locale::SoET => "so_ET", + Locale::SoKE => "so_KE", + Locale::SoSO => "so_SO", + Locale::SqAL => "sq_AL", + Locale::SqMK => "sq_MK", + Locale::SrME => "sr_ME", + Locale::SrRS => "sr_RS", + Locale::SrRSLatin => "sr_RS@latin", + Locale::SsZA => "ss_ZA", + Locale::StZA => "st_ZA", + Locale::SvFI => "sv_FI", + Locale::SvFIEuro => "sv_FI@euro", + Locale::SvSE => "sv_SE", + Locale::SwKE => "sw_KE", + Locale::SwTZ => "sw_TZ", + Locale::SzlPL => "szl_PL", + Locale::TaIN => "ta_IN", + Locale::TaLK => "ta_LK", + Locale::TcyIN => "tcy_IN", + Locale::TeIN => "te_IN", + Locale::TgTJ => "tg_TJ", + Locale::ThTH => "th_TH", + Locale::TheNP => "the_NP", + Locale::TiER => "ti_ER", + Locale::TiET => "ti_ET", + Locale::TigER => "tig_ER", + Locale::TkTM => "tk_TM", + Locale::TlPH => "tl_PH", + Locale::TnZA => "tn_ZA", + Locale::ToTO => "to_TO", + Locale::TpiPG => "tpi_PG", + Locale::TrCY => "tr_CY", + Locale::TrTR => "tr_TR", + Locale::TsZA => "ts_ZA", + Locale::TtRU => "tt_RU", + Locale::TtRUIqtelif => "tt_RU@iqtelif", + Locale::UgCN => "ug_CN", + Locale::UkUA => "uk_UA", + Locale::UnmUS => "unm_US", + Locale::UrIN => "ur_IN", + Locale::UrPK => "ur_PK", + Locale::UzUZ => "uz_UZ", + Locale::UzUZCyrillic => "uz_UZ@cyrillic", + Locale::VeZA => "ve_ZA", + Locale::ViVN => "vi_VN", + Locale::WaBE => "wa_BE", + Locale::WaBEEuro => "wa_BE@euro", + Locale::WaeCH => "wae_CH", + Locale::WalET => "wal_ET", + Locale::WoSN => "wo_SN", + Locale::XhZA => "xh_ZA", + Locale::YiUS => "yi_US", + Locale::YoNG => "yo_NG", + Locale::YueHK => "yue_HK", + Locale::YuwPG => "yuw_PG", + Locale::ZhCN => "zh_CN", + Locale::ZhHK => "zh_HK", + Locale::ZhSG => "zh_SG", + Locale::ZhTW => "zh_TW", + Locale::ZuZA => "zu_ZA", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(Locale::POSIX), + 1 => Some(Locale::AaDJ), + 2 => Some(Locale::AaER), + 3 => Some(Locale::AaERSaaho), + 4 => Some(Locale::AaET), + 5 => Some(Locale::AfZA), + 6 => Some(Locale::AgrPE), + 7 => Some(Locale::AkGH), + 8 => Some(Locale::AmET), + 9 => Some(Locale::AnES), + 10 => Some(Locale::AnpIN), + 11 => Some(Locale::ArAE), + 12 => Some(Locale::ArBH), + 13 => Some(Locale::ArDZ), + 14 => Some(Locale::ArEG), + 15 => Some(Locale::ArIN), + 16 => Some(Locale::ArIQ), + 17 => Some(Locale::ArJO), + 18 => Some(Locale::ArKW), + 19 => Some(Locale::ArLB), + 20 => Some(Locale::ArLY), + 21 => Some(Locale::ArMA), + 22 => Some(Locale::ArOM), + 23 => Some(Locale::ArQA), + 24 => Some(Locale::ArSA), + 25 => Some(Locale::ArSD), + 26 => Some(Locale::ArSS), + 27 => Some(Locale::ArSY), + 28 => Some(Locale::ArTN), + 29 => Some(Locale::ArYE), + 30 => Some(Locale::AsIN), + 31 => Some(Locale::AstES), + 32 => Some(Locale::AycPE), + 33 => Some(Locale::AzAZ), + 34 => Some(Locale::AzIR), + 35 => Some(Locale::BeBY), + 36 => Some(Locale::BeBYLatin), + 37 => Some(Locale::BemZM), + 38 => Some(Locale::BerDZ), + 39 => Some(Locale::BerMA), + 40 => Some(Locale::BgBG), + 41 => Some(Locale::BhbIN), + 42 => Some(Locale::BhoIN), + 43 => Some(Locale::BhoNP), + 44 => Some(Locale::BiVU), + 45 => Some(Locale::BnBD), + 46 => Some(Locale::BnIN), + 47 => Some(Locale::BoCN), + 48 => Some(Locale::BoIN), + 49 => Some(Locale::BrFR), + 50 => Some(Locale::BrFREuro), + 51 => Some(Locale::BrxIN), + 52 => Some(Locale::BsBA), + 53 => Some(Locale::BynER), + 54 => Some(Locale::CaAD), + 55 => Some(Locale::CaES), + 56 => Some(Locale::CaESEuro), + 57 => Some(Locale::CaESValencia), + 58 => Some(Locale::CaFR), + 59 => Some(Locale::CaIT), + 60 => Some(Locale::CeRU), + 61 => Some(Locale::ChrUS), + 62 => Some(Locale::CmnTW), + 63 => Some(Locale::CrhUA), + 64 => Some(Locale::CsCZ), + 65 => Some(Locale::CsbPL), + 66 => Some(Locale::CvRU), + 67 => Some(Locale::CyGB), + 68 => Some(Locale::DaDK), + 69 => Some(Locale::DeAT), + 70 => Some(Locale::DeATEuro), + 71 => Some(Locale::DeBE), + 72 => Some(Locale::DeBEEuro), + 73 => Some(Locale::DeCH), + 74 => Some(Locale::DeDE), + 75 => Some(Locale::DeDEEuro), + 76 => Some(Locale::DeIT), + 77 => Some(Locale::DeLI), + 78 => Some(Locale::DeLU), + 79 => Some(Locale::DeLUEuro), + 80 => Some(Locale::DoiIN), + 81 => Some(Locale::DsbDE), + 82 => Some(Locale::DvMV), + 83 => Some(Locale::DzBT), + 84 => Some(Locale::ElCY), + 85 => Some(Locale::ElGR), + 86 => Some(Locale::ElGREuro), + 87 => Some(Locale::EnAG), + 88 => Some(Locale::EnAU), + 89 => Some(Locale::EnBW), + 90 => Some(Locale::EnCA), + 91 => Some(Locale::EnDK), + 92 => Some(Locale::EnGB), + 93 => Some(Locale::EnHK), + 94 => Some(Locale::EnIE), + 95 => Some(Locale::EnIEEuro), + 96 => Some(Locale::EnIL), + 97 => Some(Locale::EnIN), + 98 => Some(Locale::EnNG), + 99 => Some(Locale::EnNZ), + 100 => Some(Locale::EnPH), + 101 => Some(Locale::EnSC), + 102 => Some(Locale::EnSG), + 103 => Some(Locale::EnUS), + 104 => Some(Locale::EnZA), + 105 => Some(Locale::EnZM), + 106 => Some(Locale::EnZW), + 107 => Some(Locale::Eo), + 108 => Some(Locale::EsAR), + 109 => Some(Locale::EsBO), + 110 => Some(Locale::EsCL), + 111 => Some(Locale::EsCO), + 112 => Some(Locale::EsCR), + 113 => Some(Locale::EsCU), + 114 => Some(Locale::EsDO), + 115 => Some(Locale::EsEC), + 116 => Some(Locale::EsES), + 117 => Some(Locale::EsESEuro), + 118 => Some(Locale::EsGT), + 119 => Some(Locale::EsHN), + 120 => Some(Locale::EsMX), + 121 => Some(Locale::EsNI), + 122 => Some(Locale::EsPA), + 123 => Some(Locale::EsPE), + 124 => Some(Locale::EsPR), + 125 => Some(Locale::EsPY), + 126 => Some(Locale::EsSV), + 127 => Some(Locale::EsUS), + 128 => Some(Locale::EsUY), + 129 => Some(Locale::EsVE), + 130 => Some(Locale::EtEE), + 131 => Some(Locale::EuES), + 132 => Some(Locale::EuESEuro), + 133 => Some(Locale::FaIR), + 134 => Some(Locale::FfSN), + 135 => Some(Locale::FiFI), + 136 => Some(Locale::FiFIEuro), + 137 => Some(Locale::FilPH), + 138 => Some(Locale::FoFO), + 139 => Some(Locale::FrBE), + 140 => Some(Locale::FrBEEuro), + 141 => Some(Locale::FrCA), + 142 => Some(Locale::FrCH), + 143 => Some(Locale::FrFR), + 144 => Some(Locale::FrFREuro), + 145 => Some(Locale::FrLU), + 146 => Some(Locale::FrLUEuro), + 147 => Some(Locale::FurIT), + 148 => Some(Locale::FyDE), + 149 => Some(Locale::FyNL), + 150 => Some(Locale::GaIE), + 151 => Some(Locale::GaIEEuro), + 152 => Some(Locale::GdGB), + 153 => Some(Locale::GezER), + 154 => Some(Locale::GezERAbegede), + 155 => Some(Locale::GezET), + 156 => Some(Locale::GezETAbegede), + 157 => Some(Locale::GlES), + 158 => Some(Locale::GlESEuro), + 159 => Some(Locale::GuIN), + 160 => Some(Locale::GvGB), + 161 => Some(Locale::HaNG), + 162 => Some(Locale::HakTW), + 163 => Some(Locale::HeIL), + 164 => Some(Locale::HiIN), + 165 => Some(Locale::HifFJ), + 166 => Some(Locale::HneIN), + 167 => Some(Locale::HrHR), + 168 => Some(Locale::HsbDE), + 169 => Some(Locale::HtHT), + 170 => Some(Locale::HuHU), + 171 => Some(Locale::HyAM), + 172 => Some(Locale::IaFR), + 173 => Some(Locale::IdID), + 174 => Some(Locale::IgNG), + 175 => Some(Locale::IkCA), + 176 => Some(Locale::IsIS), + 177 => Some(Locale::ItCH), + 178 => Some(Locale::ItIT), + 179 => Some(Locale::ItITEuro), + 180 => Some(Locale::IuCA), + 181 => Some(Locale::JaJP), + 182 => Some(Locale::KaGE), + 183 => Some(Locale::KabDZ), + 184 => Some(Locale::KkKZ), + 185 => Some(Locale::KlGL), + 186 => Some(Locale::KmKH), + 187 => Some(Locale::KnIN), + 188 => Some(Locale::KoKR), + 189 => Some(Locale::KokIN), + 190 => Some(Locale::KsIN), + 191 => Some(Locale::KsINDevanagari), + 192 => Some(Locale::KuTR), + 193 => Some(Locale::KwGB), + 194 => Some(Locale::KyKG), + 195 => Some(Locale::LbLU), + 196 => Some(Locale::LgUG), + 197 => Some(Locale::LiBE), + 198 => Some(Locale::LiNL), + 199 => Some(Locale::LijIT), + 200 => Some(Locale::LnCD), + 201 => Some(Locale::LoLA), + 202 => Some(Locale::LtLT), + 203 => Some(Locale::LvLV), + 204 => Some(Locale::LzhTW), + 205 => Some(Locale::MagIN), + 206 => Some(Locale::MaiIN), + 207 => Some(Locale::MaiNP), + 208 => Some(Locale::MfeMU), + 209 => Some(Locale::MgMG), + 210 => Some(Locale::MhrRU), + 211 => Some(Locale::MiNZ), + 212 => Some(Locale::MiqNI), + 213 => Some(Locale::MjwIN), + 214 => Some(Locale::MkMK), + 215 => Some(Locale::MlIN), + 216 => Some(Locale::MnMN), + 217 => Some(Locale::MniIN), + 218 => Some(Locale::MnwMM), + 219 => Some(Locale::MrIN), + 220 => Some(Locale::MsMY), + 221 => Some(Locale::MtMT), + 222 => Some(Locale::MyMM), + 223 => Some(Locale::NanTW), + 224 => Some(Locale::NanTWLatin), + 225 => Some(Locale::NbNO), + 226 => Some(Locale::NdsDE), + 227 => Some(Locale::NdsNL), + 228 => Some(Locale::NeNP), + 229 => Some(Locale::NhnMX), + 230 => Some(Locale::NiuNU), + 231 => Some(Locale::NiuNZ), + 232 => Some(Locale::NlAW), + 233 => Some(Locale::NlBE), + 234 => Some(Locale::NlBEEuro), + 235 => Some(Locale::NlNL), + 236 => Some(Locale::NlNLEuro), + 237 => Some(Locale::NnNO), + 238 => Some(Locale::NrZA), + 239 => Some(Locale::NsoZA), + 240 => Some(Locale::OcFR), + 241 => Some(Locale::OmET), + 242 => Some(Locale::OmKE), + 243 => Some(Locale::OrIN), + 244 => Some(Locale::OsRU), + 245 => Some(Locale::PaIN), + 246 => Some(Locale::PaPK), + 247 => Some(Locale::PapAW), + 248 => Some(Locale::PapCW), + 249 => Some(Locale::PlPL), + 250 => Some(Locale::PsAF), + 251 => Some(Locale::PtBR), + 252 => Some(Locale::PtPT), + 253 => Some(Locale::PtPTEuro), + 254 => Some(Locale::QuzPE), + 255 => Some(Locale::RajIN), + 256 => Some(Locale::RoRO), + 257 => Some(Locale::RuRU), + 258 => Some(Locale::RuUA), + 259 => Some(Locale::RwRW), + 260 => Some(Locale::SaIN), + 261 => Some(Locale::SahRU), + 262 => Some(Locale::SatIN), + 263 => Some(Locale::ScIT), + 264 => Some(Locale::SdIN), + 265 => Some(Locale::SdINDevanagari), + 266 => Some(Locale::SeNO), + 267 => Some(Locale::SgsLT), + 268 => Some(Locale::ShnMM), + 269 => Some(Locale::ShsCA), + 270 => Some(Locale::SiLK), + 271 => Some(Locale::SidET), + 272 => Some(Locale::SkSK), + 273 => Some(Locale::SlSI), + 274 => Some(Locale::SmWS), + 275 => Some(Locale::SoDJ), + 276 => Some(Locale::SoET), + 277 => Some(Locale::SoKE), + 278 => Some(Locale::SoSO), + 279 => Some(Locale::SqAL), + 280 => Some(Locale::SqMK), + 281 => Some(Locale::SrME), + 282 => Some(Locale::SrRS), + 283 => Some(Locale::SrRSLatin), + 284 => Some(Locale::SsZA), + 285 => Some(Locale::StZA), + 286 => Some(Locale::SvFI), + 287 => Some(Locale::SvFIEuro), + 288 => Some(Locale::SvSE), + 289 => Some(Locale::SwKE), + 290 => Some(Locale::SwTZ), + 291 => Some(Locale::SzlPL), + 292 => Some(Locale::TaIN), + 293 => Some(Locale::TaLK), + 294 => Some(Locale::TcyIN), + 295 => Some(Locale::TeIN), + 296 => Some(Locale::TgTJ), + 297 => Some(Locale::ThTH), + 298 => Some(Locale::TheNP), + 299 => Some(Locale::TiER), + 300 => Some(Locale::TiET), + 301 => Some(Locale::TigER), + 302 => Some(Locale::TkTM), + 303 => Some(Locale::TlPH), + 304 => Some(Locale::TnZA), + 305 => Some(Locale::ToTO), + 306 => Some(Locale::TpiPG), + 307 => Some(Locale::TrCY), + 308 => Some(Locale::TrTR), + 309 => Some(Locale::TsZA), + 310 => Some(Locale::TtRU), + 311 => Some(Locale::TtRUIqtelif), + 312 => Some(Locale::UgCN), + 313 => Some(Locale::UkUA), + 314 => Some(Locale::UnmUS), + 315 => Some(Locale::UrIN), + 316 => Some(Locale::UrPK), + 317 => Some(Locale::UzUZ), + 318 => Some(Locale::UzUZCyrillic), + 319 => Some(Locale::VeZA), + 320 => Some(Locale::ViVN), + 321 => Some(Locale::WaBE), + 322 => Some(Locale::WaBEEuro), + 323 => Some(Locale::WaeCH), + 324 => Some(Locale::WalET), + 325 => Some(Locale::WoSN), + 326 => Some(Locale::XhZA), + 327 => Some(Locale::YiUS), + 328 => Some(Locale::YoNG), + 329 => Some(Locale::YueHK), + 330 => Some(Locale::YuwPG), + 331 => Some(Locale::ZhCN), + 332 => Some(Locale::ZhHK), + 333 => Some(Locale::ZhSG), + 334 => Some(Locale::ZhTW), + 335 => Some(Locale::ZuZA), + _ => None, + } + } + + const COUNT: usize = 336; +} + +impl serde::Serialize for Locale { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for Locale { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for LogRotateFrequency { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"daily" => LogRotateFrequency::Daily, + b"hourly" => LogRotateFrequency::Hourly, + b"minutely" => LogRotateFrequency::Minutely, + b"never" => LogRotateFrequency::Never, + } + } + + fn as_str(&self) -> &'static str { + match self { + LogRotateFrequency::Daily => "daily", + LogRotateFrequency::Hourly => "hourly", + LogRotateFrequency::Minutely => "minutely", + LogRotateFrequency::Never => "never", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(LogRotateFrequency::Daily), + 1 => Some(LogRotateFrequency::Hourly), + 2 => Some(LogRotateFrequency::Minutely), + 3 => Some(LogRotateFrequency::Never), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for LogRotateFrequency { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for LogRotateFrequency { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for LookupStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"PostgreSql" => LookupStoreType::PostgreSql, + b"MySql" => LookupStoreType::MySql, + b"Sqlite" => LookupStoreType::Sqlite, + b"Sharded" => LookupStoreType::Sharded, + b"Redis" => LookupStoreType::Redis, + b"RedisCluster" => LookupStoreType::RedisCluster, + } + } + + fn as_str(&self) -> &'static str { + match self { + LookupStoreType::PostgreSql => "PostgreSql", + LookupStoreType::MySql => "MySql", + LookupStoreType::Sqlite => "Sqlite", + LookupStoreType::Sharded => "Sharded", + LookupStoreType::Redis => "Redis", + LookupStoreType::RedisCluster => "RedisCluster", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(LookupStoreType::PostgreSql), + 1 => Some(LookupStoreType::MySql), + 2 => Some(LookupStoreType::Sqlite), + 3 => Some(LookupStoreType::Sharded), + 4 => Some(LookupStoreType::Redis), + 5 => Some(LookupStoreType::RedisCluster), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for LookupStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for LookupStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MessageFlag { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"authenticated" => MessageFlag::Authenticated, + b"unauthenticated" => MessageFlag::Unauthenticated, + b"unauthenticatedDmarc" => MessageFlag::UnauthenticatedDmarc, + b"dsn" => MessageFlag::Dsn, + b"report" => MessageFlag::Report, + b"autogenerated" => MessageFlag::Autogenerated, + } + } + + fn as_str(&self) -> &'static str { + match self { + MessageFlag::Authenticated => "authenticated", + MessageFlag::Unauthenticated => "unauthenticated", + MessageFlag::UnauthenticatedDmarc => "unauthenticatedDmarc", + MessageFlag::Dsn => "dsn", + MessageFlag::Report => "report", + MessageFlag::Autogenerated => "autogenerated", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MessageFlag::Authenticated), + 1 => Some(MessageFlag::Unauthenticated), + 2 => Some(MessageFlag::UnauthenticatedDmarc), + 3 => Some(MessageFlag::Dsn), + 4 => Some(MessageFlag::Report), + 5 => Some(MessageFlag::Autogenerated), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for MessageFlag { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MessageFlag { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MetricType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Counter" => MetricType::Counter, + b"Gauge" => MetricType::Gauge, + b"Histogram" => MetricType::Histogram, + } + } + + fn as_str(&self) -> &'static str { + match self { + MetricType::Counter => "Counter", + MetricType::Gauge => "Gauge", + MetricType::Histogram => "Histogram", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MetricType::Counter), + 1 => Some(MetricType::Gauge), + 2 => Some(MetricType::Histogram), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for MetricType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MetricType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MetricsOtelType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => MetricsOtelType::Disabled, + b"Http" => MetricsOtelType::Http, + b"Grpc" => MetricsOtelType::Grpc, + } + } + + fn as_str(&self) -> &'static str { + match self { + MetricsOtelType::Disabled => "Disabled", + MetricsOtelType::Http => "Http", + MetricsOtelType::Grpc => "Grpc", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MetricsOtelType::Disabled), + 1 => Some(MetricsOtelType::Http), + 2 => Some(MetricsOtelType::Grpc), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for MetricsOtelType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MetricsOtelType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MetricsPrometheusType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => MetricsPrometheusType::Disabled, + b"Enabled" => MetricsPrometheusType::Enabled, + } + } + + fn as_str(&self) -> &'static str { + match self { + MetricsPrometheusType::Disabled => "Disabled", + MetricsPrometheusType::Enabled => "Enabled", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MetricsPrometheusType::Disabled), + 1 => Some(MetricsPrometheusType::Enabled), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for MetricsPrometheusType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MetricsPrometheusType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MetricsStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => MetricsStoreType::Disabled, + b"Default" => MetricsStoreType::Default, + b"FoundationDb" => MetricsStoreType::FoundationDb, + b"PostgreSql" => MetricsStoreType::PostgreSql, + b"MySql" => MetricsStoreType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + MetricsStoreType::Disabled => "Disabled", + MetricsStoreType::Default => "Default", + MetricsStoreType::FoundationDb => "FoundationDb", + MetricsStoreType::PostgreSql => "PostgreSql", + MetricsStoreType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MetricsStoreType::Disabled), + 1 => Some(MetricsStoreType::Default), + 2 => Some(MetricsStoreType::FoundationDb), + 3 => Some(MetricsStoreType::PostgreSql), + 4 => Some(MetricsStoreType::MySql), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for MetricsStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MetricsStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MilterVersion { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"v2" => MilterVersion::V2, + b"v6" => MilterVersion::V6, + } + } + + fn as_str(&self) -> &'static str { + match self { + MilterVersion::V2 => "v2", + MilterVersion::V6 => "v6", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MilterVersion::V2), + 1 => Some(MilterVersion::V6), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for MilterVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MilterVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ModelSize { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"16" => ModelSize::V16, + b"17" => ModelSize::V17, + b"18" => ModelSize::V18, + b"19" => ModelSize::V19, + b"20" => ModelSize::V20, + b"21" => ModelSize::V21, + b"22" => ModelSize::V22, + b"23" => ModelSize::V23, + b"24" => ModelSize::V24, + b"25" => ModelSize::V25, + b"26" => ModelSize::V26, + b"27" => ModelSize::V27, + b"28" => ModelSize::V28, + } + } + + fn as_str(&self) -> &'static str { + match self { + ModelSize::V16 => "16", + ModelSize::V17 => "17", + ModelSize::V18 => "18", + ModelSize::V19 => "19", + ModelSize::V20 => "20", + ModelSize::V21 => "21", + ModelSize::V22 => "22", + ModelSize::V23 => "23", + ModelSize::V24 => "24", + ModelSize::V25 => "25", + ModelSize::V26 => "26", + ModelSize::V27 => "27", + ModelSize::V28 => "28", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ModelSize::V16), + 1 => Some(ModelSize::V17), + 2 => Some(ModelSize::V18), + 3 => Some(ModelSize::V19), + 4 => Some(ModelSize::V20), + 5 => Some(ModelSize::V21), + 6 => Some(ModelSize::V22), + 7 => Some(ModelSize::V23), + 8 => Some(ModelSize::V24), + 9 => Some(ModelSize::V25), + 10 => Some(ModelSize::V26), + 11 => Some(ModelSize::V27), + 12 => Some(ModelSize::V28), + _ => None, + } + } + + const COUNT: usize = 13; +} + +impl serde::Serialize for ModelSize { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ModelSize { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaDeliveryExpirationType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Ttl" => MtaDeliveryExpirationType::Ttl, + b"Attempts" => MtaDeliveryExpirationType::Attempts, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaDeliveryExpirationType::Ttl => "Ttl", + MtaDeliveryExpirationType::Attempts => "Attempts", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaDeliveryExpirationType::Ttl), + 1 => Some(MtaDeliveryExpirationType::Attempts), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for MtaDeliveryExpirationType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaDeliveryExpirationType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaDeliveryScheduleIntervalsOrDefaultType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => MtaDeliveryScheduleIntervalsOrDefaultType::Default, + b"Custom" => MtaDeliveryScheduleIntervalsOrDefaultType::Custom, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaDeliveryScheduleIntervalsOrDefaultType::Default => "Default", + MtaDeliveryScheduleIntervalsOrDefaultType::Custom => "Custom", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaDeliveryScheduleIntervalsOrDefaultType::Default), + 1 => Some(MtaDeliveryScheduleIntervalsOrDefaultType::Custom), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for MtaDeliveryScheduleIntervalsOrDefaultType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaDeliveryScheduleIntervalsOrDefaultType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaInboundThrottleKey { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"listener" => MtaInboundThrottleKey::Listener, + b"remoteIp" => MtaInboundThrottleKey::RemoteIp, + b"localIp" => MtaInboundThrottleKey::LocalIp, + b"authenticatedAs" => MtaInboundThrottleKey::AuthenticatedAs, + b"heloDomain" => MtaInboundThrottleKey::HeloDomain, + b"sender" => MtaInboundThrottleKey::Sender, + b"senderDomain" => MtaInboundThrottleKey::SenderDomain, + b"rcpt" => MtaInboundThrottleKey::Rcpt, + b"rcptDomain" => MtaInboundThrottleKey::RcptDomain, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaInboundThrottleKey::Listener => "listener", + MtaInboundThrottleKey::RemoteIp => "remoteIp", + MtaInboundThrottleKey::LocalIp => "localIp", + MtaInboundThrottleKey::AuthenticatedAs => "authenticatedAs", + MtaInboundThrottleKey::HeloDomain => "heloDomain", + MtaInboundThrottleKey::Sender => "sender", + MtaInboundThrottleKey::SenderDomain => "senderDomain", + MtaInboundThrottleKey::Rcpt => "rcpt", + MtaInboundThrottleKey::RcptDomain => "rcptDomain", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaInboundThrottleKey::Listener), + 1 => Some(MtaInboundThrottleKey::RemoteIp), + 2 => Some(MtaInboundThrottleKey::LocalIp), + 3 => Some(MtaInboundThrottleKey::AuthenticatedAs), + 4 => Some(MtaInboundThrottleKey::HeloDomain), + 5 => Some(MtaInboundThrottleKey::Sender), + 6 => Some(MtaInboundThrottleKey::SenderDomain), + 7 => Some(MtaInboundThrottleKey::Rcpt), + 8 => Some(MtaInboundThrottleKey::RcptDomain), + _ => None, + } + } + + const COUNT: usize = 9; +} + +impl serde::Serialize for MtaInboundThrottleKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaInboundThrottleKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaIpStrategy { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"v4ThenV6" => MtaIpStrategy::V4ThenV6, + b"v6ThenV4" => MtaIpStrategy::V6ThenV4, + b"v4Only" => MtaIpStrategy::V4Only, + b"v6Only" => MtaIpStrategy::V6Only, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaIpStrategy::V4ThenV6 => "v4ThenV6", + MtaIpStrategy::V6ThenV4 => "v6ThenV4", + MtaIpStrategy::V4Only => "v4Only", + MtaIpStrategy::V6Only => "v6Only", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaIpStrategy::V4ThenV6), + 1 => Some(MtaIpStrategy::V6ThenV4), + 2 => Some(MtaIpStrategy::V4Only), + 3 => Some(MtaIpStrategy::V6Only), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for MtaIpStrategy { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaIpStrategy { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaOutboundThrottleKey { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"mx" => MtaOutboundThrottleKey::Mx, + b"remoteIp" => MtaOutboundThrottleKey::RemoteIp, + b"localIp" => MtaOutboundThrottleKey::LocalIp, + b"sender" => MtaOutboundThrottleKey::Sender, + b"senderDomain" => MtaOutboundThrottleKey::SenderDomain, + b"rcptDomain" => MtaOutboundThrottleKey::RcptDomain, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaOutboundThrottleKey::Mx => "mx", + MtaOutboundThrottleKey::RemoteIp => "remoteIp", + MtaOutboundThrottleKey::LocalIp => "localIp", + MtaOutboundThrottleKey::Sender => "sender", + MtaOutboundThrottleKey::SenderDomain => "senderDomain", + MtaOutboundThrottleKey::RcptDomain => "rcptDomain", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaOutboundThrottleKey::Mx), + 1 => Some(MtaOutboundThrottleKey::RemoteIp), + 2 => Some(MtaOutboundThrottleKey::LocalIp), + 3 => Some(MtaOutboundThrottleKey::Sender), + 4 => Some(MtaOutboundThrottleKey::SenderDomain), + 5 => Some(MtaOutboundThrottleKey::RcptDomain), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for MtaOutboundThrottleKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaOutboundThrottleKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"smtp" => MtaProtocol::Smtp, + b"lmtp" => MtaProtocol::Lmtp, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaProtocol::Smtp => "smtp", + MtaProtocol::Lmtp => "lmtp", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaProtocol::Smtp), + 1 => Some(MtaProtocol::Lmtp), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for MtaProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaQueueQuotaKey { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"sender" => MtaQueueQuotaKey::Sender, + b"senderDomain" => MtaQueueQuotaKey::SenderDomain, + b"rcpt" => MtaQueueQuotaKey::Rcpt, + b"rcptDomain" => MtaQueueQuotaKey::RcptDomain, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaQueueQuotaKey::Sender => "sender", + MtaQueueQuotaKey::SenderDomain => "senderDomain", + MtaQueueQuotaKey::Rcpt => "rcpt", + MtaQueueQuotaKey::RcptDomain => "rcptDomain", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaQueueQuotaKey::Sender), + 1 => Some(MtaQueueQuotaKey::SenderDomain), + 2 => Some(MtaQueueQuotaKey::Rcpt), + 3 => Some(MtaQueueQuotaKey::RcptDomain), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for MtaQueueQuotaKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaQueueQuotaKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaRequiredOrOptional { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"optional" => MtaRequiredOrOptional::Optional, + b"require" => MtaRequiredOrOptional::Require, + b"disable" => MtaRequiredOrOptional::Disable, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaRequiredOrOptional::Optional => "optional", + MtaRequiredOrOptional::Require => "require", + MtaRequiredOrOptional::Disable => "disable", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaRequiredOrOptional::Optional), + 1 => Some(MtaRequiredOrOptional::Require), + 2 => Some(MtaRequiredOrOptional::Disable), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for MtaRequiredOrOptional { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaRequiredOrOptional { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaRouteType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Mx" => MtaRouteType::Mx, + b"Relay" => MtaRouteType::Relay, + b"Local" => MtaRouteType::Local, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaRouteType::Mx => "Mx", + MtaRouteType::Relay => "Relay", + MtaRouteType::Local => "Local", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaRouteType::Mx), + 1 => Some(MtaRouteType::Relay), + 2 => Some(MtaRouteType::Local), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for MtaRouteType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaRouteType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for MtaStage { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"connect" => MtaStage::Connect, + b"ehlo" => MtaStage::Ehlo, + b"auth" => MtaStage::Auth, + b"mail" => MtaStage::Mail, + b"rcpt" => MtaStage::Rcpt, + b"data" => MtaStage::Data, + } + } + + fn as_str(&self) -> &'static str { + match self { + MtaStage::Connect => "connect", + MtaStage::Ehlo => "ehlo", + MtaStage::Auth => "auth", + MtaStage::Mail => "mail", + MtaStage::Rcpt => "rcpt", + MtaStage::Data => "data", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(MtaStage::Connect), + 1 => Some(MtaStage::Ehlo), + 2 => Some(MtaStage::Auth), + 3 => Some(MtaStage::Mail), + 4 => Some(MtaStage::Rcpt), + 5 => Some(MtaStage::Data), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for MtaStage { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for MtaStage { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for NetworkListenerProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"smtp" => NetworkListenerProtocol::Smtp, + b"lmtp" => NetworkListenerProtocol::Lmtp, + b"http" => NetworkListenerProtocol::Http, + b"imap" => NetworkListenerProtocol::Imap, + b"pop3" => NetworkListenerProtocol::Pop3, + b"manageSieve" => NetworkListenerProtocol::ManageSieve, + } + } + + fn as_str(&self) -> &'static str { + match self { + NetworkListenerProtocol::Smtp => "smtp", + NetworkListenerProtocol::Lmtp => "lmtp", + NetworkListenerProtocol::Http => "http", + NetworkListenerProtocol::Imap => "imap", + NetworkListenerProtocol::Pop3 => "pop3", + NetworkListenerProtocol::ManageSieve => "manageSieve", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(NetworkListenerProtocol::Smtp), + 1 => Some(NetworkListenerProtocol::Lmtp), + 2 => Some(NetworkListenerProtocol::Http), + 3 => Some(NetworkListenerProtocol::Imap), + 4 => Some(NetworkListenerProtocol::Pop3), + 5 => Some(NetworkListenerProtocol::ManageSieve), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for NetworkListenerProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for NetworkListenerProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for OvhEndpoint { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"ovh-eu" => OvhEndpoint::OvhEu, + b"ovh-ca" => OvhEndpoint::OvhCa, + b"kimsufi-eu" => OvhEndpoint::KimsufiEu, + b"kimsufi-ca" => OvhEndpoint::KimsufiCa, + b"soyoustart-eu" => OvhEndpoint::SoyoustartEu, + b"soyoustart-ca" => OvhEndpoint::SoyoustartCa, + } + } + + fn as_str(&self) -> &'static str { + match self { + OvhEndpoint::OvhEu => "ovh-eu", + OvhEndpoint::OvhCa => "ovh-ca", + OvhEndpoint::KimsufiEu => "kimsufi-eu", + OvhEndpoint::KimsufiCa => "kimsufi-ca", + OvhEndpoint::SoyoustartEu => "soyoustart-eu", + OvhEndpoint::SoyoustartCa => "soyoustart-ca", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(OvhEndpoint::OvhEu), + 1 => Some(OvhEndpoint::OvhCa), + 2 => Some(OvhEndpoint::KimsufiEu), + 3 => Some(OvhEndpoint::KimsufiCa), + 4 => Some(OvhEndpoint::SoyoustartEu), + 5 => Some(OvhEndpoint::SoyoustartCa), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for OvhEndpoint { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for OvhEndpoint { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PasswordHashAlgorithm { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"argon2id" => PasswordHashAlgorithm::Argon2id, + b"bcrypt" => PasswordHashAlgorithm::Bcrypt, + b"scrypt" => PasswordHashAlgorithm::Scrypt, + b"pbkdf2" => PasswordHashAlgorithm::Pbkdf2, + } + } + + fn as_str(&self) -> &'static str { + match self { + PasswordHashAlgorithm::Argon2id => "argon2id", + PasswordHashAlgorithm::Bcrypt => "bcrypt", + PasswordHashAlgorithm::Scrypt => "scrypt", + PasswordHashAlgorithm::Pbkdf2 => "pbkdf2", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PasswordHashAlgorithm::Argon2id), + 1 => Some(PasswordHashAlgorithm::Bcrypt), + 2 => Some(PasswordHashAlgorithm::Scrypt), + 3 => Some(PasswordHashAlgorithm::Pbkdf2), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for PasswordHashAlgorithm { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PasswordHashAlgorithm { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PasswordStrength { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"zero" => PasswordStrength::Zero, + b"one" => PasswordStrength::One, + b"two" => PasswordStrength::Two, + b"three" => PasswordStrength::Three, + b"four" => PasswordStrength::Four, + } + } + + fn as_str(&self) -> &'static str { + match self { + PasswordStrength::Zero => "zero", + PasswordStrength::One => "one", + PasswordStrength::Two => "two", + PasswordStrength::Three => "three", + PasswordStrength::Four => "four", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PasswordStrength::Zero), + 1 => Some(PasswordStrength::One), + 2 => Some(PasswordStrength::Two), + 3 => Some(PasswordStrength::Three), + 4 => Some(PasswordStrength::Four), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for PasswordStrength { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PasswordStrength { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for Permission { + fn parse(value: &str) -> Option { + hashify::map! { + value.as_bytes(), + Permission, + b"authenticate" => Permission::Authenticate, + b"authenticateWithAlias" => Permission::AuthenticateWithAlias, + b"interactAi" => Permission::InteractAi, + b"impersonate" => Permission::Impersonate, + b"unlimitedRequests" => Permission::UnlimitedRequests, + b"unlimitedUploads" => Permission::UnlimitedUploads, + b"fetchAnyBlob" => Permission::FetchAnyBlob, + b"emailSend" => Permission::EmailSend, + b"emailReceive" => Permission::EmailReceive, + b"calendarAlarmsSend" => Permission::CalendarAlarmsSend, + b"calendarSchedulingSend" => Permission::CalendarSchedulingSend, + b"calendarSchedulingReceive" => Permission::CalendarSchedulingReceive, + b"jmapPushSubscriptionGet" => Permission::JmapPushSubscriptionGet, + b"jmapPushSubscriptionCreate" => Permission::JmapPushSubscriptionCreate, + b"jmapPushSubscriptionUpdate" => Permission::JmapPushSubscriptionUpdate, + b"jmapPushSubscriptionDestroy" => Permission::JmapPushSubscriptionDestroy, + b"jmapMailboxGet" => Permission::JmapMailboxGet, + b"jmapMailboxChanges" => Permission::JmapMailboxChanges, + b"jmapMailboxQuery" => Permission::JmapMailboxQuery, + b"jmapMailboxQueryChanges" => Permission::JmapMailboxQueryChanges, + b"jmapMailboxCreate" => Permission::JmapMailboxCreate, + b"jmapMailboxUpdate" => Permission::JmapMailboxUpdate, + b"jmapMailboxDestroy" => Permission::JmapMailboxDestroy, + b"jmapThreadGet" => Permission::JmapThreadGet, + b"jmapThreadChanges" => Permission::JmapThreadChanges, + b"jmapEmailGet" => Permission::JmapEmailGet, + b"jmapEmailChanges" => Permission::JmapEmailChanges, + b"jmapEmailQuery" => Permission::JmapEmailQuery, + b"jmapEmailQueryChanges" => Permission::JmapEmailQueryChanges, + b"jmapEmailCreate" => Permission::JmapEmailCreate, + b"jmapEmailUpdate" => Permission::JmapEmailUpdate, + b"jmapEmailDestroy" => Permission::JmapEmailDestroy, + b"jmapEmailCopy" => Permission::JmapEmailCopy, + b"jmapEmailImport" => Permission::JmapEmailImport, + b"jmapEmailParse" => Permission::JmapEmailParse, + b"jmapSearchSnippetGet" => Permission::JmapSearchSnippetGet, + b"jmapIdentityGet" => Permission::JmapIdentityGet, + b"jmapIdentityChanges" => Permission::JmapIdentityChanges, + b"jmapIdentityCreate" => Permission::JmapIdentityCreate, + b"jmapIdentityUpdate" => Permission::JmapIdentityUpdate, + b"jmapIdentityDestroy" => Permission::JmapIdentityDestroy, + b"jmapEmailSubmissionGet" => Permission::JmapEmailSubmissionGet, + b"jmapEmailSubmissionChanges" => Permission::JmapEmailSubmissionChanges, + b"jmapEmailSubmissionQuery" => Permission::JmapEmailSubmissionQuery, + b"jmapEmailSubmissionQueryChanges" => Permission::JmapEmailSubmissionQueryChanges, + b"jmapEmailSubmissionCreate" => Permission::JmapEmailSubmissionCreate, + b"jmapEmailSubmissionUpdate" => Permission::JmapEmailSubmissionUpdate, + b"jmapEmailSubmissionDestroy" => Permission::JmapEmailSubmissionDestroy, + b"jmapVacationResponseGet" => Permission::JmapVacationResponseGet, + b"jmapVacationResponseCreate" => Permission::JmapVacationResponseCreate, + b"jmapVacationResponseUpdate" => Permission::JmapVacationResponseUpdate, + b"jmapVacationResponseDestroy" => Permission::JmapVacationResponseDestroy, + b"jmapSieveScriptGet" => Permission::JmapSieveScriptGet, + b"jmapSieveScriptQuery" => Permission::JmapSieveScriptQuery, + b"jmapSieveScriptValidate" => Permission::JmapSieveScriptValidate, + b"jmapSieveScriptCreate" => Permission::JmapSieveScriptCreate, + b"jmapSieveScriptUpdate" => Permission::JmapSieveScriptUpdate, + b"jmapSieveScriptDestroy" => Permission::JmapSieveScriptDestroy, + b"jmapPrincipalGet" => Permission::JmapPrincipalGet, + b"jmapPrincipalQuery" => Permission::JmapPrincipalQuery, + b"jmapPrincipalChanges" => Permission::JmapPrincipalChanges, + b"jmapPrincipalQueryChanges" => Permission::JmapPrincipalQueryChanges, + b"jmapPrincipalGetAvailability" => Permission::JmapPrincipalGetAvailability, + b"jmapPrincipalCreate" => Permission::JmapPrincipalCreate, + b"jmapPrincipalUpdate" => Permission::JmapPrincipalUpdate, + b"jmapPrincipalDestroy" => Permission::JmapPrincipalDestroy, + b"jmapQuotaGet" => Permission::JmapQuotaGet, + b"jmapQuotaChanges" => Permission::JmapQuotaChanges, + b"jmapQuotaQuery" => Permission::JmapQuotaQuery, + b"jmapQuotaQueryChanges" => Permission::JmapQuotaQueryChanges, + b"jmapBlobGet" => Permission::JmapBlobGet, + b"jmapBlobCopy" => Permission::JmapBlobCopy, + b"jmapBlobLookup" => Permission::JmapBlobLookup, + b"jmapBlobUpload" => Permission::JmapBlobUpload, + b"jmapAddressBookGet" => Permission::JmapAddressBookGet, + b"jmapAddressBookChanges" => Permission::JmapAddressBookChanges, + b"jmapAddressBookCreate" => Permission::JmapAddressBookCreate, + b"jmapAddressBookUpdate" => Permission::JmapAddressBookUpdate, + b"jmapAddressBookDestroy" => Permission::JmapAddressBookDestroy, + b"jmapContactCardGet" => Permission::JmapContactCardGet, + b"jmapContactCardChanges" => Permission::JmapContactCardChanges, + b"jmapContactCardQuery" => Permission::JmapContactCardQuery, + b"jmapContactCardQueryChanges" => Permission::JmapContactCardQueryChanges, + b"jmapContactCardCreate" => Permission::JmapContactCardCreate, + b"jmapContactCardUpdate" => Permission::JmapContactCardUpdate, + b"jmapContactCardDestroy" => Permission::JmapContactCardDestroy, + b"jmapContactCardCopy" => Permission::JmapContactCardCopy, + b"jmapContactCardParse" => Permission::JmapContactCardParse, + b"jmapFileNodeGet" => Permission::JmapFileNodeGet, + b"jmapFileNodeChanges" => Permission::JmapFileNodeChanges, + b"jmapFileNodeQuery" => Permission::JmapFileNodeQuery, + b"jmapFileNodeQueryChanges" => Permission::JmapFileNodeQueryChanges, + b"jmapFileNodeCreate" => Permission::JmapFileNodeCreate, + b"jmapFileNodeUpdate" => Permission::JmapFileNodeUpdate, + b"jmapFileNodeDestroy" => Permission::JmapFileNodeDestroy, + b"jmapShareNotificationGet" => Permission::JmapShareNotificationGet, + b"jmapShareNotificationChanges" => Permission::JmapShareNotificationChanges, + b"jmapShareNotificationQuery" => Permission::JmapShareNotificationQuery, + b"jmapShareNotificationQueryChanges" => Permission::JmapShareNotificationQueryChanges, + b"jmapShareNotificationCreate" => Permission::JmapShareNotificationCreate, + b"jmapShareNotificationUpdate" => Permission::JmapShareNotificationUpdate, + b"jmapShareNotificationDestroy" => Permission::JmapShareNotificationDestroy, + b"jmapCalendarGet" => Permission::JmapCalendarGet, + b"jmapCalendarChanges" => Permission::JmapCalendarChanges, + b"jmapCalendarCreate" => Permission::JmapCalendarCreate, + b"jmapCalendarUpdate" => Permission::JmapCalendarUpdate, + b"jmapCalendarDestroy" => Permission::JmapCalendarDestroy, + b"jmapCalendarEventGet" => Permission::JmapCalendarEventGet, + b"jmapCalendarEventChanges" => Permission::JmapCalendarEventChanges, + b"jmapCalendarEventQuery" => Permission::JmapCalendarEventQuery, + b"jmapCalendarEventQueryChanges" => Permission::JmapCalendarEventQueryChanges, + b"jmapCalendarEventCreate" => Permission::JmapCalendarEventCreate, + b"jmapCalendarEventUpdate" => Permission::JmapCalendarEventUpdate, + b"jmapCalendarEventDestroy" => Permission::JmapCalendarEventDestroy, + b"jmapCalendarEventCopy" => Permission::JmapCalendarEventCopy, + b"jmapCalendarEventParse" => Permission::JmapCalendarEventParse, + b"jmapCalendarEventNotificationGet" => Permission::JmapCalendarEventNotificationGet, + b"jmapCalendarEventNotificationChanges" => Permission::JmapCalendarEventNotificationChanges, + b"jmapCalendarEventNotificationQuery" => Permission::JmapCalendarEventNotificationQuery, + b"jmapCalendarEventNotificationQueryChanges" => Permission::JmapCalendarEventNotificationQueryChanges, + b"jmapCalendarEventNotificationCreate" => Permission::JmapCalendarEventNotificationCreate, + b"jmapCalendarEventNotificationUpdate" => Permission::JmapCalendarEventNotificationUpdate, + b"jmapCalendarEventNotificationDestroy" => Permission::JmapCalendarEventNotificationDestroy, + b"jmapParticipantIdentityGet" => Permission::JmapParticipantIdentityGet, + b"jmapParticipantIdentityChanges" => Permission::JmapParticipantIdentityChanges, + b"jmapParticipantIdentityCreate" => Permission::JmapParticipantIdentityCreate, + b"jmapParticipantIdentityUpdate" => Permission::JmapParticipantIdentityUpdate, + b"jmapParticipantIdentityDestroy" => Permission::JmapParticipantIdentityDestroy, + b"jmapCoreEcho" => Permission::JmapCoreEcho, + b"imapAuthenticate" => Permission::ImapAuthenticate, + b"imapAclGet" => Permission::ImapAclGet, + b"imapAclSet" => Permission::ImapAclSet, + b"imapMyRights" => Permission::ImapMyRights, + b"imapListRights" => Permission::ImapListRights, + b"imapAppend" => Permission::ImapAppend, + b"imapCapability" => Permission::ImapCapability, + b"imapId" => Permission::ImapId, + b"imapCopy" => Permission::ImapCopy, + b"imapMove" => Permission::ImapMove, + b"imapCreate" => Permission::ImapCreate, + b"imapDelete" => Permission::ImapDelete, + b"imapEnable" => Permission::ImapEnable, + b"imapExpunge" => Permission::ImapExpunge, + b"imapFetch" => Permission::ImapFetch, + b"imapIdle" => Permission::ImapIdle, + b"imapList" => Permission::ImapList, + b"imapLsub" => Permission::ImapLsub, + b"imapNamespace" => Permission::ImapNamespace, + b"imapRename" => Permission::ImapRename, + b"imapSearch" => Permission::ImapSearch, + b"imapSort" => Permission::ImapSort, + b"imapSelect" => Permission::ImapSelect, + b"imapExamine" => Permission::ImapExamine, + b"imapStatus" => Permission::ImapStatus, + b"imapStore" => Permission::ImapStore, + b"imapSubscribe" => Permission::ImapSubscribe, + b"imapThread" => Permission::ImapThread, + b"pop3Authenticate" => Permission::Pop3Authenticate, + b"pop3List" => Permission::Pop3List, + b"pop3Uidl" => Permission::Pop3Uidl, + b"pop3Stat" => Permission::Pop3Stat, + b"pop3Retr" => Permission::Pop3Retr, + b"pop3Dele" => Permission::Pop3Dele, + b"sieveAuthenticate" => Permission::SieveAuthenticate, + b"sieveListScripts" => Permission::SieveListScripts, + b"sieveSetActive" => Permission::SieveSetActive, + b"sieveGetScript" => Permission::SieveGetScript, + b"sievePutScript" => Permission::SievePutScript, + b"sieveDeleteScript" => Permission::SieveDeleteScript, + b"sieveRenameScript" => Permission::SieveRenameScript, + b"sieveCheckScript" => Permission::SieveCheckScript, + b"sieveHaveSpace" => Permission::SieveHaveSpace, + b"davSyncCollection" => Permission::DavSyncCollection, + b"davExpandProperty" => Permission::DavExpandProperty, + b"davPrincipalAcl" => Permission::DavPrincipalAcl, + b"davPrincipalList" => Permission::DavPrincipalList, + b"davPrincipalMatch" => Permission::DavPrincipalMatch, + b"davPrincipalSearch" => Permission::DavPrincipalSearch, + b"davPrincipalSearchPropSet" => Permission::DavPrincipalSearchPropSet, + b"davFilePropFind" => Permission::DavFilePropFind, + b"davFilePropPatch" => Permission::DavFilePropPatch, + b"davFileGet" => Permission::DavFileGet, + b"davFileMkCol" => Permission::DavFileMkCol, + b"davFileDelete" => Permission::DavFileDelete, + b"davFilePut" => Permission::DavFilePut, + b"davFileCopy" => Permission::DavFileCopy, + b"davFileMove" => Permission::DavFileMove, + b"davFileLock" => Permission::DavFileLock, + b"davFileAcl" => Permission::DavFileAcl, + b"davCardPropFind" => Permission::DavCardPropFind, + b"davCardPropPatch" => Permission::DavCardPropPatch, + b"davCardGet" => Permission::DavCardGet, + b"davCardMkCol" => Permission::DavCardMkCol, + b"davCardDelete" => Permission::DavCardDelete, + b"davCardPut" => Permission::DavCardPut, + b"davCardCopy" => Permission::DavCardCopy, + b"davCardMove" => Permission::DavCardMove, + b"davCardLock" => Permission::DavCardLock, + b"davCardAcl" => Permission::DavCardAcl, + b"davCardQuery" => Permission::DavCardQuery, + b"davCardMultiGet" => Permission::DavCardMultiGet, + b"davCalPropFind" => Permission::DavCalPropFind, + b"davCalPropPatch" => Permission::DavCalPropPatch, + b"davCalGet" => Permission::DavCalGet, + b"davCalMkCol" => Permission::DavCalMkCol, + b"davCalDelete" => Permission::DavCalDelete, + b"davCalPut" => Permission::DavCalPut, + b"davCalCopy" => Permission::DavCalCopy, + b"davCalMove" => Permission::DavCalMove, + b"davCalLock" => Permission::DavCalLock, + b"davCalAcl" => Permission::DavCalAcl, + b"davCalQuery" => Permission::DavCalQuery, + b"davCalMultiGet" => Permission::DavCalMultiGet, + b"davCalFreeBusyQuery" => Permission::DavCalFreeBusyQuery, + b"oAuthClientRegistration" => Permission::OAuthClientRegistration, + b"oAuthClientOverride" => Permission::OAuthClientOverride, + b"liveTracing" => Permission::LiveTracing, + b"liveMetrics" => Permission::LiveMetrics, + b"liveDeliveryTest" => Permission::LiveDeliveryTest, + b"sysAccountGet" => Permission::SysAccountGet, + b"sysAccountCreate" => Permission::SysAccountCreate, + b"sysAccountUpdate" => Permission::SysAccountUpdate, + b"sysAccountDestroy" => Permission::SysAccountDestroy, + b"sysAccountQuery" => Permission::SysAccountQuery, + b"sysAccountPasswordGet" => Permission::SysAccountPasswordGet, + b"sysAccountPasswordUpdate" => Permission::SysAccountPasswordUpdate, + b"sysAccountSettingsGet" => Permission::SysAccountSettingsGet, + b"sysAccountSettingsUpdate" => Permission::SysAccountSettingsUpdate, + b"sysAcmeProviderGet" => Permission::SysAcmeProviderGet, + b"sysAcmeProviderCreate" => Permission::SysAcmeProviderCreate, + b"sysAcmeProviderUpdate" => Permission::SysAcmeProviderUpdate, + b"sysAcmeProviderDestroy" => Permission::SysAcmeProviderDestroy, + b"sysAcmeProviderQuery" => Permission::SysAcmeProviderQuery, + b"actionReloadSettings" => Permission::ActionReloadSettings, + b"actionReloadTlsCertificates" => Permission::ActionReloadTlsCertificates, + b"actionReloadLookupStores" => Permission::ActionReloadLookupStores, + b"actionReloadBlockedIps" => Permission::ActionReloadBlockedIps, + b"actionUpdateApps" => Permission::ActionUpdateApps, + b"actionTroubleshootDmarc" => Permission::ActionTroubleshootDmarc, + b"actionClassifySpam" => Permission::ActionClassifySpam, + b"actionInvalidateCaches" => Permission::ActionInvalidateCaches, + b"actionInvalidateNegativeCaches" => Permission::ActionInvalidateNegativeCaches, + b"actionPauseMtaQueue" => Permission::ActionPauseMtaQueue, + b"actionResumeMtaQueue" => Permission::ActionResumeMtaQueue, + b"sysActionGet" => Permission::SysActionGet, + b"sysActionCreate" => Permission::SysActionCreate, + b"sysActionUpdate" => Permission::SysActionUpdate, + b"sysActionDestroy" => Permission::SysActionDestroy, + b"sysActionQuery" => Permission::SysActionQuery, + b"sysAddressBookGet" => Permission::SysAddressBookGet, + b"sysAddressBookUpdate" => Permission::SysAddressBookUpdate, + b"sysAiModelGet" => Permission::SysAiModelGet, + b"sysAiModelCreate" => Permission::SysAiModelCreate, + b"sysAiModelUpdate" => Permission::SysAiModelUpdate, + b"sysAiModelDestroy" => Permission::SysAiModelDestroy, + b"sysAiModelQuery" => Permission::SysAiModelQuery, + b"sysAlertGet" => Permission::SysAlertGet, + b"sysAlertCreate" => Permission::SysAlertCreate, + b"sysAlertUpdate" => Permission::SysAlertUpdate, + b"sysAlertDestroy" => Permission::SysAlertDestroy, + b"sysAlertQuery" => Permission::SysAlertQuery, + b"sysAllowedIpGet" => Permission::SysAllowedIpGet, + b"sysAllowedIpCreate" => Permission::SysAllowedIpCreate, + b"sysAllowedIpUpdate" => Permission::SysAllowedIpUpdate, + b"sysAllowedIpDestroy" => Permission::SysAllowedIpDestroy, + b"sysAllowedIpQuery" => Permission::SysAllowedIpQuery, + b"sysApiKeyGet" => Permission::SysApiKeyGet, + b"sysApiKeyCreate" => Permission::SysApiKeyCreate, + b"sysApiKeyUpdate" => Permission::SysApiKeyUpdate, + b"sysApiKeyDestroy" => Permission::SysApiKeyDestroy, + b"sysApiKeyQuery" => Permission::SysApiKeyQuery, + b"sysAppPasswordGet" => Permission::SysAppPasswordGet, + b"sysAppPasswordCreate" => Permission::SysAppPasswordCreate, + b"sysAppPasswordUpdate" => Permission::SysAppPasswordUpdate, + b"sysAppPasswordDestroy" => Permission::SysAppPasswordDestroy, + b"sysAppPasswordQuery" => Permission::SysAppPasswordQuery, + b"sysApplicationGet" => Permission::SysApplicationGet, + b"sysApplicationCreate" => Permission::SysApplicationCreate, + b"sysApplicationUpdate" => Permission::SysApplicationUpdate, + b"sysApplicationDestroy" => Permission::SysApplicationDestroy, + b"sysApplicationQuery" => Permission::SysApplicationQuery, + b"sysArchivedItemGet" => Permission::SysArchivedItemGet, + b"sysArchivedItemCreate" => Permission::SysArchivedItemCreate, + b"sysArchivedItemUpdate" => Permission::SysArchivedItemUpdate, + b"sysArchivedItemDestroy" => Permission::SysArchivedItemDestroy, + b"sysArchivedItemQuery" => Permission::SysArchivedItemQuery, + b"sysArfExternalReportGet" => Permission::SysArfExternalReportGet, + b"sysArfExternalReportCreate" => Permission::SysArfExternalReportCreate, + b"sysArfExternalReportUpdate" => Permission::SysArfExternalReportUpdate, + b"sysArfExternalReportDestroy" => Permission::SysArfExternalReportDestroy, + b"sysArfExternalReportQuery" => Permission::SysArfExternalReportQuery, + b"sysAsnGet" => Permission::SysAsnGet, + b"sysAsnUpdate" => Permission::SysAsnUpdate, + b"sysAuthenticationGet" => Permission::SysAuthenticationGet, + b"sysAuthenticationUpdate" => Permission::SysAuthenticationUpdate, + b"sysBlobStoreGet" => Permission::SysBlobStoreGet, + b"sysBlobStoreUpdate" => Permission::SysBlobStoreUpdate, + b"sysBlockedIpGet" => Permission::SysBlockedIpGet, + b"sysBlockedIpCreate" => Permission::SysBlockedIpCreate, + b"sysBlockedIpUpdate" => Permission::SysBlockedIpUpdate, + b"sysBlockedIpDestroy" => Permission::SysBlockedIpDestroy, + b"sysBlockedIpQuery" => Permission::SysBlockedIpQuery, + b"sysBootstrapGet" => Permission::SysBootstrapGet, + b"sysBootstrapUpdate" => Permission::SysBootstrapUpdate, + b"sysCacheGet" => Permission::SysCacheGet, + b"sysCacheUpdate" => Permission::SysCacheUpdate, + b"sysCalendarGet" => Permission::SysCalendarGet, + b"sysCalendarUpdate" => Permission::SysCalendarUpdate, + b"sysCalendarAlarmGet" => Permission::SysCalendarAlarmGet, + b"sysCalendarAlarmUpdate" => Permission::SysCalendarAlarmUpdate, + b"sysCalendarSchedulingGet" => Permission::SysCalendarSchedulingGet, + b"sysCalendarSchedulingUpdate" => Permission::SysCalendarSchedulingUpdate, + b"sysCertificateGet" => Permission::SysCertificateGet, + b"sysCertificateCreate" => Permission::SysCertificateCreate, + b"sysCertificateUpdate" => Permission::SysCertificateUpdate, + b"sysCertificateDestroy" => Permission::SysCertificateDestroy, + b"sysCertificateQuery" => Permission::SysCertificateQuery, + b"sysClusterNodeGet" => Permission::SysClusterNodeGet, + b"sysClusterNodeCreate" => Permission::SysClusterNodeCreate, + b"sysClusterNodeUpdate" => Permission::SysClusterNodeUpdate, + b"sysClusterNodeDestroy" => Permission::SysClusterNodeDestroy, + b"sysClusterNodeQuery" => Permission::SysClusterNodeQuery, + b"sysClusterRoleGet" => Permission::SysClusterRoleGet, + b"sysClusterRoleCreate" => Permission::SysClusterRoleCreate, + b"sysClusterRoleUpdate" => Permission::SysClusterRoleUpdate, + b"sysClusterRoleDestroy" => Permission::SysClusterRoleDestroy, + b"sysClusterRoleQuery" => Permission::SysClusterRoleQuery, + b"sysCoordinatorGet" => Permission::SysCoordinatorGet, + b"sysCoordinatorUpdate" => Permission::SysCoordinatorUpdate, + b"sysDataRetentionGet" => Permission::SysDataRetentionGet, + b"sysDataRetentionUpdate" => Permission::SysDataRetentionUpdate, + b"sysDataStoreGet" => Permission::SysDataStoreGet, + b"sysDataStoreUpdate" => Permission::SysDataStoreUpdate, + b"sysDirectoryGet" => Permission::SysDirectoryGet, + b"sysDirectoryCreate" => Permission::SysDirectoryCreate, + b"sysDirectoryUpdate" => Permission::SysDirectoryUpdate, + b"sysDirectoryDestroy" => Permission::SysDirectoryDestroy, + b"sysDirectoryQuery" => Permission::SysDirectoryQuery, + b"sysDkimReportSettingsGet" => Permission::SysDkimReportSettingsGet, + b"sysDkimReportSettingsUpdate" => Permission::SysDkimReportSettingsUpdate, + b"sysDkimSignatureGet" => Permission::SysDkimSignatureGet, + b"sysDkimSignatureCreate" => Permission::SysDkimSignatureCreate, + b"sysDkimSignatureUpdate" => Permission::SysDkimSignatureUpdate, + b"sysDkimSignatureDestroy" => Permission::SysDkimSignatureDestroy, + b"sysDkimSignatureQuery" => Permission::SysDkimSignatureQuery, + b"sysDmarcExternalReportGet" => Permission::SysDmarcExternalReportGet, + b"sysDmarcExternalReportCreate" => Permission::SysDmarcExternalReportCreate, + b"sysDmarcExternalReportUpdate" => Permission::SysDmarcExternalReportUpdate, + b"sysDmarcExternalReportDestroy" => Permission::SysDmarcExternalReportDestroy, + b"sysDmarcExternalReportQuery" => Permission::SysDmarcExternalReportQuery, + b"sysDmarcInternalReportGet" => Permission::SysDmarcInternalReportGet, + b"sysDmarcInternalReportCreate" => Permission::SysDmarcInternalReportCreate, + b"sysDmarcInternalReportUpdate" => Permission::SysDmarcInternalReportUpdate, + b"sysDmarcInternalReportDestroy" => Permission::SysDmarcInternalReportDestroy, + b"sysDmarcInternalReportQuery" => Permission::SysDmarcInternalReportQuery, + b"sysDmarcReportSettingsGet" => Permission::SysDmarcReportSettingsGet, + b"sysDmarcReportSettingsUpdate" => Permission::SysDmarcReportSettingsUpdate, + b"sysDnsResolverGet" => Permission::SysDnsResolverGet, + b"sysDnsResolverUpdate" => Permission::SysDnsResolverUpdate, + b"sysDnsServerGet" => Permission::SysDnsServerGet, + b"sysDnsServerCreate" => Permission::SysDnsServerCreate, + b"sysDnsServerUpdate" => Permission::SysDnsServerUpdate, + b"sysDnsServerDestroy" => Permission::SysDnsServerDestroy, + b"sysDnsServerQuery" => Permission::SysDnsServerQuery, + b"sysDomainGet" => Permission::SysDomainGet, + b"sysDomainCreate" => Permission::SysDomainCreate, + b"sysDomainUpdate" => Permission::SysDomainUpdate, + b"sysDomainDestroy" => Permission::SysDomainDestroy, + b"sysDomainQuery" => Permission::SysDomainQuery, + b"sysDsnReportSettingsGet" => Permission::SysDsnReportSettingsGet, + b"sysDsnReportSettingsUpdate" => Permission::SysDsnReportSettingsUpdate, + b"sysEmailGet" => Permission::SysEmailGet, + b"sysEmailUpdate" => Permission::SysEmailUpdate, + b"sysEnterpriseGet" => Permission::SysEnterpriseGet, + b"sysEnterpriseUpdate" => Permission::SysEnterpriseUpdate, + b"sysEventTracingLevelGet" => Permission::SysEventTracingLevelGet, + b"sysEventTracingLevelCreate" => Permission::SysEventTracingLevelCreate, + b"sysEventTracingLevelUpdate" => Permission::SysEventTracingLevelUpdate, + b"sysEventTracingLevelDestroy" => Permission::SysEventTracingLevelDestroy, + b"sysEventTracingLevelQuery" => Permission::SysEventTracingLevelQuery, + b"sysFileStorageGet" => Permission::SysFileStorageGet, + b"sysFileStorageUpdate" => Permission::SysFileStorageUpdate, + b"sysHttpGet" => Permission::SysHttpGet, + b"sysHttpUpdate" => Permission::SysHttpUpdate, + b"sysHttpFormGet" => Permission::SysHttpFormGet, + b"sysHttpFormUpdate" => Permission::SysHttpFormUpdate, + b"sysHttpLookupGet" => Permission::SysHttpLookupGet, + b"sysHttpLookupCreate" => Permission::SysHttpLookupCreate, + b"sysHttpLookupUpdate" => Permission::SysHttpLookupUpdate, + b"sysHttpLookupDestroy" => Permission::SysHttpLookupDestroy, + b"sysHttpLookupQuery" => Permission::SysHttpLookupQuery, + b"sysImapGet" => Permission::SysImapGet, + b"sysImapUpdate" => Permission::SysImapUpdate, + b"sysInMemoryStoreGet" => Permission::SysInMemoryStoreGet, + b"sysInMemoryStoreUpdate" => Permission::SysInMemoryStoreUpdate, + b"sysJmapGet" => Permission::SysJmapGet, + b"sysJmapUpdate" => Permission::SysJmapUpdate, + b"sysLogGet" => Permission::SysLogGet, + b"sysLogCreate" => Permission::SysLogCreate, + b"sysLogUpdate" => Permission::SysLogUpdate, + b"sysLogDestroy" => Permission::SysLogDestroy, + b"sysLogQuery" => Permission::SysLogQuery, + b"sysMailingListGet" => Permission::SysMailingListGet, + b"sysMailingListCreate" => Permission::SysMailingListCreate, + b"sysMailingListUpdate" => Permission::SysMailingListUpdate, + b"sysMailingListDestroy" => Permission::SysMailingListDestroy, + b"sysMailingListQuery" => Permission::SysMailingListQuery, + b"sysMaskedEmailGet" => Permission::SysMaskedEmailGet, + b"sysMaskedEmailCreate" => Permission::SysMaskedEmailCreate, + b"sysMaskedEmailUpdate" => Permission::SysMaskedEmailUpdate, + b"sysMaskedEmailDestroy" => Permission::SysMaskedEmailDestroy, + b"sysMaskedEmailQuery" => Permission::SysMaskedEmailQuery, + b"sysMemoryLookupKeyGet" => Permission::SysMemoryLookupKeyGet, + b"sysMemoryLookupKeyCreate" => Permission::SysMemoryLookupKeyCreate, + b"sysMemoryLookupKeyUpdate" => Permission::SysMemoryLookupKeyUpdate, + b"sysMemoryLookupKeyDestroy" => Permission::SysMemoryLookupKeyDestroy, + b"sysMemoryLookupKeyQuery" => Permission::SysMemoryLookupKeyQuery, + b"sysMemoryLookupKeyValueGet" => Permission::SysMemoryLookupKeyValueGet, + b"sysMemoryLookupKeyValueCreate" => Permission::SysMemoryLookupKeyValueCreate, + b"sysMemoryLookupKeyValueUpdate" => Permission::SysMemoryLookupKeyValueUpdate, + b"sysMemoryLookupKeyValueDestroy" => Permission::SysMemoryLookupKeyValueDestroy, + b"sysMemoryLookupKeyValueQuery" => Permission::SysMemoryLookupKeyValueQuery, + b"sysMetricGet" => Permission::SysMetricGet, + b"sysMetricCreate" => Permission::SysMetricCreate, + b"sysMetricUpdate" => Permission::SysMetricUpdate, + b"sysMetricDestroy" => Permission::SysMetricDestroy, + b"sysMetricQuery" => Permission::SysMetricQuery, + b"sysMetricsGet" => Permission::SysMetricsGet, + b"sysMetricsUpdate" => Permission::SysMetricsUpdate, + b"sysMetricsStoreGet" => Permission::SysMetricsStoreGet, + b"sysMetricsStoreUpdate" => Permission::SysMetricsStoreUpdate, + b"sysMtaConnectionStrategyGet" => Permission::SysMtaConnectionStrategyGet, + b"sysMtaConnectionStrategyCreate" => Permission::SysMtaConnectionStrategyCreate, + b"sysMtaConnectionStrategyUpdate" => Permission::SysMtaConnectionStrategyUpdate, + b"sysMtaConnectionStrategyDestroy" => Permission::SysMtaConnectionStrategyDestroy, + b"sysMtaConnectionStrategyQuery" => Permission::SysMtaConnectionStrategyQuery, + b"sysMtaDeliveryScheduleGet" => Permission::SysMtaDeliveryScheduleGet, + b"sysMtaDeliveryScheduleCreate" => Permission::SysMtaDeliveryScheduleCreate, + b"sysMtaDeliveryScheduleUpdate" => Permission::SysMtaDeliveryScheduleUpdate, + b"sysMtaDeliveryScheduleDestroy" => Permission::SysMtaDeliveryScheduleDestroy, + b"sysMtaDeliveryScheduleQuery" => Permission::SysMtaDeliveryScheduleQuery, + b"sysMtaExtensionsGet" => Permission::SysMtaExtensionsGet, + b"sysMtaExtensionsUpdate" => Permission::SysMtaExtensionsUpdate, + b"sysMtaHookGet" => Permission::SysMtaHookGet, + b"sysMtaHookCreate" => Permission::SysMtaHookCreate, + b"sysMtaHookUpdate" => Permission::SysMtaHookUpdate, + b"sysMtaHookDestroy" => Permission::SysMtaHookDestroy, + b"sysMtaHookQuery" => Permission::SysMtaHookQuery, + b"sysMtaInboundSessionGet" => Permission::SysMtaInboundSessionGet, + b"sysMtaInboundSessionUpdate" => Permission::SysMtaInboundSessionUpdate, + b"sysMtaInboundThrottleGet" => Permission::SysMtaInboundThrottleGet, + b"sysMtaInboundThrottleCreate" => Permission::SysMtaInboundThrottleCreate, + b"sysMtaInboundThrottleUpdate" => Permission::SysMtaInboundThrottleUpdate, + b"sysMtaInboundThrottleDestroy" => Permission::SysMtaInboundThrottleDestroy, + b"sysMtaInboundThrottleQuery" => Permission::SysMtaInboundThrottleQuery, + b"sysMtaMilterGet" => Permission::SysMtaMilterGet, + b"sysMtaMilterCreate" => Permission::SysMtaMilterCreate, + b"sysMtaMilterUpdate" => Permission::SysMtaMilterUpdate, + b"sysMtaMilterDestroy" => Permission::SysMtaMilterDestroy, + b"sysMtaMilterQuery" => Permission::SysMtaMilterQuery, + b"sysMtaOutboundStrategyGet" => Permission::SysMtaOutboundStrategyGet, + b"sysMtaOutboundStrategyUpdate" => Permission::SysMtaOutboundStrategyUpdate, + b"sysMtaOutboundThrottleGet" => Permission::SysMtaOutboundThrottleGet, + b"sysMtaOutboundThrottleCreate" => Permission::SysMtaOutboundThrottleCreate, + b"sysMtaOutboundThrottleUpdate" => Permission::SysMtaOutboundThrottleUpdate, + b"sysMtaOutboundThrottleDestroy" => Permission::SysMtaOutboundThrottleDestroy, + b"sysMtaOutboundThrottleQuery" => Permission::SysMtaOutboundThrottleQuery, + b"sysMtaQueueQuotaGet" => Permission::SysMtaQueueQuotaGet, + b"sysMtaQueueQuotaCreate" => Permission::SysMtaQueueQuotaCreate, + b"sysMtaQueueQuotaUpdate" => Permission::SysMtaQueueQuotaUpdate, + b"sysMtaQueueQuotaDestroy" => Permission::SysMtaQueueQuotaDestroy, + b"sysMtaQueueQuotaQuery" => Permission::SysMtaQueueQuotaQuery, + b"sysMtaRouteGet" => Permission::SysMtaRouteGet, + b"sysMtaRouteCreate" => Permission::SysMtaRouteCreate, + b"sysMtaRouteUpdate" => Permission::SysMtaRouteUpdate, + b"sysMtaRouteDestroy" => Permission::SysMtaRouteDestroy, + b"sysMtaRouteQuery" => Permission::SysMtaRouteQuery, + b"sysMtaStageAuthGet" => Permission::SysMtaStageAuthGet, + b"sysMtaStageAuthUpdate" => Permission::SysMtaStageAuthUpdate, + b"sysMtaStageConnectGet" => Permission::SysMtaStageConnectGet, + b"sysMtaStageConnectUpdate" => Permission::SysMtaStageConnectUpdate, + b"sysMtaStageDataGet" => Permission::SysMtaStageDataGet, + b"sysMtaStageDataUpdate" => Permission::SysMtaStageDataUpdate, + b"sysMtaStageEhloGet" => Permission::SysMtaStageEhloGet, + b"sysMtaStageEhloUpdate" => Permission::SysMtaStageEhloUpdate, + b"sysMtaStageMailGet" => Permission::SysMtaStageMailGet, + b"sysMtaStageMailUpdate" => Permission::SysMtaStageMailUpdate, + b"sysMtaStageRcptGet" => Permission::SysMtaStageRcptGet, + b"sysMtaStageRcptUpdate" => Permission::SysMtaStageRcptUpdate, + b"sysMtaStsGet" => Permission::SysMtaStsGet, + b"sysMtaStsUpdate" => Permission::SysMtaStsUpdate, + b"sysMtaTlsStrategyGet" => Permission::SysMtaTlsStrategyGet, + b"sysMtaTlsStrategyCreate" => Permission::SysMtaTlsStrategyCreate, + b"sysMtaTlsStrategyUpdate" => Permission::SysMtaTlsStrategyUpdate, + b"sysMtaTlsStrategyDestroy" => Permission::SysMtaTlsStrategyDestroy, + b"sysMtaTlsStrategyQuery" => Permission::SysMtaTlsStrategyQuery, + b"sysMtaVirtualQueueGet" => Permission::SysMtaVirtualQueueGet, + b"sysMtaVirtualQueueCreate" => Permission::SysMtaVirtualQueueCreate, + b"sysMtaVirtualQueueUpdate" => Permission::SysMtaVirtualQueueUpdate, + b"sysMtaVirtualQueueDestroy" => Permission::SysMtaVirtualQueueDestroy, + b"sysMtaVirtualQueueQuery" => Permission::SysMtaVirtualQueueQuery, + b"sysNetworkListenerGet" => Permission::SysNetworkListenerGet, + b"sysNetworkListenerCreate" => Permission::SysNetworkListenerCreate, + b"sysNetworkListenerUpdate" => Permission::SysNetworkListenerUpdate, + b"sysNetworkListenerDestroy" => Permission::SysNetworkListenerDestroy, + b"sysNetworkListenerQuery" => Permission::SysNetworkListenerQuery, + b"sysOAuthClientGet" => Permission::SysOAuthClientGet, + b"sysOAuthClientCreate" => Permission::SysOAuthClientCreate, + b"sysOAuthClientUpdate" => Permission::SysOAuthClientUpdate, + b"sysOAuthClientDestroy" => Permission::SysOAuthClientDestroy, + b"sysOAuthClientQuery" => Permission::SysOAuthClientQuery, + b"sysOidcProviderGet" => Permission::SysOidcProviderGet, + b"sysOidcProviderUpdate" => Permission::SysOidcProviderUpdate, + b"sysPublicKeyGet" => Permission::SysPublicKeyGet, + b"sysPublicKeyCreate" => Permission::SysPublicKeyCreate, + b"sysPublicKeyUpdate" => Permission::SysPublicKeyUpdate, + b"sysPublicKeyDestroy" => Permission::SysPublicKeyDestroy, + b"sysPublicKeyQuery" => Permission::SysPublicKeyQuery, + b"sysQueuedMessageGet" => Permission::SysQueuedMessageGet, + b"sysQueuedMessageCreate" => Permission::SysQueuedMessageCreate, + b"sysQueuedMessageUpdate" => Permission::SysQueuedMessageUpdate, + b"sysQueuedMessageDestroy" => Permission::SysQueuedMessageDestroy, + b"sysQueuedMessageQuery" => Permission::SysQueuedMessageQuery, + b"sysReportSettingsGet" => Permission::SysReportSettingsGet, + b"sysReportSettingsUpdate" => Permission::SysReportSettingsUpdate, + b"sysRoleGet" => Permission::SysRoleGet, + b"sysRoleCreate" => Permission::SysRoleCreate, + b"sysRoleUpdate" => Permission::SysRoleUpdate, + b"sysRoleDestroy" => Permission::SysRoleDestroy, + b"sysRoleQuery" => Permission::SysRoleQuery, + b"sysSearchGet" => Permission::SysSearchGet, + b"sysSearchUpdate" => Permission::SysSearchUpdate, + b"sysSearchStoreGet" => Permission::SysSearchStoreGet, + b"sysSearchStoreUpdate" => Permission::SysSearchStoreUpdate, + b"sysSecurityGet" => Permission::SysSecurityGet, + b"sysSecurityUpdate" => Permission::SysSecurityUpdate, + b"sysSenderAuthGet" => Permission::SysSenderAuthGet, + b"sysSenderAuthUpdate" => Permission::SysSenderAuthUpdate, + b"sysSharingGet" => Permission::SysSharingGet, + b"sysSharingUpdate" => Permission::SysSharingUpdate, + b"sysSieveSystemInterpreterGet" => Permission::SysSieveSystemInterpreterGet, + b"sysSieveSystemInterpreterUpdate" => Permission::SysSieveSystemInterpreterUpdate, + b"sysSieveSystemScriptGet" => Permission::SysSieveSystemScriptGet, + b"sysSieveSystemScriptCreate" => Permission::SysSieveSystemScriptCreate, + b"sysSieveSystemScriptUpdate" => Permission::SysSieveSystemScriptUpdate, + b"sysSieveSystemScriptDestroy" => Permission::SysSieveSystemScriptDestroy, + b"sysSieveSystemScriptQuery" => Permission::SysSieveSystemScriptQuery, + b"sysSieveUserInterpreterGet" => Permission::SysSieveUserInterpreterGet, + b"sysSieveUserInterpreterUpdate" => Permission::SysSieveUserInterpreterUpdate, + b"sysSieveUserScriptGet" => Permission::SysSieveUserScriptGet, + b"sysSieveUserScriptCreate" => Permission::SysSieveUserScriptCreate, + b"sysSieveUserScriptUpdate" => Permission::SysSieveUserScriptUpdate, + b"sysSieveUserScriptDestroy" => Permission::SysSieveUserScriptDestroy, + b"sysSieveUserScriptQuery" => Permission::SysSieveUserScriptQuery, + b"sysSpamClassifierGet" => Permission::SysSpamClassifierGet, + b"sysSpamClassifierUpdate" => Permission::SysSpamClassifierUpdate, + b"sysSpamDnsblServerGet" => Permission::SysSpamDnsblServerGet, + b"sysSpamDnsblServerCreate" => Permission::SysSpamDnsblServerCreate, + b"sysSpamDnsblServerUpdate" => Permission::SysSpamDnsblServerUpdate, + b"sysSpamDnsblServerDestroy" => Permission::SysSpamDnsblServerDestroy, + b"sysSpamDnsblServerQuery" => Permission::SysSpamDnsblServerQuery, + b"sysSpamDnsblSettingsGet" => Permission::SysSpamDnsblSettingsGet, + b"sysSpamDnsblSettingsUpdate" => Permission::SysSpamDnsblSettingsUpdate, + b"sysSpamFileExtensionGet" => Permission::SysSpamFileExtensionGet, + b"sysSpamFileExtensionCreate" => Permission::SysSpamFileExtensionCreate, + b"sysSpamFileExtensionUpdate" => Permission::SysSpamFileExtensionUpdate, + b"sysSpamFileExtensionDestroy" => Permission::SysSpamFileExtensionDestroy, + b"sysSpamFileExtensionQuery" => Permission::SysSpamFileExtensionQuery, + b"sysSpamLlmGet" => Permission::SysSpamLlmGet, + b"sysSpamLlmUpdate" => Permission::SysSpamLlmUpdate, + b"sysSpamPyzorGet" => Permission::SysSpamPyzorGet, + b"sysSpamPyzorUpdate" => Permission::SysSpamPyzorUpdate, + b"sysSpamRuleGet" => Permission::SysSpamRuleGet, + b"sysSpamRuleCreate" => Permission::SysSpamRuleCreate, + b"sysSpamRuleUpdate" => Permission::SysSpamRuleUpdate, + b"sysSpamRuleDestroy" => Permission::SysSpamRuleDestroy, + b"sysSpamRuleQuery" => Permission::SysSpamRuleQuery, + b"sysSpamSettingsGet" => Permission::SysSpamSettingsGet, + b"sysSpamSettingsUpdate" => Permission::SysSpamSettingsUpdate, + b"sysSpamTagGet" => Permission::SysSpamTagGet, + b"sysSpamTagCreate" => Permission::SysSpamTagCreate, + b"sysSpamTagUpdate" => Permission::SysSpamTagUpdate, + b"sysSpamTagDestroy" => Permission::SysSpamTagDestroy, + b"sysSpamTagQuery" => Permission::SysSpamTagQuery, + b"sysSpamTrainingSampleGet" => Permission::SysSpamTrainingSampleGet, + b"sysSpamTrainingSampleCreate" => Permission::SysSpamTrainingSampleCreate, + b"sysSpamTrainingSampleUpdate" => Permission::SysSpamTrainingSampleUpdate, + b"sysSpamTrainingSampleDestroy" => Permission::SysSpamTrainingSampleDestroy, + b"sysSpamTrainingSampleQuery" => Permission::SysSpamTrainingSampleQuery, + b"sysSpfReportSettingsGet" => Permission::SysSpfReportSettingsGet, + b"sysSpfReportSettingsUpdate" => Permission::SysSpfReportSettingsUpdate, + b"sysStoreLookupGet" => Permission::SysStoreLookupGet, + b"sysStoreLookupCreate" => Permission::SysStoreLookupCreate, + b"sysStoreLookupUpdate" => Permission::SysStoreLookupUpdate, + b"sysStoreLookupDestroy" => Permission::SysStoreLookupDestroy, + b"sysStoreLookupQuery" => Permission::SysStoreLookupQuery, + b"sysSystemSettingsGet" => Permission::SysSystemSettingsGet, + b"sysSystemSettingsUpdate" => Permission::SysSystemSettingsUpdate, + b"taskIndexDocument" => Permission::TaskIndexDocument, + b"taskUnindexDocument" => Permission::TaskUnindexDocument, + b"taskIndexTrace" => Permission::TaskIndexTrace, + b"taskCalendarAlarmEmail" => Permission::TaskCalendarAlarmEmail, + b"taskCalendarAlarmNotification" => Permission::TaskCalendarAlarmNotification, + b"taskCalendarItipMessage" => Permission::TaskCalendarItipMessage, + b"taskMergeThreads" => Permission::TaskMergeThreads, + b"taskDmarcReport" => Permission::TaskDmarcReport, + b"taskTlsReport" => Permission::TaskTlsReport, + b"taskRestoreArchivedItem" => Permission::TaskRestoreArchivedItem, + b"taskDestroyAccount" => Permission::TaskDestroyAccount, + b"taskAccountMaintenance" => Permission::TaskAccountMaintenance, + b"taskTenantMaintenance" => Permission::TaskTenantMaintenance, + b"taskStoreMaintenance" => Permission::TaskStoreMaintenance, + b"taskSpamFilterMaintenance" => Permission::TaskSpamFilterMaintenance, + b"taskAcmeRenewal" => Permission::TaskAcmeRenewal, + b"taskDkimManagement" => Permission::TaskDkimManagement, + b"taskDnsManagement" => Permission::TaskDnsManagement, + b"sysTaskGet" => Permission::SysTaskGet, + b"sysTaskCreate" => Permission::SysTaskCreate, + b"sysTaskUpdate" => Permission::SysTaskUpdate, + b"sysTaskDestroy" => Permission::SysTaskDestroy, + b"sysTaskQuery" => Permission::SysTaskQuery, + b"sysTaskManagerGet" => Permission::SysTaskManagerGet, + b"sysTaskManagerUpdate" => Permission::SysTaskManagerUpdate, + b"sysTenantGet" => Permission::SysTenantGet, + b"sysTenantCreate" => Permission::SysTenantCreate, + b"sysTenantUpdate" => Permission::SysTenantUpdate, + b"sysTenantDestroy" => Permission::SysTenantDestroy, + b"sysTenantQuery" => Permission::SysTenantQuery, + b"sysTlsExternalReportGet" => Permission::SysTlsExternalReportGet, + b"sysTlsExternalReportCreate" => Permission::SysTlsExternalReportCreate, + b"sysTlsExternalReportUpdate" => Permission::SysTlsExternalReportUpdate, + b"sysTlsExternalReportDestroy" => Permission::SysTlsExternalReportDestroy, + b"sysTlsExternalReportQuery" => Permission::SysTlsExternalReportQuery, + b"sysTlsInternalReportGet" => Permission::SysTlsInternalReportGet, + b"sysTlsInternalReportCreate" => Permission::SysTlsInternalReportCreate, + b"sysTlsInternalReportUpdate" => Permission::SysTlsInternalReportUpdate, + b"sysTlsInternalReportDestroy" => Permission::SysTlsInternalReportDestroy, + b"sysTlsInternalReportQuery" => Permission::SysTlsInternalReportQuery, + b"sysTlsReportSettingsGet" => Permission::SysTlsReportSettingsGet, + b"sysTlsReportSettingsUpdate" => Permission::SysTlsReportSettingsUpdate, + b"sysTraceGet" => Permission::SysTraceGet, + b"sysTraceCreate" => Permission::SysTraceCreate, + b"sysTraceUpdate" => Permission::SysTraceUpdate, + b"sysTraceDestroy" => Permission::SysTraceDestroy, + b"sysTraceQuery" => Permission::SysTraceQuery, + b"sysTracerGet" => Permission::SysTracerGet, + b"sysTracerCreate" => Permission::SysTracerCreate, + b"sysTracerUpdate" => Permission::SysTracerUpdate, + b"sysTracerDestroy" => Permission::SysTracerDestroy, + b"sysTracerQuery" => Permission::SysTracerQuery, + b"sysTracingStoreGet" => Permission::SysTracingStoreGet, + b"sysTracingStoreUpdate" => Permission::SysTracingStoreUpdate, + b"sysWebDavGet" => Permission::SysWebDavGet, + b"sysWebDavUpdate" => Permission::SysWebDavUpdate, + b"sysWebHookGet" => Permission::SysWebHookGet, + b"sysWebHookCreate" => Permission::SysWebHookCreate, + b"sysWebHookUpdate" => Permission::SysWebHookUpdate, + b"sysWebHookDestroy" => Permission::SysWebHookDestroy, + b"sysWebHookQuery" => Permission::SysWebHookQuery, + } + .copied() + } + + fn as_str(&self) -> &'static str { + match self { + Permission::Authenticate => "authenticate", + Permission::AuthenticateWithAlias => "authenticateWithAlias", + Permission::InteractAi => "interactAi", + Permission::Impersonate => "impersonate", + Permission::UnlimitedRequests => "unlimitedRequests", + Permission::UnlimitedUploads => "unlimitedUploads", + Permission::FetchAnyBlob => "fetchAnyBlob", + Permission::EmailSend => "emailSend", + Permission::EmailReceive => "emailReceive", + Permission::CalendarAlarmsSend => "calendarAlarmsSend", + Permission::CalendarSchedulingSend => "calendarSchedulingSend", + Permission::CalendarSchedulingReceive => "calendarSchedulingReceive", + Permission::JmapPushSubscriptionGet => "jmapPushSubscriptionGet", + Permission::JmapPushSubscriptionCreate => "jmapPushSubscriptionCreate", + Permission::JmapPushSubscriptionUpdate => "jmapPushSubscriptionUpdate", + Permission::JmapPushSubscriptionDestroy => "jmapPushSubscriptionDestroy", + Permission::JmapMailboxGet => "jmapMailboxGet", + Permission::JmapMailboxChanges => "jmapMailboxChanges", + Permission::JmapMailboxQuery => "jmapMailboxQuery", + Permission::JmapMailboxQueryChanges => "jmapMailboxQueryChanges", + Permission::JmapMailboxCreate => "jmapMailboxCreate", + Permission::JmapMailboxUpdate => "jmapMailboxUpdate", + Permission::JmapMailboxDestroy => "jmapMailboxDestroy", + Permission::JmapThreadGet => "jmapThreadGet", + Permission::JmapThreadChanges => "jmapThreadChanges", + Permission::JmapEmailGet => "jmapEmailGet", + Permission::JmapEmailChanges => "jmapEmailChanges", + Permission::JmapEmailQuery => "jmapEmailQuery", + Permission::JmapEmailQueryChanges => "jmapEmailQueryChanges", + Permission::JmapEmailCreate => "jmapEmailCreate", + Permission::JmapEmailUpdate => "jmapEmailUpdate", + Permission::JmapEmailDestroy => "jmapEmailDestroy", + Permission::JmapEmailCopy => "jmapEmailCopy", + Permission::JmapEmailImport => "jmapEmailImport", + Permission::JmapEmailParse => "jmapEmailParse", + Permission::JmapSearchSnippetGet => "jmapSearchSnippetGet", + Permission::JmapIdentityGet => "jmapIdentityGet", + Permission::JmapIdentityChanges => "jmapIdentityChanges", + Permission::JmapIdentityCreate => "jmapIdentityCreate", + Permission::JmapIdentityUpdate => "jmapIdentityUpdate", + Permission::JmapIdentityDestroy => "jmapIdentityDestroy", + Permission::JmapEmailSubmissionGet => "jmapEmailSubmissionGet", + Permission::JmapEmailSubmissionChanges => "jmapEmailSubmissionChanges", + Permission::JmapEmailSubmissionQuery => "jmapEmailSubmissionQuery", + Permission::JmapEmailSubmissionQueryChanges => "jmapEmailSubmissionQueryChanges", + Permission::JmapEmailSubmissionCreate => "jmapEmailSubmissionCreate", + Permission::JmapEmailSubmissionUpdate => "jmapEmailSubmissionUpdate", + Permission::JmapEmailSubmissionDestroy => "jmapEmailSubmissionDestroy", + Permission::JmapVacationResponseGet => "jmapVacationResponseGet", + Permission::JmapVacationResponseCreate => "jmapVacationResponseCreate", + Permission::JmapVacationResponseUpdate => "jmapVacationResponseUpdate", + Permission::JmapVacationResponseDestroy => "jmapVacationResponseDestroy", + Permission::JmapSieveScriptGet => "jmapSieveScriptGet", + Permission::JmapSieveScriptQuery => "jmapSieveScriptQuery", + Permission::JmapSieveScriptValidate => "jmapSieveScriptValidate", + Permission::JmapSieveScriptCreate => "jmapSieveScriptCreate", + Permission::JmapSieveScriptUpdate => "jmapSieveScriptUpdate", + Permission::JmapSieveScriptDestroy => "jmapSieveScriptDestroy", + Permission::JmapPrincipalGet => "jmapPrincipalGet", + Permission::JmapPrincipalQuery => "jmapPrincipalQuery", + Permission::JmapPrincipalChanges => "jmapPrincipalChanges", + Permission::JmapPrincipalQueryChanges => "jmapPrincipalQueryChanges", + Permission::JmapPrincipalGetAvailability => "jmapPrincipalGetAvailability", + Permission::JmapPrincipalCreate => "jmapPrincipalCreate", + Permission::JmapPrincipalUpdate => "jmapPrincipalUpdate", + Permission::JmapPrincipalDestroy => "jmapPrincipalDestroy", + Permission::JmapQuotaGet => "jmapQuotaGet", + Permission::JmapQuotaChanges => "jmapQuotaChanges", + Permission::JmapQuotaQuery => "jmapQuotaQuery", + Permission::JmapQuotaQueryChanges => "jmapQuotaQueryChanges", + Permission::JmapBlobGet => "jmapBlobGet", + Permission::JmapBlobCopy => "jmapBlobCopy", + Permission::JmapBlobLookup => "jmapBlobLookup", + Permission::JmapBlobUpload => "jmapBlobUpload", + Permission::JmapAddressBookGet => "jmapAddressBookGet", + Permission::JmapAddressBookChanges => "jmapAddressBookChanges", + Permission::JmapAddressBookCreate => "jmapAddressBookCreate", + Permission::JmapAddressBookUpdate => "jmapAddressBookUpdate", + Permission::JmapAddressBookDestroy => "jmapAddressBookDestroy", + Permission::JmapContactCardGet => "jmapContactCardGet", + Permission::JmapContactCardChanges => "jmapContactCardChanges", + Permission::JmapContactCardQuery => "jmapContactCardQuery", + Permission::JmapContactCardQueryChanges => "jmapContactCardQueryChanges", + Permission::JmapContactCardCreate => "jmapContactCardCreate", + Permission::JmapContactCardUpdate => "jmapContactCardUpdate", + Permission::JmapContactCardDestroy => "jmapContactCardDestroy", + Permission::JmapContactCardCopy => "jmapContactCardCopy", + Permission::JmapContactCardParse => "jmapContactCardParse", + Permission::JmapFileNodeGet => "jmapFileNodeGet", + Permission::JmapFileNodeChanges => "jmapFileNodeChanges", + Permission::JmapFileNodeQuery => "jmapFileNodeQuery", + Permission::JmapFileNodeQueryChanges => "jmapFileNodeQueryChanges", + Permission::JmapFileNodeCreate => "jmapFileNodeCreate", + Permission::JmapFileNodeUpdate => "jmapFileNodeUpdate", + Permission::JmapFileNodeDestroy => "jmapFileNodeDestroy", + Permission::JmapShareNotificationGet => "jmapShareNotificationGet", + Permission::JmapShareNotificationChanges => "jmapShareNotificationChanges", + Permission::JmapShareNotificationQuery => "jmapShareNotificationQuery", + Permission::JmapShareNotificationQueryChanges => "jmapShareNotificationQueryChanges", + Permission::JmapShareNotificationCreate => "jmapShareNotificationCreate", + Permission::JmapShareNotificationUpdate => "jmapShareNotificationUpdate", + Permission::JmapShareNotificationDestroy => "jmapShareNotificationDestroy", + Permission::JmapCalendarGet => "jmapCalendarGet", + Permission::JmapCalendarChanges => "jmapCalendarChanges", + Permission::JmapCalendarCreate => "jmapCalendarCreate", + Permission::JmapCalendarUpdate => "jmapCalendarUpdate", + Permission::JmapCalendarDestroy => "jmapCalendarDestroy", + Permission::JmapCalendarEventGet => "jmapCalendarEventGet", + Permission::JmapCalendarEventChanges => "jmapCalendarEventChanges", + Permission::JmapCalendarEventQuery => "jmapCalendarEventQuery", + Permission::JmapCalendarEventQueryChanges => "jmapCalendarEventQueryChanges", + Permission::JmapCalendarEventCreate => "jmapCalendarEventCreate", + Permission::JmapCalendarEventUpdate => "jmapCalendarEventUpdate", + Permission::JmapCalendarEventDestroy => "jmapCalendarEventDestroy", + Permission::JmapCalendarEventCopy => "jmapCalendarEventCopy", + Permission::JmapCalendarEventParse => "jmapCalendarEventParse", + Permission::JmapCalendarEventNotificationGet => "jmapCalendarEventNotificationGet", + Permission::JmapCalendarEventNotificationChanges => { + "jmapCalendarEventNotificationChanges" + } + Permission::JmapCalendarEventNotificationQuery => "jmapCalendarEventNotificationQuery", + Permission::JmapCalendarEventNotificationQueryChanges => { + "jmapCalendarEventNotificationQueryChanges" + } + Permission::JmapCalendarEventNotificationCreate => { + "jmapCalendarEventNotificationCreate" + } + Permission::JmapCalendarEventNotificationUpdate => { + "jmapCalendarEventNotificationUpdate" + } + Permission::JmapCalendarEventNotificationDestroy => { + "jmapCalendarEventNotificationDestroy" + } + Permission::JmapParticipantIdentityGet => "jmapParticipantIdentityGet", + Permission::JmapParticipantIdentityChanges => "jmapParticipantIdentityChanges", + Permission::JmapParticipantIdentityCreate => "jmapParticipantIdentityCreate", + Permission::JmapParticipantIdentityUpdate => "jmapParticipantIdentityUpdate", + Permission::JmapParticipantIdentityDestroy => "jmapParticipantIdentityDestroy", + Permission::JmapCoreEcho => "jmapCoreEcho", + Permission::ImapAuthenticate => "imapAuthenticate", + Permission::ImapAclGet => "imapAclGet", + Permission::ImapAclSet => "imapAclSet", + Permission::ImapMyRights => "imapMyRights", + Permission::ImapListRights => "imapListRights", + Permission::ImapAppend => "imapAppend", + Permission::ImapCapability => "imapCapability", + Permission::ImapId => "imapId", + Permission::ImapCopy => "imapCopy", + Permission::ImapMove => "imapMove", + Permission::ImapCreate => "imapCreate", + Permission::ImapDelete => "imapDelete", + Permission::ImapEnable => "imapEnable", + Permission::ImapExpunge => "imapExpunge", + Permission::ImapFetch => "imapFetch", + Permission::ImapIdle => "imapIdle", + Permission::ImapList => "imapList", + Permission::ImapLsub => "imapLsub", + Permission::ImapNamespace => "imapNamespace", + Permission::ImapRename => "imapRename", + Permission::ImapSearch => "imapSearch", + Permission::ImapSort => "imapSort", + Permission::ImapSelect => "imapSelect", + Permission::ImapExamine => "imapExamine", + Permission::ImapStatus => "imapStatus", + Permission::ImapStore => "imapStore", + Permission::ImapSubscribe => "imapSubscribe", + Permission::ImapThread => "imapThread", + Permission::Pop3Authenticate => "pop3Authenticate", + Permission::Pop3List => "pop3List", + Permission::Pop3Uidl => "pop3Uidl", + Permission::Pop3Stat => "pop3Stat", + Permission::Pop3Retr => "pop3Retr", + Permission::Pop3Dele => "pop3Dele", + Permission::SieveAuthenticate => "sieveAuthenticate", + Permission::SieveListScripts => "sieveListScripts", + Permission::SieveSetActive => "sieveSetActive", + Permission::SieveGetScript => "sieveGetScript", + Permission::SievePutScript => "sievePutScript", + Permission::SieveDeleteScript => "sieveDeleteScript", + Permission::SieveRenameScript => "sieveRenameScript", + Permission::SieveCheckScript => "sieveCheckScript", + Permission::SieveHaveSpace => "sieveHaveSpace", + Permission::DavSyncCollection => "davSyncCollection", + Permission::DavExpandProperty => "davExpandProperty", + Permission::DavPrincipalAcl => "davPrincipalAcl", + Permission::DavPrincipalList => "davPrincipalList", + Permission::DavPrincipalMatch => "davPrincipalMatch", + Permission::DavPrincipalSearch => "davPrincipalSearch", + Permission::DavPrincipalSearchPropSet => "davPrincipalSearchPropSet", + Permission::DavFilePropFind => "davFilePropFind", + Permission::DavFilePropPatch => "davFilePropPatch", + Permission::DavFileGet => "davFileGet", + Permission::DavFileMkCol => "davFileMkCol", + Permission::DavFileDelete => "davFileDelete", + Permission::DavFilePut => "davFilePut", + Permission::DavFileCopy => "davFileCopy", + Permission::DavFileMove => "davFileMove", + Permission::DavFileLock => "davFileLock", + Permission::DavFileAcl => "davFileAcl", + Permission::DavCardPropFind => "davCardPropFind", + Permission::DavCardPropPatch => "davCardPropPatch", + Permission::DavCardGet => "davCardGet", + Permission::DavCardMkCol => "davCardMkCol", + Permission::DavCardDelete => "davCardDelete", + Permission::DavCardPut => "davCardPut", + Permission::DavCardCopy => "davCardCopy", + Permission::DavCardMove => "davCardMove", + Permission::DavCardLock => "davCardLock", + Permission::DavCardAcl => "davCardAcl", + Permission::DavCardQuery => "davCardQuery", + Permission::DavCardMultiGet => "davCardMultiGet", + Permission::DavCalPropFind => "davCalPropFind", + Permission::DavCalPropPatch => "davCalPropPatch", + Permission::DavCalGet => "davCalGet", + Permission::DavCalMkCol => "davCalMkCol", + Permission::DavCalDelete => "davCalDelete", + Permission::DavCalPut => "davCalPut", + Permission::DavCalCopy => "davCalCopy", + Permission::DavCalMove => "davCalMove", + Permission::DavCalLock => "davCalLock", + Permission::DavCalAcl => "davCalAcl", + Permission::DavCalQuery => "davCalQuery", + Permission::DavCalMultiGet => "davCalMultiGet", + Permission::DavCalFreeBusyQuery => "davCalFreeBusyQuery", + Permission::OAuthClientRegistration => "oAuthClientRegistration", + Permission::OAuthClientOverride => "oAuthClientOverride", + Permission::LiveTracing => "liveTracing", + Permission::LiveMetrics => "liveMetrics", + Permission::LiveDeliveryTest => "liveDeliveryTest", + Permission::SysAccountGet => "sysAccountGet", + Permission::SysAccountCreate => "sysAccountCreate", + Permission::SysAccountUpdate => "sysAccountUpdate", + Permission::SysAccountDestroy => "sysAccountDestroy", + Permission::SysAccountQuery => "sysAccountQuery", + Permission::SysAccountPasswordGet => "sysAccountPasswordGet", + Permission::SysAccountPasswordUpdate => "sysAccountPasswordUpdate", + Permission::SysAccountSettingsGet => "sysAccountSettingsGet", + Permission::SysAccountSettingsUpdate => "sysAccountSettingsUpdate", + Permission::SysAcmeProviderGet => "sysAcmeProviderGet", + Permission::SysAcmeProviderCreate => "sysAcmeProviderCreate", + Permission::SysAcmeProviderUpdate => "sysAcmeProviderUpdate", + Permission::SysAcmeProviderDestroy => "sysAcmeProviderDestroy", + Permission::SysAcmeProviderQuery => "sysAcmeProviderQuery", + Permission::ActionReloadSettings => "actionReloadSettings", + Permission::ActionReloadTlsCertificates => "actionReloadTlsCertificates", + Permission::ActionReloadLookupStores => "actionReloadLookupStores", + Permission::ActionReloadBlockedIps => "actionReloadBlockedIps", + Permission::ActionUpdateApps => "actionUpdateApps", + Permission::ActionTroubleshootDmarc => "actionTroubleshootDmarc", + Permission::ActionClassifySpam => "actionClassifySpam", + Permission::ActionInvalidateCaches => "actionInvalidateCaches", + Permission::ActionInvalidateNegativeCaches => "actionInvalidateNegativeCaches", + Permission::ActionPauseMtaQueue => "actionPauseMtaQueue", + Permission::ActionResumeMtaQueue => "actionResumeMtaQueue", + Permission::SysActionGet => "sysActionGet", + Permission::SysActionCreate => "sysActionCreate", + Permission::SysActionUpdate => "sysActionUpdate", + Permission::SysActionDestroy => "sysActionDestroy", + Permission::SysActionQuery => "sysActionQuery", + Permission::SysAddressBookGet => "sysAddressBookGet", + Permission::SysAddressBookUpdate => "sysAddressBookUpdate", + Permission::SysAiModelGet => "sysAiModelGet", + Permission::SysAiModelCreate => "sysAiModelCreate", + Permission::SysAiModelUpdate => "sysAiModelUpdate", + Permission::SysAiModelDestroy => "sysAiModelDestroy", + Permission::SysAiModelQuery => "sysAiModelQuery", + Permission::SysAlertGet => "sysAlertGet", + Permission::SysAlertCreate => "sysAlertCreate", + Permission::SysAlertUpdate => "sysAlertUpdate", + Permission::SysAlertDestroy => "sysAlertDestroy", + Permission::SysAlertQuery => "sysAlertQuery", + Permission::SysAllowedIpGet => "sysAllowedIpGet", + Permission::SysAllowedIpCreate => "sysAllowedIpCreate", + Permission::SysAllowedIpUpdate => "sysAllowedIpUpdate", + Permission::SysAllowedIpDestroy => "sysAllowedIpDestroy", + Permission::SysAllowedIpQuery => "sysAllowedIpQuery", + Permission::SysApiKeyGet => "sysApiKeyGet", + Permission::SysApiKeyCreate => "sysApiKeyCreate", + Permission::SysApiKeyUpdate => "sysApiKeyUpdate", + Permission::SysApiKeyDestroy => "sysApiKeyDestroy", + Permission::SysApiKeyQuery => "sysApiKeyQuery", + Permission::SysAppPasswordGet => "sysAppPasswordGet", + Permission::SysAppPasswordCreate => "sysAppPasswordCreate", + Permission::SysAppPasswordUpdate => "sysAppPasswordUpdate", + Permission::SysAppPasswordDestroy => "sysAppPasswordDestroy", + Permission::SysAppPasswordQuery => "sysAppPasswordQuery", + Permission::SysApplicationGet => "sysApplicationGet", + Permission::SysApplicationCreate => "sysApplicationCreate", + Permission::SysApplicationUpdate => "sysApplicationUpdate", + Permission::SysApplicationDestroy => "sysApplicationDestroy", + Permission::SysApplicationQuery => "sysApplicationQuery", + Permission::SysArchivedItemGet => "sysArchivedItemGet", + Permission::SysArchivedItemCreate => "sysArchivedItemCreate", + Permission::SysArchivedItemUpdate => "sysArchivedItemUpdate", + Permission::SysArchivedItemDestroy => "sysArchivedItemDestroy", + Permission::SysArchivedItemQuery => "sysArchivedItemQuery", + Permission::SysArfExternalReportGet => "sysArfExternalReportGet", + Permission::SysArfExternalReportCreate => "sysArfExternalReportCreate", + Permission::SysArfExternalReportUpdate => "sysArfExternalReportUpdate", + Permission::SysArfExternalReportDestroy => "sysArfExternalReportDestroy", + Permission::SysArfExternalReportQuery => "sysArfExternalReportQuery", + Permission::SysAsnGet => "sysAsnGet", + Permission::SysAsnUpdate => "sysAsnUpdate", + Permission::SysAuthenticationGet => "sysAuthenticationGet", + Permission::SysAuthenticationUpdate => "sysAuthenticationUpdate", + Permission::SysBlobStoreGet => "sysBlobStoreGet", + Permission::SysBlobStoreUpdate => "sysBlobStoreUpdate", + Permission::SysBlockedIpGet => "sysBlockedIpGet", + Permission::SysBlockedIpCreate => "sysBlockedIpCreate", + Permission::SysBlockedIpUpdate => "sysBlockedIpUpdate", + Permission::SysBlockedIpDestroy => "sysBlockedIpDestroy", + Permission::SysBlockedIpQuery => "sysBlockedIpQuery", + Permission::SysBootstrapGet => "sysBootstrapGet", + Permission::SysBootstrapUpdate => "sysBootstrapUpdate", + Permission::SysCacheGet => "sysCacheGet", + Permission::SysCacheUpdate => "sysCacheUpdate", + Permission::SysCalendarGet => "sysCalendarGet", + Permission::SysCalendarUpdate => "sysCalendarUpdate", + Permission::SysCalendarAlarmGet => "sysCalendarAlarmGet", + Permission::SysCalendarAlarmUpdate => "sysCalendarAlarmUpdate", + Permission::SysCalendarSchedulingGet => "sysCalendarSchedulingGet", + Permission::SysCalendarSchedulingUpdate => "sysCalendarSchedulingUpdate", + Permission::SysCertificateGet => "sysCertificateGet", + Permission::SysCertificateCreate => "sysCertificateCreate", + Permission::SysCertificateUpdate => "sysCertificateUpdate", + Permission::SysCertificateDestroy => "sysCertificateDestroy", + Permission::SysCertificateQuery => "sysCertificateQuery", + Permission::SysClusterNodeGet => "sysClusterNodeGet", + Permission::SysClusterNodeCreate => "sysClusterNodeCreate", + Permission::SysClusterNodeUpdate => "sysClusterNodeUpdate", + Permission::SysClusterNodeDestroy => "sysClusterNodeDestroy", + Permission::SysClusterNodeQuery => "sysClusterNodeQuery", + Permission::SysClusterRoleGet => "sysClusterRoleGet", + Permission::SysClusterRoleCreate => "sysClusterRoleCreate", + Permission::SysClusterRoleUpdate => "sysClusterRoleUpdate", + Permission::SysClusterRoleDestroy => "sysClusterRoleDestroy", + Permission::SysClusterRoleQuery => "sysClusterRoleQuery", + Permission::SysCoordinatorGet => "sysCoordinatorGet", + Permission::SysCoordinatorUpdate => "sysCoordinatorUpdate", + Permission::SysDataRetentionGet => "sysDataRetentionGet", + Permission::SysDataRetentionUpdate => "sysDataRetentionUpdate", + Permission::SysDataStoreGet => "sysDataStoreGet", + Permission::SysDataStoreUpdate => "sysDataStoreUpdate", + Permission::SysDirectoryGet => "sysDirectoryGet", + Permission::SysDirectoryCreate => "sysDirectoryCreate", + Permission::SysDirectoryUpdate => "sysDirectoryUpdate", + Permission::SysDirectoryDestroy => "sysDirectoryDestroy", + Permission::SysDirectoryQuery => "sysDirectoryQuery", + Permission::SysDkimReportSettingsGet => "sysDkimReportSettingsGet", + Permission::SysDkimReportSettingsUpdate => "sysDkimReportSettingsUpdate", + Permission::SysDkimSignatureGet => "sysDkimSignatureGet", + Permission::SysDkimSignatureCreate => "sysDkimSignatureCreate", + Permission::SysDkimSignatureUpdate => "sysDkimSignatureUpdate", + Permission::SysDkimSignatureDestroy => "sysDkimSignatureDestroy", + Permission::SysDkimSignatureQuery => "sysDkimSignatureQuery", + Permission::SysDmarcExternalReportGet => "sysDmarcExternalReportGet", + Permission::SysDmarcExternalReportCreate => "sysDmarcExternalReportCreate", + Permission::SysDmarcExternalReportUpdate => "sysDmarcExternalReportUpdate", + Permission::SysDmarcExternalReportDestroy => "sysDmarcExternalReportDestroy", + Permission::SysDmarcExternalReportQuery => "sysDmarcExternalReportQuery", + Permission::SysDmarcInternalReportGet => "sysDmarcInternalReportGet", + Permission::SysDmarcInternalReportCreate => "sysDmarcInternalReportCreate", + Permission::SysDmarcInternalReportUpdate => "sysDmarcInternalReportUpdate", + Permission::SysDmarcInternalReportDestroy => "sysDmarcInternalReportDestroy", + Permission::SysDmarcInternalReportQuery => "sysDmarcInternalReportQuery", + Permission::SysDmarcReportSettingsGet => "sysDmarcReportSettingsGet", + Permission::SysDmarcReportSettingsUpdate => "sysDmarcReportSettingsUpdate", + Permission::SysDnsResolverGet => "sysDnsResolverGet", + Permission::SysDnsResolverUpdate => "sysDnsResolverUpdate", + Permission::SysDnsServerGet => "sysDnsServerGet", + Permission::SysDnsServerCreate => "sysDnsServerCreate", + Permission::SysDnsServerUpdate => "sysDnsServerUpdate", + Permission::SysDnsServerDestroy => "sysDnsServerDestroy", + Permission::SysDnsServerQuery => "sysDnsServerQuery", + Permission::SysDomainGet => "sysDomainGet", + Permission::SysDomainCreate => "sysDomainCreate", + Permission::SysDomainUpdate => "sysDomainUpdate", + Permission::SysDomainDestroy => "sysDomainDestroy", + Permission::SysDomainQuery => "sysDomainQuery", + Permission::SysDsnReportSettingsGet => "sysDsnReportSettingsGet", + Permission::SysDsnReportSettingsUpdate => "sysDsnReportSettingsUpdate", + Permission::SysEmailGet => "sysEmailGet", + Permission::SysEmailUpdate => "sysEmailUpdate", + Permission::SysEnterpriseGet => "sysEnterpriseGet", + Permission::SysEnterpriseUpdate => "sysEnterpriseUpdate", + Permission::SysEventTracingLevelGet => "sysEventTracingLevelGet", + Permission::SysEventTracingLevelCreate => "sysEventTracingLevelCreate", + Permission::SysEventTracingLevelUpdate => "sysEventTracingLevelUpdate", + Permission::SysEventTracingLevelDestroy => "sysEventTracingLevelDestroy", + Permission::SysEventTracingLevelQuery => "sysEventTracingLevelQuery", + Permission::SysFileStorageGet => "sysFileStorageGet", + Permission::SysFileStorageUpdate => "sysFileStorageUpdate", + Permission::SysHttpGet => "sysHttpGet", + Permission::SysHttpUpdate => "sysHttpUpdate", + Permission::SysHttpFormGet => "sysHttpFormGet", + Permission::SysHttpFormUpdate => "sysHttpFormUpdate", + Permission::SysHttpLookupGet => "sysHttpLookupGet", + Permission::SysHttpLookupCreate => "sysHttpLookupCreate", + Permission::SysHttpLookupUpdate => "sysHttpLookupUpdate", + Permission::SysHttpLookupDestroy => "sysHttpLookupDestroy", + Permission::SysHttpLookupQuery => "sysHttpLookupQuery", + Permission::SysImapGet => "sysImapGet", + Permission::SysImapUpdate => "sysImapUpdate", + Permission::SysInMemoryStoreGet => "sysInMemoryStoreGet", + Permission::SysInMemoryStoreUpdate => "sysInMemoryStoreUpdate", + Permission::SysJmapGet => "sysJmapGet", + Permission::SysJmapUpdate => "sysJmapUpdate", + Permission::SysLogGet => "sysLogGet", + Permission::SysLogCreate => "sysLogCreate", + Permission::SysLogUpdate => "sysLogUpdate", + Permission::SysLogDestroy => "sysLogDestroy", + Permission::SysLogQuery => "sysLogQuery", + Permission::SysMailingListGet => "sysMailingListGet", + Permission::SysMailingListCreate => "sysMailingListCreate", + Permission::SysMailingListUpdate => "sysMailingListUpdate", + Permission::SysMailingListDestroy => "sysMailingListDestroy", + Permission::SysMailingListQuery => "sysMailingListQuery", + Permission::SysMaskedEmailGet => "sysMaskedEmailGet", + Permission::SysMaskedEmailCreate => "sysMaskedEmailCreate", + Permission::SysMaskedEmailUpdate => "sysMaskedEmailUpdate", + Permission::SysMaskedEmailDestroy => "sysMaskedEmailDestroy", + Permission::SysMaskedEmailQuery => "sysMaskedEmailQuery", + Permission::SysMemoryLookupKeyGet => "sysMemoryLookupKeyGet", + Permission::SysMemoryLookupKeyCreate => "sysMemoryLookupKeyCreate", + Permission::SysMemoryLookupKeyUpdate => "sysMemoryLookupKeyUpdate", + Permission::SysMemoryLookupKeyDestroy => "sysMemoryLookupKeyDestroy", + Permission::SysMemoryLookupKeyQuery => "sysMemoryLookupKeyQuery", + Permission::SysMemoryLookupKeyValueGet => "sysMemoryLookupKeyValueGet", + Permission::SysMemoryLookupKeyValueCreate => "sysMemoryLookupKeyValueCreate", + Permission::SysMemoryLookupKeyValueUpdate => "sysMemoryLookupKeyValueUpdate", + Permission::SysMemoryLookupKeyValueDestroy => "sysMemoryLookupKeyValueDestroy", + Permission::SysMemoryLookupKeyValueQuery => "sysMemoryLookupKeyValueQuery", + Permission::SysMetricGet => "sysMetricGet", + Permission::SysMetricCreate => "sysMetricCreate", + Permission::SysMetricUpdate => "sysMetricUpdate", + Permission::SysMetricDestroy => "sysMetricDestroy", + Permission::SysMetricQuery => "sysMetricQuery", + Permission::SysMetricsGet => "sysMetricsGet", + Permission::SysMetricsUpdate => "sysMetricsUpdate", + Permission::SysMetricsStoreGet => "sysMetricsStoreGet", + Permission::SysMetricsStoreUpdate => "sysMetricsStoreUpdate", + Permission::SysMtaConnectionStrategyGet => "sysMtaConnectionStrategyGet", + Permission::SysMtaConnectionStrategyCreate => "sysMtaConnectionStrategyCreate", + Permission::SysMtaConnectionStrategyUpdate => "sysMtaConnectionStrategyUpdate", + Permission::SysMtaConnectionStrategyDestroy => "sysMtaConnectionStrategyDestroy", + Permission::SysMtaConnectionStrategyQuery => "sysMtaConnectionStrategyQuery", + Permission::SysMtaDeliveryScheduleGet => "sysMtaDeliveryScheduleGet", + Permission::SysMtaDeliveryScheduleCreate => "sysMtaDeliveryScheduleCreate", + Permission::SysMtaDeliveryScheduleUpdate => "sysMtaDeliveryScheduleUpdate", + Permission::SysMtaDeliveryScheduleDestroy => "sysMtaDeliveryScheduleDestroy", + Permission::SysMtaDeliveryScheduleQuery => "sysMtaDeliveryScheduleQuery", + Permission::SysMtaExtensionsGet => "sysMtaExtensionsGet", + Permission::SysMtaExtensionsUpdate => "sysMtaExtensionsUpdate", + Permission::SysMtaHookGet => "sysMtaHookGet", + Permission::SysMtaHookCreate => "sysMtaHookCreate", + Permission::SysMtaHookUpdate => "sysMtaHookUpdate", + Permission::SysMtaHookDestroy => "sysMtaHookDestroy", + Permission::SysMtaHookQuery => "sysMtaHookQuery", + Permission::SysMtaInboundSessionGet => "sysMtaInboundSessionGet", + Permission::SysMtaInboundSessionUpdate => "sysMtaInboundSessionUpdate", + Permission::SysMtaInboundThrottleGet => "sysMtaInboundThrottleGet", + Permission::SysMtaInboundThrottleCreate => "sysMtaInboundThrottleCreate", + Permission::SysMtaInboundThrottleUpdate => "sysMtaInboundThrottleUpdate", + Permission::SysMtaInboundThrottleDestroy => "sysMtaInboundThrottleDestroy", + Permission::SysMtaInboundThrottleQuery => "sysMtaInboundThrottleQuery", + Permission::SysMtaMilterGet => "sysMtaMilterGet", + Permission::SysMtaMilterCreate => "sysMtaMilterCreate", + Permission::SysMtaMilterUpdate => "sysMtaMilterUpdate", + Permission::SysMtaMilterDestroy => "sysMtaMilterDestroy", + Permission::SysMtaMilterQuery => "sysMtaMilterQuery", + Permission::SysMtaOutboundStrategyGet => "sysMtaOutboundStrategyGet", + Permission::SysMtaOutboundStrategyUpdate => "sysMtaOutboundStrategyUpdate", + Permission::SysMtaOutboundThrottleGet => "sysMtaOutboundThrottleGet", + Permission::SysMtaOutboundThrottleCreate => "sysMtaOutboundThrottleCreate", + Permission::SysMtaOutboundThrottleUpdate => "sysMtaOutboundThrottleUpdate", + Permission::SysMtaOutboundThrottleDestroy => "sysMtaOutboundThrottleDestroy", + Permission::SysMtaOutboundThrottleQuery => "sysMtaOutboundThrottleQuery", + Permission::SysMtaQueueQuotaGet => "sysMtaQueueQuotaGet", + Permission::SysMtaQueueQuotaCreate => "sysMtaQueueQuotaCreate", + Permission::SysMtaQueueQuotaUpdate => "sysMtaQueueQuotaUpdate", + Permission::SysMtaQueueQuotaDestroy => "sysMtaQueueQuotaDestroy", + Permission::SysMtaQueueQuotaQuery => "sysMtaQueueQuotaQuery", + Permission::SysMtaRouteGet => "sysMtaRouteGet", + Permission::SysMtaRouteCreate => "sysMtaRouteCreate", + Permission::SysMtaRouteUpdate => "sysMtaRouteUpdate", + Permission::SysMtaRouteDestroy => "sysMtaRouteDestroy", + Permission::SysMtaRouteQuery => "sysMtaRouteQuery", + Permission::SysMtaStageAuthGet => "sysMtaStageAuthGet", + Permission::SysMtaStageAuthUpdate => "sysMtaStageAuthUpdate", + Permission::SysMtaStageConnectGet => "sysMtaStageConnectGet", + Permission::SysMtaStageConnectUpdate => "sysMtaStageConnectUpdate", + Permission::SysMtaStageDataGet => "sysMtaStageDataGet", + Permission::SysMtaStageDataUpdate => "sysMtaStageDataUpdate", + Permission::SysMtaStageEhloGet => "sysMtaStageEhloGet", + Permission::SysMtaStageEhloUpdate => "sysMtaStageEhloUpdate", + Permission::SysMtaStageMailGet => "sysMtaStageMailGet", + Permission::SysMtaStageMailUpdate => "sysMtaStageMailUpdate", + Permission::SysMtaStageRcptGet => "sysMtaStageRcptGet", + Permission::SysMtaStageRcptUpdate => "sysMtaStageRcptUpdate", + Permission::SysMtaStsGet => "sysMtaStsGet", + Permission::SysMtaStsUpdate => "sysMtaStsUpdate", + Permission::SysMtaTlsStrategyGet => "sysMtaTlsStrategyGet", + Permission::SysMtaTlsStrategyCreate => "sysMtaTlsStrategyCreate", + Permission::SysMtaTlsStrategyUpdate => "sysMtaTlsStrategyUpdate", + Permission::SysMtaTlsStrategyDestroy => "sysMtaTlsStrategyDestroy", + Permission::SysMtaTlsStrategyQuery => "sysMtaTlsStrategyQuery", + Permission::SysMtaVirtualQueueGet => "sysMtaVirtualQueueGet", + Permission::SysMtaVirtualQueueCreate => "sysMtaVirtualQueueCreate", + Permission::SysMtaVirtualQueueUpdate => "sysMtaVirtualQueueUpdate", + Permission::SysMtaVirtualQueueDestroy => "sysMtaVirtualQueueDestroy", + Permission::SysMtaVirtualQueueQuery => "sysMtaVirtualQueueQuery", + Permission::SysNetworkListenerGet => "sysNetworkListenerGet", + Permission::SysNetworkListenerCreate => "sysNetworkListenerCreate", + Permission::SysNetworkListenerUpdate => "sysNetworkListenerUpdate", + Permission::SysNetworkListenerDestroy => "sysNetworkListenerDestroy", + Permission::SysNetworkListenerQuery => "sysNetworkListenerQuery", + Permission::SysOAuthClientGet => "sysOAuthClientGet", + Permission::SysOAuthClientCreate => "sysOAuthClientCreate", + Permission::SysOAuthClientUpdate => "sysOAuthClientUpdate", + Permission::SysOAuthClientDestroy => "sysOAuthClientDestroy", + Permission::SysOAuthClientQuery => "sysOAuthClientQuery", + Permission::SysOidcProviderGet => "sysOidcProviderGet", + Permission::SysOidcProviderUpdate => "sysOidcProviderUpdate", + Permission::SysPublicKeyGet => "sysPublicKeyGet", + Permission::SysPublicKeyCreate => "sysPublicKeyCreate", + Permission::SysPublicKeyUpdate => "sysPublicKeyUpdate", + Permission::SysPublicKeyDestroy => "sysPublicKeyDestroy", + Permission::SysPublicKeyQuery => "sysPublicKeyQuery", + Permission::SysQueuedMessageGet => "sysQueuedMessageGet", + Permission::SysQueuedMessageCreate => "sysQueuedMessageCreate", + Permission::SysQueuedMessageUpdate => "sysQueuedMessageUpdate", + Permission::SysQueuedMessageDestroy => "sysQueuedMessageDestroy", + Permission::SysQueuedMessageQuery => "sysQueuedMessageQuery", + Permission::SysReportSettingsGet => "sysReportSettingsGet", + Permission::SysReportSettingsUpdate => "sysReportSettingsUpdate", + Permission::SysRoleGet => "sysRoleGet", + Permission::SysRoleCreate => "sysRoleCreate", + Permission::SysRoleUpdate => "sysRoleUpdate", + Permission::SysRoleDestroy => "sysRoleDestroy", + Permission::SysRoleQuery => "sysRoleQuery", + Permission::SysSearchGet => "sysSearchGet", + Permission::SysSearchUpdate => "sysSearchUpdate", + Permission::SysSearchStoreGet => "sysSearchStoreGet", + Permission::SysSearchStoreUpdate => "sysSearchStoreUpdate", + Permission::SysSecurityGet => "sysSecurityGet", + Permission::SysSecurityUpdate => "sysSecurityUpdate", + Permission::SysSenderAuthGet => "sysSenderAuthGet", + Permission::SysSenderAuthUpdate => "sysSenderAuthUpdate", + Permission::SysSharingGet => "sysSharingGet", + Permission::SysSharingUpdate => "sysSharingUpdate", + Permission::SysSieveSystemInterpreterGet => "sysSieveSystemInterpreterGet", + Permission::SysSieveSystemInterpreterUpdate => "sysSieveSystemInterpreterUpdate", + Permission::SysSieveSystemScriptGet => "sysSieveSystemScriptGet", + Permission::SysSieveSystemScriptCreate => "sysSieveSystemScriptCreate", + Permission::SysSieveSystemScriptUpdate => "sysSieveSystemScriptUpdate", + Permission::SysSieveSystemScriptDestroy => "sysSieveSystemScriptDestroy", + Permission::SysSieveSystemScriptQuery => "sysSieveSystemScriptQuery", + Permission::SysSieveUserInterpreterGet => "sysSieveUserInterpreterGet", + Permission::SysSieveUserInterpreterUpdate => "sysSieveUserInterpreterUpdate", + Permission::SysSieveUserScriptGet => "sysSieveUserScriptGet", + Permission::SysSieveUserScriptCreate => "sysSieveUserScriptCreate", + Permission::SysSieveUserScriptUpdate => "sysSieveUserScriptUpdate", + Permission::SysSieveUserScriptDestroy => "sysSieveUserScriptDestroy", + Permission::SysSieveUserScriptQuery => "sysSieveUserScriptQuery", + Permission::SysSpamClassifierGet => "sysSpamClassifierGet", + Permission::SysSpamClassifierUpdate => "sysSpamClassifierUpdate", + Permission::SysSpamDnsblServerGet => "sysSpamDnsblServerGet", + Permission::SysSpamDnsblServerCreate => "sysSpamDnsblServerCreate", + Permission::SysSpamDnsblServerUpdate => "sysSpamDnsblServerUpdate", + Permission::SysSpamDnsblServerDestroy => "sysSpamDnsblServerDestroy", + Permission::SysSpamDnsblServerQuery => "sysSpamDnsblServerQuery", + Permission::SysSpamDnsblSettingsGet => "sysSpamDnsblSettingsGet", + Permission::SysSpamDnsblSettingsUpdate => "sysSpamDnsblSettingsUpdate", + Permission::SysSpamFileExtensionGet => "sysSpamFileExtensionGet", + Permission::SysSpamFileExtensionCreate => "sysSpamFileExtensionCreate", + Permission::SysSpamFileExtensionUpdate => "sysSpamFileExtensionUpdate", + Permission::SysSpamFileExtensionDestroy => "sysSpamFileExtensionDestroy", + Permission::SysSpamFileExtensionQuery => "sysSpamFileExtensionQuery", + Permission::SysSpamLlmGet => "sysSpamLlmGet", + Permission::SysSpamLlmUpdate => "sysSpamLlmUpdate", + Permission::SysSpamPyzorGet => "sysSpamPyzorGet", + Permission::SysSpamPyzorUpdate => "sysSpamPyzorUpdate", + Permission::SysSpamRuleGet => "sysSpamRuleGet", + Permission::SysSpamRuleCreate => "sysSpamRuleCreate", + Permission::SysSpamRuleUpdate => "sysSpamRuleUpdate", + Permission::SysSpamRuleDestroy => "sysSpamRuleDestroy", + Permission::SysSpamRuleQuery => "sysSpamRuleQuery", + Permission::SysSpamSettingsGet => "sysSpamSettingsGet", + Permission::SysSpamSettingsUpdate => "sysSpamSettingsUpdate", + Permission::SysSpamTagGet => "sysSpamTagGet", + Permission::SysSpamTagCreate => "sysSpamTagCreate", + Permission::SysSpamTagUpdate => "sysSpamTagUpdate", + Permission::SysSpamTagDestroy => "sysSpamTagDestroy", + Permission::SysSpamTagQuery => "sysSpamTagQuery", + Permission::SysSpamTrainingSampleGet => "sysSpamTrainingSampleGet", + Permission::SysSpamTrainingSampleCreate => "sysSpamTrainingSampleCreate", + Permission::SysSpamTrainingSampleUpdate => "sysSpamTrainingSampleUpdate", + Permission::SysSpamTrainingSampleDestroy => "sysSpamTrainingSampleDestroy", + Permission::SysSpamTrainingSampleQuery => "sysSpamTrainingSampleQuery", + Permission::SysSpfReportSettingsGet => "sysSpfReportSettingsGet", + Permission::SysSpfReportSettingsUpdate => "sysSpfReportSettingsUpdate", + Permission::SysStoreLookupGet => "sysStoreLookupGet", + Permission::SysStoreLookupCreate => "sysStoreLookupCreate", + Permission::SysStoreLookupUpdate => "sysStoreLookupUpdate", + Permission::SysStoreLookupDestroy => "sysStoreLookupDestroy", + Permission::SysStoreLookupQuery => "sysStoreLookupQuery", + Permission::SysSystemSettingsGet => "sysSystemSettingsGet", + Permission::SysSystemSettingsUpdate => "sysSystemSettingsUpdate", + Permission::TaskIndexDocument => "taskIndexDocument", + Permission::TaskUnindexDocument => "taskUnindexDocument", + Permission::TaskIndexTrace => "taskIndexTrace", + Permission::TaskCalendarAlarmEmail => "taskCalendarAlarmEmail", + Permission::TaskCalendarAlarmNotification => "taskCalendarAlarmNotification", + Permission::TaskCalendarItipMessage => "taskCalendarItipMessage", + Permission::TaskMergeThreads => "taskMergeThreads", + Permission::TaskDmarcReport => "taskDmarcReport", + Permission::TaskTlsReport => "taskTlsReport", + Permission::TaskRestoreArchivedItem => "taskRestoreArchivedItem", + Permission::TaskDestroyAccount => "taskDestroyAccount", + Permission::TaskAccountMaintenance => "taskAccountMaintenance", + Permission::TaskTenantMaintenance => "taskTenantMaintenance", + Permission::TaskStoreMaintenance => "taskStoreMaintenance", + Permission::TaskSpamFilterMaintenance => "taskSpamFilterMaintenance", + Permission::TaskAcmeRenewal => "taskAcmeRenewal", + Permission::TaskDkimManagement => "taskDkimManagement", + Permission::TaskDnsManagement => "taskDnsManagement", + Permission::SysTaskGet => "sysTaskGet", + Permission::SysTaskCreate => "sysTaskCreate", + Permission::SysTaskUpdate => "sysTaskUpdate", + Permission::SysTaskDestroy => "sysTaskDestroy", + Permission::SysTaskQuery => "sysTaskQuery", + Permission::SysTaskManagerGet => "sysTaskManagerGet", + Permission::SysTaskManagerUpdate => "sysTaskManagerUpdate", + Permission::SysTenantGet => "sysTenantGet", + Permission::SysTenantCreate => "sysTenantCreate", + Permission::SysTenantUpdate => "sysTenantUpdate", + Permission::SysTenantDestroy => "sysTenantDestroy", + Permission::SysTenantQuery => "sysTenantQuery", + Permission::SysTlsExternalReportGet => "sysTlsExternalReportGet", + Permission::SysTlsExternalReportCreate => "sysTlsExternalReportCreate", + Permission::SysTlsExternalReportUpdate => "sysTlsExternalReportUpdate", + Permission::SysTlsExternalReportDestroy => "sysTlsExternalReportDestroy", + Permission::SysTlsExternalReportQuery => "sysTlsExternalReportQuery", + Permission::SysTlsInternalReportGet => "sysTlsInternalReportGet", + Permission::SysTlsInternalReportCreate => "sysTlsInternalReportCreate", + Permission::SysTlsInternalReportUpdate => "sysTlsInternalReportUpdate", + Permission::SysTlsInternalReportDestroy => "sysTlsInternalReportDestroy", + Permission::SysTlsInternalReportQuery => "sysTlsInternalReportQuery", + Permission::SysTlsReportSettingsGet => "sysTlsReportSettingsGet", + Permission::SysTlsReportSettingsUpdate => "sysTlsReportSettingsUpdate", + Permission::SysTraceGet => "sysTraceGet", + Permission::SysTraceCreate => "sysTraceCreate", + Permission::SysTraceUpdate => "sysTraceUpdate", + Permission::SysTraceDestroy => "sysTraceDestroy", + Permission::SysTraceQuery => "sysTraceQuery", + Permission::SysTracerGet => "sysTracerGet", + Permission::SysTracerCreate => "sysTracerCreate", + Permission::SysTracerUpdate => "sysTracerUpdate", + Permission::SysTracerDestroy => "sysTracerDestroy", + Permission::SysTracerQuery => "sysTracerQuery", + Permission::SysTracingStoreGet => "sysTracingStoreGet", + Permission::SysTracingStoreUpdate => "sysTracingStoreUpdate", + Permission::SysWebDavGet => "sysWebDavGet", + Permission::SysWebDavUpdate => "sysWebDavUpdate", + Permission::SysWebHookGet => "sysWebHookGet", + Permission::SysWebHookCreate => "sysWebHookCreate", + Permission::SysWebHookUpdate => "sysWebHookUpdate", + Permission::SysWebHookDestroy => "sysWebHookDestroy", + Permission::SysWebHookQuery => "sysWebHookQuery", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(Permission::Authenticate), + 1 => Some(Permission::AuthenticateWithAlias), + 2 => Some(Permission::InteractAi), + 3 => Some(Permission::Impersonate), + 4 => Some(Permission::UnlimitedRequests), + 5 => Some(Permission::UnlimitedUploads), + 6 => Some(Permission::FetchAnyBlob), + 7 => Some(Permission::EmailSend), + 8 => Some(Permission::EmailReceive), + 9 => Some(Permission::CalendarAlarmsSend), + 10 => Some(Permission::CalendarSchedulingSend), + 11 => Some(Permission::CalendarSchedulingReceive), + 12 => Some(Permission::JmapPushSubscriptionGet), + 13 => Some(Permission::JmapPushSubscriptionCreate), + 14 => Some(Permission::JmapPushSubscriptionUpdate), + 15 => Some(Permission::JmapPushSubscriptionDestroy), + 16 => Some(Permission::JmapMailboxGet), + 17 => Some(Permission::JmapMailboxChanges), + 18 => Some(Permission::JmapMailboxQuery), + 19 => Some(Permission::JmapMailboxQueryChanges), + 20 => Some(Permission::JmapMailboxCreate), + 21 => Some(Permission::JmapMailboxUpdate), + 22 => Some(Permission::JmapMailboxDestroy), + 23 => Some(Permission::JmapThreadGet), + 24 => Some(Permission::JmapThreadChanges), + 25 => Some(Permission::JmapEmailGet), + 26 => Some(Permission::JmapEmailChanges), + 27 => Some(Permission::JmapEmailQuery), + 28 => Some(Permission::JmapEmailQueryChanges), + 29 => Some(Permission::JmapEmailCreate), + 30 => Some(Permission::JmapEmailUpdate), + 31 => Some(Permission::JmapEmailDestroy), + 32 => Some(Permission::JmapEmailCopy), + 33 => Some(Permission::JmapEmailImport), + 34 => Some(Permission::JmapEmailParse), + 35 => Some(Permission::JmapSearchSnippetGet), + 36 => Some(Permission::JmapIdentityGet), + 37 => Some(Permission::JmapIdentityChanges), + 38 => Some(Permission::JmapIdentityCreate), + 39 => Some(Permission::JmapIdentityUpdate), + 40 => Some(Permission::JmapIdentityDestroy), + 41 => Some(Permission::JmapEmailSubmissionGet), + 42 => Some(Permission::JmapEmailSubmissionChanges), + 43 => Some(Permission::JmapEmailSubmissionQuery), + 44 => Some(Permission::JmapEmailSubmissionQueryChanges), + 45 => Some(Permission::JmapEmailSubmissionCreate), + 46 => Some(Permission::JmapEmailSubmissionUpdate), + 47 => Some(Permission::JmapEmailSubmissionDestroy), + 48 => Some(Permission::JmapVacationResponseGet), + 49 => Some(Permission::JmapVacationResponseCreate), + 50 => Some(Permission::JmapVacationResponseUpdate), + 51 => Some(Permission::JmapVacationResponseDestroy), + 52 => Some(Permission::JmapSieveScriptGet), + 53 => Some(Permission::JmapSieveScriptQuery), + 54 => Some(Permission::JmapSieveScriptValidate), + 55 => Some(Permission::JmapSieveScriptCreate), + 56 => Some(Permission::JmapSieveScriptUpdate), + 57 => Some(Permission::JmapSieveScriptDestroy), + 58 => Some(Permission::JmapPrincipalGet), + 59 => Some(Permission::JmapPrincipalQuery), + 60 => Some(Permission::JmapPrincipalChanges), + 61 => Some(Permission::JmapPrincipalQueryChanges), + 62 => Some(Permission::JmapPrincipalGetAvailability), + 63 => Some(Permission::JmapPrincipalCreate), + 64 => Some(Permission::JmapPrincipalUpdate), + 65 => Some(Permission::JmapPrincipalDestroy), + 66 => Some(Permission::JmapQuotaGet), + 67 => Some(Permission::JmapQuotaChanges), + 68 => Some(Permission::JmapQuotaQuery), + 69 => Some(Permission::JmapQuotaQueryChanges), + 70 => Some(Permission::JmapBlobGet), + 71 => Some(Permission::JmapBlobCopy), + 72 => Some(Permission::JmapBlobLookup), + 73 => Some(Permission::JmapBlobUpload), + 74 => Some(Permission::JmapAddressBookGet), + 75 => Some(Permission::JmapAddressBookChanges), + 76 => Some(Permission::JmapAddressBookCreate), + 77 => Some(Permission::JmapAddressBookUpdate), + 78 => Some(Permission::JmapAddressBookDestroy), + 79 => Some(Permission::JmapContactCardGet), + 80 => Some(Permission::JmapContactCardChanges), + 81 => Some(Permission::JmapContactCardQuery), + 82 => Some(Permission::JmapContactCardQueryChanges), + 83 => Some(Permission::JmapContactCardCreate), + 84 => Some(Permission::JmapContactCardUpdate), + 85 => Some(Permission::JmapContactCardDestroy), + 86 => Some(Permission::JmapContactCardCopy), + 87 => Some(Permission::JmapContactCardParse), + 88 => Some(Permission::JmapFileNodeGet), + 89 => Some(Permission::JmapFileNodeChanges), + 90 => Some(Permission::JmapFileNodeQuery), + 91 => Some(Permission::JmapFileNodeQueryChanges), + 92 => Some(Permission::JmapFileNodeCreate), + 93 => Some(Permission::JmapFileNodeUpdate), + 94 => Some(Permission::JmapFileNodeDestroy), + 95 => Some(Permission::JmapShareNotificationGet), + 96 => Some(Permission::JmapShareNotificationChanges), + 97 => Some(Permission::JmapShareNotificationQuery), + 98 => Some(Permission::JmapShareNotificationQueryChanges), + 99 => Some(Permission::JmapShareNotificationCreate), + 100 => Some(Permission::JmapShareNotificationUpdate), + 101 => Some(Permission::JmapShareNotificationDestroy), + 102 => Some(Permission::JmapCalendarGet), + 103 => Some(Permission::JmapCalendarChanges), + 104 => Some(Permission::JmapCalendarCreate), + 105 => Some(Permission::JmapCalendarUpdate), + 106 => Some(Permission::JmapCalendarDestroy), + 107 => Some(Permission::JmapCalendarEventGet), + 108 => Some(Permission::JmapCalendarEventChanges), + 109 => Some(Permission::JmapCalendarEventQuery), + 110 => Some(Permission::JmapCalendarEventQueryChanges), + 111 => Some(Permission::JmapCalendarEventCreate), + 112 => Some(Permission::JmapCalendarEventUpdate), + 113 => Some(Permission::JmapCalendarEventDestroy), + 114 => Some(Permission::JmapCalendarEventCopy), + 115 => Some(Permission::JmapCalendarEventParse), + 116 => Some(Permission::JmapCalendarEventNotificationGet), + 117 => Some(Permission::JmapCalendarEventNotificationChanges), + 118 => Some(Permission::JmapCalendarEventNotificationQuery), + 119 => Some(Permission::JmapCalendarEventNotificationQueryChanges), + 120 => Some(Permission::JmapCalendarEventNotificationCreate), + 121 => Some(Permission::JmapCalendarEventNotificationUpdate), + 122 => Some(Permission::JmapCalendarEventNotificationDestroy), + 123 => Some(Permission::JmapParticipantIdentityGet), + 124 => Some(Permission::JmapParticipantIdentityChanges), + 125 => Some(Permission::JmapParticipantIdentityCreate), + 126 => Some(Permission::JmapParticipantIdentityUpdate), + 127 => Some(Permission::JmapParticipantIdentityDestroy), + 128 => Some(Permission::JmapCoreEcho), + 129 => Some(Permission::ImapAuthenticate), + 130 => Some(Permission::ImapAclGet), + 131 => Some(Permission::ImapAclSet), + 132 => Some(Permission::ImapMyRights), + 133 => Some(Permission::ImapListRights), + 134 => Some(Permission::ImapAppend), + 135 => Some(Permission::ImapCapability), + 136 => Some(Permission::ImapId), + 137 => Some(Permission::ImapCopy), + 138 => Some(Permission::ImapMove), + 139 => Some(Permission::ImapCreate), + 140 => Some(Permission::ImapDelete), + 141 => Some(Permission::ImapEnable), + 142 => Some(Permission::ImapExpunge), + 143 => Some(Permission::ImapFetch), + 144 => Some(Permission::ImapIdle), + 145 => Some(Permission::ImapList), + 146 => Some(Permission::ImapLsub), + 147 => Some(Permission::ImapNamespace), + 148 => Some(Permission::ImapRename), + 149 => Some(Permission::ImapSearch), + 150 => Some(Permission::ImapSort), + 151 => Some(Permission::ImapSelect), + 152 => Some(Permission::ImapExamine), + 153 => Some(Permission::ImapStatus), + 154 => Some(Permission::ImapStore), + 155 => Some(Permission::ImapSubscribe), + 156 => Some(Permission::ImapThread), + 157 => Some(Permission::Pop3Authenticate), + 158 => Some(Permission::Pop3List), + 159 => Some(Permission::Pop3Uidl), + 160 => Some(Permission::Pop3Stat), + 161 => Some(Permission::Pop3Retr), + 162 => Some(Permission::Pop3Dele), + 163 => Some(Permission::SieveAuthenticate), + 164 => Some(Permission::SieveListScripts), + 165 => Some(Permission::SieveSetActive), + 166 => Some(Permission::SieveGetScript), + 167 => Some(Permission::SievePutScript), + 168 => Some(Permission::SieveDeleteScript), + 169 => Some(Permission::SieveRenameScript), + 170 => Some(Permission::SieveCheckScript), + 171 => Some(Permission::SieveHaveSpace), + 172 => Some(Permission::DavSyncCollection), + 173 => Some(Permission::DavExpandProperty), + 174 => Some(Permission::DavPrincipalAcl), + 175 => Some(Permission::DavPrincipalList), + 176 => Some(Permission::DavPrincipalMatch), + 177 => Some(Permission::DavPrincipalSearch), + 178 => Some(Permission::DavPrincipalSearchPropSet), + 179 => Some(Permission::DavFilePropFind), + 180 => Some(Permission::DavFilePropPatch), + 181 => Some(Permission::DavFileGet), + 182 => Some(Permission::DavFileMkCol), + 183 => Some(Permission::DavFileDelete), + 184 => Some(Permission::DavFilePut), + 185 => Some(Permission::DavFileCopy), + 186 => Some(Permission::DavFileMove), + 187 => Some(Permission::DavFileLock), + 188 => Some(Permission::DavFileAcl), + 189 => Some(Permission::DavCardPropFind), + 190 => Some(Permission::DavCardPropPatch), + 191 => Some(Permission::DavCardGet), + 192 => Some(Permission::DavCardMkCol), + 193 => Some(Permission::DavCardDelete), + 194 => Some(Permission::DavCardPut), + 195 => Some(Permission::DavCardCopy), + 196 => Some(Permission::DavCardMove), + 197 => Some(Permission::DavCardLock), + 198 => Some(Permission::DavCardAcl), + 199 => Some(Permission::DavCardQuery), + 200 => Some(Permission::DavCardMultiGet), + 201 => Some(Permission::DavCalPropFind), + 202 => Some(Permission::DavCalPropPatch), + 203 => Some(Permission::DavCalGet), + 204 => Some(Permission::DavCalMkCol), + 205 => Some(Permission::DavCalDelete), + 206 => Some(Permission::DavCalPut), + 207 => Some(Permission::DavCalCopy), + 208 => Some(Permission::DavCalMove), + 209 => Some(Permission::DavCalLock), + 210 => Some(Permission::DavCalAcl), + 211 => Some(Permission::DavCalQuery), + 212 => Some(Permission::DavCalMultiGet), + 213 => Some(Permission::DavCalFreeBusyQuery), + 214 => Some(Permission::OAuthClientRegistration), + 215 => Some(Permission::OAuthClientOverride), + 216 => Some(Permission::LiveTracing), + 217 => Some(Permission::LiveMetrics), + 218 => Some(Permission::LiveDeliveryTest), + 219 => Some(Permission::SysAccountGet), + 220 => Some(Permission::SysAccountCreate), + 221 => Some(Permission::SysAccountUpdate), + 222 => Some(Permission::SysAccountDestroy), + 223 => Some(Permission::SysAccountQuery), + 224 => Some(Permission::SysAccountPasswordGet), + 225 => Some(Permission::SysAccountPasswordUpdate), + 226 => Some(Permission::SysAccountSettingsGet), + 227 => Some(Permission::SysAccountSettingsUpdate), + 228 => Some(Permission::SysAcmeProviderGet), + 229 => Some(Permission::SysAcmeProviderCreate), + 230 => Some(Permission::SysAcmeProviderUpdate), + 231 => Some(Permission::SysAcmeProviderDestroy), + 232 => Some(Permission::SysAcmeProviderQuery), + 233 => Some(Permission::ActionReloadSettings), + 234 => Some(Permission::ActionReloadTlsCertificates), + 235 => Some(Permission::ActionReloadLookupStores), + 236 => Some(Permission::ActionReloadBlockedIps), + 237 => Some(Permission::ActionUpdateApps), + 238 => Some(Permission::ActionTroubleshootDmarc), + 239 => Some(Permission::ActionClassifySpam), + 240 => Some(Permission::ActionInvalidateCaches), + 241 => Some(Permission::ActionInvalidateNegativeCaches), + 242 => Some(Permission::ActionPauseMtaQueue), + 243 => Some(Permission::ActionResumeMtaQueue), + 244 => Some(Permission::SysActionGet), + 245 => Some(Permission::SysActionCreate), + 246 => Some(Permission::SysActionUpdate), + 247 => Some(Permission::SysActionDestroy), + 248 => Some(Permission::SysActionQuery), + 249 => Some(Permission::SysAddressBookGet), + 250 => Some(Permission::SysAddressBookUpdate), + 251 => Some(Permission::SysAiModelGet), + 252 => Some(Permission::SysAiModelCreate), + 253 => Some(Permission::SysAiModelUpdate), + 254 => Some(Permission::SysAiModelDestroy), + 255 => Some(Permission::SysAiModelQuery), + 256 => Some(Permission::SysAlertGet), + 257 => Some(Permission::SysAlertCreate), + 258 => Some(Permission::SysAlertUpdate), + 259 => Some(Permission::SysAlertDestroy), + 260 => Some(Permission::SysAlertQuery), + 261 => Some(Permission::SysAllowedIpGet), + 262 => Some(Permission::SysAllowedIpCreate), + 263 => Some(Permission::SysAllowedIpUpdate), + 264 => Some(Permission::SysAllowedIpDestroy), + 265 => Some(Permission::SysAllowedIpQuery), + 266 => Some(Permission::SysApiKeyGet), + 267 => Some(Permission::SysApiKeyCreate), + 268 => Some(Permission::SysApiKeyUpdate), + 269 => Some(Permission::SysApiKeyDestroy), + 270 => Some(Permission::SysApiKeyQuery), + 271 => Some(Permission::SysAppPasswordGet), + 272 => Some(Permission::SysAppPasswordCreate), + 273 => Some(Permission::SysAppPasswordUpdate), + 274 => Some(Permission::SysAppPasswordDestroy), + 275 => Some(Permission::SysAppPasswordQuery), + 276 => Some(Permission::SysApplicationGet), + 277 => Some(Permission::SysApplicationCreate), + 278 => Some(Permission::SysApplicationUpdate), + 279 => Some(Permission::SysApplicationDestroy), + 280 => Some(Permission::SysApplicationQuery), + 281 => Some(Permission::SysArchivedItemGet), + 282 => Some(Permission::SysArchivedItemCreate), + 283 => Some(Permission::SysArchivedItemUpdate), + 284 => Some(Permission::SysArchivedItemDestroy), + 285 => Some(Permission::SysArchivedItemQuery), + 286 => Some(Permission::SysArfExternalReportGet), + 287 => Some(Permission::SysArfExternalReportCreate), + 288 => Some(Permission::SysArfExternalReportUpdate), + 289 => Some(Permission::SysArfExternalReportDestroy), + 290 => Some(Permission::SysArfExternalReportQuery), + 291 => Some(Permission::SysAsnGet), + 292 => Some(Permission::SysAsnUpdate), + 293 => Some(Permission::SysAuthenticationGet), + 294 => Some(Permission::SysAuthenticationUpdate), + 295 => Some(Permission::SysBlobStoreGet), + 296 => Some(Permission::SysBlobStoreUpdate), + 297 => Some(Permission::SysBlockedIpGet), + 298 => Some(Permission::SysBlockedIpCreate), + 299 => Some(Permission::SysBlockedIpUpdate), + 300 => Some(Permission::SysBlockedIpDestroy), + 301 => Some(Permission::SysBlockedIpQuery), + 302 => Some(Permission::SysBootstrapGet), + 303 => Some(Permission::SysBootstrapUpdate), + 304 => Some(Permission::SysCacheGet), + 305 => Some(Permission::SysCacheUpdate), + 306 => Some(Permission::SysCalendarGet), + 307 => Some(Permission::SysCalendarUpdate), + 308 => Some(Permission::SysCalendarAlarmGet), + 309 => Some(Permission::SysCalendarAlarmUpdate), + 310 => Some(Permission::SysCalendarSchedulingGet), + 311 => Some(Permission::SysCalendarSchedulingUpdate), + 312 => Some(Permission::SysCertificateGet), + 313 => Some(Permission::SysCertificateCreate), + 314 => Some(Permission::SysCertificateUpdate), + 315 => Some(Permission::SysCertificateDestroy), + 316 => Some(Permission::SysCertificateQuery), + 317 => Some(Permission::SysClusterNodeGet), + 318 => Some(Permission::SysClusterNodeCreate), + 319 => Some(Permission::SysClusterNodeUpdate), + 320 => Some(Permission::SysClusterNodeDestroy), + 321 => Some(Permission::SysClusterNodeQuery), + 322 => Some(Permission::SysClusterRoleGet), + 323 => Some(Permission::SysClusterRoleCreate), + 324 => Some(Permission::SysClusterRoleUpdate), + 325 => Some(Permission::SysClusterRoleDestroy), + 326 => Some(Permission::SysClusterRoleQuery), + 327 => Some(Permission::SysCoordinatorGet), + 328 => Some(Permission::SysCoordinatorUpdate), + 329 => Some(Permission::SysDataRetentionGet), + 330 => Some(Permission::SysDataRetentionUpdate), + 331 => Some(Permission::SysDataStoreGet), + 332 => Some(Permission::SysDataStoreUpdate), + 333 => Some(Permission::SysDirectoryGet), + 334 => Some(Permission::SysDirectoryCreate), + 335 => Some(Permission::SysDirectoryUpdate), + 336 => Some(Permission::SysDirectoryDestroy), + 337 => Some(Permission::SysDirectoryQuery), + 338 => Some(Permission::SysDkimReportSettingsGet), + 339 => Some(Permission::SysDkimReportSettingsUpdate), + 340 => Some(Permission::SysDkimSignatureGet), + 341 => Some(Permission::SysDkimSignatureCreate), + 342 => Some(Permission::SysDkimSignatureUpdate), + 343 => Some(Permission::SysDkimSignatureDestroy), + 344 => Some(Permission::SysDkimSignatureQuery), + 345 => Some(Permission::SysDmarcExternalReportGet), + 346 => Some(Permission::SysDmarcExternalReportCreate), + 347 => Some(Permission::SysDmarcExternalReportUpdate), + 348 => Some(Permission::SysDmarcExternalReportDestroy), + 349 => Some(Permission::SysDmarcExternalReportQuery), + 350 => Some(Permission::SysDmarcInternalReportGet), + 351 => Some(Permission::SysDmarcInternalReportCreate), + 352 => Some(Permission::SysDmarcInternalReportUpdate), + 353 => Some(Permission::SysDmarcInternalReportDestroy), + 354 => Some(Permission::SysDmarcInternalReportQuery), + 355 => Some(Permission::SysDmarcReportSettingsGet), + 356 => Some(Permission::SysDmarcReportSettingsUpdate), + 357 => Some(Permission::SysDnsResolverGet), + 358 => Some(Permission::SysDnsResolverUpdate), + 359 => Some(Permission::SysDnsServerGet), + 360 => Some(Permission::SysDnsServerCreate), + 361 => Some(Permission::SysDnsServerUpdate), + 362 => Some(Permission::SysDnsServerDestroy), + 363 => Some(Permission::SysDnsServerQuery), + 364 => Some(Permission::SysDomainGet), + 365 => Some(Permission::SysDomainCreate), + 366 => Some(Permission::SysDomainUpdate), + 367 => Some(Permission::SysDomainDestroy), + 368 => Some(Permission::SysDomainQuery), + 369 => Some(Permission::SysDsnReportSettingsGet), + 370 => Some(Permission::SysDsnReportSettingsUpdate), + 371 => Some(Permission::SysEmailGet), + 372 => Some(Permission::SysEmailUpdate), + 373 => Some(Permission::SysEnterpriseGet), + 374 => Some(Permission::SysEnterpriseUpdate), + 375 => Some(Permission::SysEventTracingLevelGet), + 376 => Some(Permission::SysEventTracingLevelCreate), + 377 => Some(Permission::SysEventTracingLevelUpdate), + 378 => Some(Permission::SysEventTracingLevelDestroy), + 379 => Some(Permission::SysEventTracingLevelQuery), + 380 => Some(Permission::SysFileStorageGet), + 381 => Some(Permission::SysFileStorageUpdate), + 382 => Some(Permission::SysHttpGet), + 383 => Some(Permission::SysHttpUpdate), + 384 => Some(Permission::SysHttpFormGet), + 385 => Some(Permission::SysHttpFormUpdate), + 386 => Some(Permission::SysHttpLookupGet), + 387 => Some(Permission::SysHttpLookupCreate), + 388 => Some(Permission::SysHttpLookupUpdate), + 389 => Some(Permission::SysHttpLookupDestroy), + 390 => Some(Permission::SysHttpLookupQuery), + 391 => Some(Permission::SysImapGet), + 392 => Some(Permission::SysImapUpdate), + 393 => Some(Permission::SysInMemoryStoreGet), + 394 => Some(Permission::SysInMemoryStoreUpdate), + 395 => Some(Permission::SysJmapGet), + 396 => Some(Permission::SysJmapUpdate), + 397 => Some(Permission::SysLogGet), + 398 => Some(Permission::SysLogCreate), + 399 => Some(Permission::SysLogUpdate), + 400 => Some(Permission::SysLogDestroy), + 401 => Some(Permission::SysLogQuery), + 402 => Some(Permission::SysMailingListGet), + 403 => Some(Permission::SysMailingListCreate), + 404 => Some(Permission::SysMailingListUpdate), + 405 => Some(Permission::SysMailingListDestroy), + 406 => Some(Permission::SysMailingListQuery), + 407 => Some(Permission::SysMaskedEmailGet), + 408 => Some(Permission::SysMaskedEmailCreate), + 409 => Some(Permission::SysMaskedEmailUpdate), + 410 => Some(Permission::SysMaskedEmailDestroy), + 411 => Some(Permission::SysMaskedEmailQuery), + 412 => Some(Permission::SysMemoryLookupKeyGet), + 413 => Some(Permission::SysMemoryLookupKeyCreate), + 414 => Some(Permission::SysMemoryLookupKeyUpdate), + 415 => Some(Permission::SysMemoryLookupKeyDestroy), + 416 => Some(Permission::SysMemoryLookupKeyQuery), + 417 => Some(Permission::SysMemoryLookupKeyValueGet), + 418 => Some(Permission::SysMemoryLookupKeyValueCreate), + 419 => Some(Permission::SysMemoryLookupKeyValueUpdate), + 420 => Some(Permission::SysMemoryLookupKeyValueDestroy), + 421 => Some(Permission::SysMemoryLookupKeyValueQuery), + 422 => Some(Permission::SysMetricGet), + 423 => Some(Permission::SysMetricCreate), + 424 => Some(Permission::SysMetricUpdate), + 425 => Some(Permission::SysMetricDestroy), + 426 => Some(Permission::SysMetricQuery), + 427 => Some(Permission::SysMetricsGet), + 428 => Some(Permission::SysMetricsUpdate), + 429 => Some(Permission::SysMetricsStoreGet), + 430 => Some(Permission::SysMetricsStoreUpdate), + 431 => Some(Permission::SysMtaConnectionStrategyGet), + 432 => Some(Permission::SysMtaConnectionStrategyCreate), + 433 => Some(Permission::SysMtaConnectionStrategyUpdate), + 434 => Some(Permission::SysMtaConnectionStrategyDestroy), + 435 => Some(Permission::SysMtaConnectionStrategyQuery), + 436 => Some(Permission::SysMtaDeliveryScheduleGet), + 437 => Some(Permission::SysMtaDeliveryScheduleCreate), + 438 => Some(Permission::SysMtaDeliveryScheduleUpdate), + 439 => Some(Permission::SysMtaDeliveryScheduleDestroy), + 440 => Some(Permission::SysMtaDeliveryScheduleQuery), + 441 => Some(Permission::SysMtaExtensionsGet), + 442 => Some(Permission::SysMtaExtensionsUpdate), + 443 => Some(Permission::SysMtaHookGet), + 444 => Some(Permission::SysMtaHookCreate), + 445 => Some(Permission::SysMtaHookUpdate), + 446 => Some(Permission::SysMtaHookDestroy), + 447 => Some(Permission::SysMtaHookQuery), + 448 => Some(Permission::SysMtaInboundSessionGet), + 449 => Some(Permission::SysMtaInboundSessionUpdate), + 450 => Some(Permission::SysMtaInboundThrottleGet), + 451 => Some(Permission::SysMtaInboundThrottleCreate), + 452 => Some(Permission::SysMtaInboundThrottleUpdate), + 453 => Some(Permission::SysMtaInboundThrottleDestroy), + 454 => Some(Permission::SysMtaInboundThrottleQuery), + 455 => Some(Permission::SysMtaMilterGet), + 456 => Some(Permission::SysMtaMilterCreate), + 457 => Some(Permission::SysMtaMilterUpdate), + 458 => Some(Permission::SysMtaMilterDestroy), + 459 => Some(Permission::SysMtaMilterQuery), + 460 => Some(Permission::SysMtaOutboundStrategyGet), + 461 => Some(Permission::SysMtaOutboundStrategyUpdate), + 462 => Some(Permission::SysMtaOutboundThrottleGet), + 463 => Some(Permission::SysMtaOutboundThrottleCreate), + 464 => Some(Permission::SysMtaOutboundThrottleUpdate), + 465 => Some(Permission::SysMtaOutboundThrottleDestroy), + 466 => Some(Permission::SysMtaOutboundThrottleQuery), + 467 => Some(Permission::SysMtaQueueQuotaGet), + 468 => Some(Permission::SysMtaQueueQuotaCreate), + 469 => Some(Permission::SysMtaQueueQuotaUpdate), + 470 => Some(Permission::SysMtaQueueQuotaDestroy), + 471 => Some(Permission::SysMtaQueueQuotaQuery), + 472 => Some(Permission::SysMtaRouteGet), + 473 => Some(Permission::SysMtaRouteCreate), + 474 => Some(Permission::SysMtaRouteUpdate), + 475 => Some(Permission::SysMtaRouteDestroy), + 476 => Some(Permission::SysMtaRouteQuery), + 477 => Some(Permission::SysMtaStageAuthGet), + 478 => Some(Permission::SysMtaStageAuthUpdate), + 479 => Some(Permission::SysMtaStageConnectGet), + 480 => Some(Permission::SysMtaStageConnectUpdate), + 481 => Some(Permission::SysMtaStageDataGet), + 482 => Some(Permission::SysMtaStageDataUpdate), + 483 => Some(Permission::SysMtaStageEhloGet), + 484 => Some(Permission::SysMtaStageEhloUpdate), + 485 => Some(Permission::SysMtaStageMailGet), + 486 => Some(Permission::SysMtaStageMailUpdate), + 487 => Some(Permission::SysMtaStageRcptGet), + 488 => Some(Permission::SysMtaStageRcptUpdate), + 489 => Some(Permission::SysMtaStsGet), + 490 => Some(Permission::SysMtaStsUpdate), + 491 => Some(Permission::SysMtaTlsStrategyGet), + 492 => Some(Permission::SysMtaTlsStrategyCreate), + 493 => Some(Permission::SysMtaTlsStrategyUpdate), + 494 => Some(Permission::SysMtaTlsStrategyDestroy), + 495 => Some(Permission::SysMtaTlsStrategyQuery), + 496 => Some(Permission::SysMtaVirtualQueueGet), + 497 => Some(Permission::SysMtaVirtualQueueCreate), + 498 => Some(Permission::SysMtaVirtualQueueUpdate), + 499 => Some(Permission::SysMtaVirtualQueueDestroy), + 500 => Some(Permission::SysMtaVirtualQueueQuery), + 501 => Some(Permission::SysNetworkListenerGet), + 502 => Some(Permission::SysNetworkListenerCreate), + 503 => Some(Permission::SysNetworkListenerUpdate), + 504 => Some(Permission::SysNetworkListenerDestroy), + 505 => Some(Permission::SysNetworkListenerQuery), + 506 => Some(Permission::SysOAuthClientGet), + 507 => Some(Permission::SysOAuthClientCreate), + 508 => Some(Permission::SysOAuthClientUpdate), + 509 => Some(Permission::SysOAuthClientDestroy), + 510 => Some(Permission::SysOAuthClientQuery), + 511 => Some(Permission::SysOidcProviderGet), + 512 => Some(Permission::SysOidcProviderUpdate), + 513 => Some(Permission::SysPublicKeyGet), + 514 => Some(Permission::SysPublicKeyCreate), + 515 => Some(Permission::SysPublicKeyUpdate), + 516 => Some(Permission::SysPublicKeyDestroy), + 517 => Some(Permission::SysPublicKeyQuery), + 518 => Some(Permission::SysQueuedMessageGet), + 519 => Some(Permission::SysQueuedMessageCreate), + 520 => Some(Permission::SysQueuedMessageUpdate), + 521 => Some(Permission::SysQueuedMessageDestroy), + 522 => Some(Permission::SysQueuedMessageQuery), + 523 => Some(Permission::SysReportSettingsGet), + 524 => Some(Permission::SysReportSettingsUpdate), + 525 => Some(Permission::SysRoleGet), + 526 => Some(Permission::SysRoleCreate), + 527 => Some(Permission::SysRoleUpdate), + 528 => Some(Permission::SysRoleDestroy), + 529 => Some(Permission::SysRoleQuery), + 530 => Some(Permission::SysSearchGet), + 531 => Some(Permission::SysSearchUpdate), + 532 => Some(Permission::SysSearchStoreGet), + 533 => Some(Permission::SysSearchStoreUpdate), + 534 => Some(Permission::SysSecurityGet), + 535 => Some(Permission::SysSecurityUpdate), + 536 => Some(Permission::SysSenderAuthGet), + 537 => Some(Permission::SysSenderAuthUpdate), + 538 => Some(Permission::SysSharingGet), + 539 => Some(Permission::SysSharingUpdate), + 540 => Some(Permission::SysSieveSystemInterpreterGet), + 541 => Some(Permission::SysSieveSystemInterpreterUpdate), + 542 => Some(Permission::SysSieveSystemScriptGet), + 543 => Some(Permission::SysSieveSystemScriptCreate), + 544 => Some(Permission::SysSieveSystemScriptUpdate), + 545 => Some(Permission::SysSieveSystemScriptDestroy), + 546 => Some(Permission::SysSieveSystemScriptQuery), + 547 => Some(Permission::SysSieveUserInterpreterGet), + 548 => Some(Permission::SysSieveUserInterpreterUpdate), + 549 => Some(Permission::SysSieveUserScriptGet), + 550 => Some(Permission::SysSieveUserScriptCreate), + 551 => Some(Permission::SysSieveUserScriptUpdate), + 552 => Some(Permission::SysSieveUserScriptDestroy), + 553 => Some(Permission::SysSieveUserScriptQuery), + 554 => Some(Permission::SysSpamClassifierGet), + 555 => Some(Permission::SysSpamClassifierUpdate), + 556 => Some(Permission::SysSpamDnsblServerGet), + 557 => Some(Permission::SysSpamDnsblServerCreate), + 558 => Some(Permission::SysSpamDnsblServerUpdate), + 559 => Some(Permission::SysSpamDnsblServerDestroy), + 560 => Some(Permission::SysSpamDnsblServerQuery), + 561 => Some(Permission::SysSpamDnsblSettingsGet), + 562 => Some(Permission::SysSpamDnsblSettingsUpdate), + 563 => Some(Permission::SysSpamFileExtensionGet), + 564 => Some(Permission::SysSpamFileExtensionCreate), + 565 => Some(Permission::SysSpamFileExtensionUpdate), + 566 => Some(Permission::SysSpamFileExtensionDestroy), + 567 => Some(Permission::SysSpamFileExtensionQuery), + 568 => Some(Permission::SysSpamLlmGet), + 569 => Some(Permission::SysSpamLlmUpdate), + 570 => Some(Permission::SysSpamPyzorGet), + 571 => Some(Permission::SysSpamPyzorUpdate), + 572 => Some(Permission::SysSpamRuleGet), + 573 => Some(Permission::SysSpamRuleCreate), + 574 => Some(Permission::SysSpamRuleUpdate), + 575 => Some(Permission::SysSpamRuleDestroy), + 576 => Some(Permission::SysSpamRuleQuery), + 577 => Some(Permission::SysSpamSettingsGet), + 578 => Some(Permission::SysSpamSettingsUpdate), + 579 => Some(Permission::SysSpamTagGet), + 580 => Some(Permission::SysSpamTagCreate), + 581 => Some(Permission::SysSpamTagUpdate), + 582 => Some(Permission::SysSpamTagDestroy), + 583 => Some(Permission::SysSpamTagQuery), + 584 => Some(Permission::SysSpamTrainingSampleGet), + 585 => Some(Permission::SysSpamTrainingSampleCreate), + 586 => Some(Permission::SysSpamTrainingSampleUpdate), + 587 => Some(Permission::SysSpamTrainingSampleDestroy), + 588 => Some(Permission::SysSpamTrainingSampleQuery), + 589 => Some(Permission::SysSpfReportSettingsGet), + 590 => Some(Permission::SysSpfReportSettingsUpdate), + 591 => Some(Permission::SysStoreLookupGet), + 592 => Some(Permission::SysStoreLookupCreate), + 593 => Some(Permission::SysStoreLookupUpdate), + 594 => Some(Permission::SysStoreLookupDestroy), + 595 => Some(Permission::SysStoreLookupQuery), + 596 => Some(Permission::SysSystemSettingsGet), + 597 => Some(Permission::SysSystemSettingsUpdate), + 598 => Some(Permission::TaskIndexDocument), + 599 => Some(Permission::TaskUnindexDocument), + 600 => Some(Permission::TaskIndexTrace), + 601 => Some(Permission::TaskCalendarAlarmEmail), + 602 => Some(Permission::TaskCalendarAlarmNotification), + 603 => Some(Permission::TaskCalendarItipMessage), + 604 => Some(Permission::TaskMergeThreads), + 605 => Some(Permission::TaskDmarcReport), + 606 => Some(Permission::TaskTlsReport), + 607 => Some(Permission::TaskRestoreArchivedItem), + 608 => Some(Permission::TaskDestroyAccount), + 609 => Some(Permission::TaskAccountMaintenance), + 610 => Some(Permission::TaskTenantMaintenance), + 611 => Some(Permission::TaskStoreMaintenance), + 612 => Some(Permission::TaskSpamFilterMaintenance), + 613 => Some(Permission::TaskAcmeRenewal), + 614 => Some(Permission::TaskDkimManagement), + 615 => Some(Permission::TaskDnsManagement), + 616 => Some(Permission::SysTaskGet), + 617 => Some(Permission::SysTaskCreate), + 618 => Some(Permission::SysTaskUpdate), + 619 => Some(Permission::SysTaskDestroy), + 620 => Some(Permission::SysTaskQuery), + 621 => Some(Permission::SysTaskManagerGet), + 622 => Some(Permission::SysTaskManagerUpdate), + 623 => Some(Permission::SysTenantGet), + 624 => Some(Permission::SysTenantCreate), + 625 => Some(Permission::SysTenantUpdate), + 626 => Some(Permission::SysTenantDestroy), + 627 => Some(Permission::SysTenantQuery), + 628 => Some(Permission::SysTlsExternalReportGet), + 629 => Some(Permission::SysTlsExternalReportCreate), + 630 => Some(Permission::SysTlsExternalReportUpdate), + 631 => Some(Permission::SysTlsExternalReportDestroy), + 632 => Some(Permission::SysTlsExternalReportQuery), + 633 => Some(Permission::SysTlsInternalReportGet), + 634 => Some(Permission::SysTlsInternalReportCreate), + 635 => Some(Permission::SysTlsInternalReportUpdate), + 636 => Some(Permission::SysTlsInternalReportDestroy), + 637 => Some(Permission::SysTlsInternalReportQuery), + 638 => Some(Permission::SysTlsReportSettingsGet), + 639 => Some(Permission::SysTlsReportSettingsUpdate), + 640 => Some(Permission::SysTraceGet), + 641 => Some(Permission::SysTraceCreate), + 642 => Some(Permission::SysTraceUpdate), + 643 => Some(Permission::SysTraceDestroy), + 644 => Some(Permission::SysTraceQuery), + 645 => Some(Permission::SysTracerGet), + 646 => Some(Permission::SysTracerCreate), + 647 => Some(Permission::SysTracerUpdate), + 648 => Some(Permission::SysTracerDestroy), + 649 => Some(Permission::SysTracerQuery), + 650 => Some(Permission::SysTracingStoreGet), + 651 => Some(Permission::SysTracingStoreUpdate), + 652 => Some(Permission::SysWebDavGet), + 653 => Some(Permission::SysWebDavUpdate), + 654 => Some(Permission::SysWebHookGet), + 655 => Some(Permission::SysWebHookCreate), + 656 => Some(Permission::SysWebHookUpdate), + 657 => Some(Permission::SysWebHookDestroy), + 658 => Some(Permission::SysWebHookQuery), + _ => None, + } + } + + const COUNT: usize = 659; +} + +impl serde::Serialize for Permission { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for Permission { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PermissionsType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Inherit" => PermissionsType::Inherit, + b"Merge" => PermissionsType::Merge, + b"Replace" => PermissionsType::Replace, + } + } + + fn as_str(&self) -> &'static str { + match self { + PermissionsType::Inherit => "Inherit", + PermissionsType::Merge => "Merge", + PermissionsType::Replace => "Replace", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PermissionsType::Inherit), + 1 => Some(PermissionsType::Merge), + 2 => Some(PermissionsType::Replace), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for PermissionsType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PermissionsType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PolicyEnforcement { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"enforce" => PolicyEnforcement::Enforce, + b"testing" => PolicyEnforcement::Testing, + b"disable" => PolicyEnforcement::Disable, + } + } + + fn as_str(&self) -> &'static str { + match self { + PolicyEnforcement::Enforce => "enforce", + PolicyEnforcement::Testing => "testing", + PolicyEnforcement::Disable => "disable", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PolicyEnforcement::Enforce), + 1 => Some(PolicyEnforcement::Testing), + 2 => Some(PolicyEnforcement::Disable), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for PolicyEnforcement { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PolicyEnforcement { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PostgreSqlRecyclingMethod { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"fast" => PostgreSqlRecyclingMethod::Fast, + b"verified" => PostgreSqlRecyclingMethod::Verified, + b"clean" => PostgreSqlRecyclingMethod::Clean, + } + } + + fn as_str(&self) -> &'static str { + match self { + PostgreSqlRecyclingMethod::Fast => "fast", + PostgreSqlRecyclingMethod::Verified => "verified", + PostgreSqlRecyclingMethod::Clean => "clean", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PostgreSqlRecyclingMethod::Fast), + 1 => Some(PostgreSqlRecyclingMethod::Verified), + 2 => Some(PostgreSqlRecyclingMethod::Clean), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for PostgreSqlRecyclingMethod { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PostgreSqlRecyclingMethod { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ProviderInfo { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"providerName" => ProviderInfo::ProviderName, + b"providerShortName" => ProviderInfo::ProviderShortName, + b"userDocumentation" => ProviderInfo::UserDocumentation, + b"developerDocumentation" => ProviderInfo::DeveloperDocumentation, + b"contactUri" => ProviderInfo::ContactUri, + b"logoUrl" => ProviderInfo::LogoUrl, + b"logoWidth" => ProviderInfo::LogoWidth, + b"logoHeight" => ProviderInfo::LogoHeight, + } + } + + fn as_str(&self) -> &'static str { + match self { + ProviderInfo::ProviderName => "providerName", + ProviderInfo::ProviderShortName => "providerShortName", + ProviderInfo::UserDocumentation => "userDocumentation", + ProviderInfo::DeveloperDocumentation => "developerDocumentation", + ProviderInfo::ContactUri => "contactUri", + ProviderInfo::LogoUrl => "logoUrl", + ProviderInfo::LogoWidth => "logoWidth", + ProviderInfo::LogoHeight => "logoHeight", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ProviderInfo::ProviderName), + 1 => Some(ProviderInfo::ProviderShortName), + 2 => Some(ProviderInfo::UserDocumentation), + 3 => Some(ProviderInfo::DeveloperDocumentation), + 4 => Some(ProviderInfo::ContactUri), + 5 => Some(ProviderInfo::LogoUrl), + 6 => Some(ProviderInfo::LogoWidth), + 7 => Some(ProviderInfo::LogoHeight), + _ => None, + } + } + + const COUNT: usize = 8; +} + +impl serde::Serialize for ProviderInfo { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ProviderInfo { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for PublicTextType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Text" => PublicTextType::Text, + b"EnvironmentVariable" => PublicTextType::EnvironmentVariable, + b"File" => PublicTextType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + PublicTextType::Text => "Text", + PublicTextType::EnvironmentVariable => "EnvironmentVariable", + PublicTextType::File => "File", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(PublicTextType::Text), + 1 => Some(PublicTextType::EnvironmentVariable), + 2 => Some(PublicTextType::File), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for PublicTextType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for PublicTextType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for QueueExpiryType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Ttl" => QueueExpiryType::Ttl, + b"Attempts" => QueueExpiryType::Attempts, + } + } + + fn as_str(&self) -> &'static str { + match self { + QueueExpiryType::Ttl => "Ttl", + QueueExpiryType::Attempts => "Attempts", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(QueueExpiryType::Ttl), + 1 => Some(QueueExpiryType::Attempts), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for QueueExpiryType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for QueueExpiryType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for RecipientFlag { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"dsnSent" => RecipientFlag::DsnSent, + b"spamPayload" => RecipientFlag::SpamPayload, + } + } + + fn as_str(&self) -> &'static str { + match self { + RecipientFlag::DsnSent => "dsnSent", + RecipientFlag::SpamPayload => "spamPayload", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(RecipientFlag::DsnSent), + 1 => Some(RecipientFlag::SpamPayload), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for RecipientFlag { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for RecipientFlag { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for RecipientStatusType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Scheduled" => RecipientStatusType::Scheduled, + b"Completed" => RecipientStatusType::Completed, + b"TemporaryFailure" => RecipientStatusType::TemporaryFailure, + b"PermanentFailure" => RecipientStatusType::PermanentFailure, + } + } + + fn as_str(&self) -> &'static str { + match self { + RecipientStatusType::Scheduled => "Scheduled", + RecipientStatusType::Completed => "Completed", + RecipientStatusType::TemporaryFailure => "TemporaryFailure", + RecipientStatusType::PermanentFailure => "PermanentFailure", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(RecipientStatusType::Scheduled), + 1 => Some(RecipientStatusType::Completed), + 2 => Some(RecipientStatusType::TemporaryFailure), + 3 => Some(RecipientStatusType::PermanentFailure), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for RecipientStatusType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for RecipientStatusType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for RedisProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"resp2" => RedisProtocol::Resp2, + b"resp3" => RedisProtocol::Resp3, + } + } + + fn as_str(&self) -> &'static str { + match self { + RedisProtocol::Resp2 => "resp2", + RedisProtocol::Resp3 => "resp3", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(RedisProtocol::Resp2), + 1 => Some(RedisProtocol::Resp3), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for RedisProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for RedisProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for RolesType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => RolesType::Default, + b"Custom" => RolesType::Custom, + } + } + + fn as_str(&self) -> &'static str { + match self { + RolesType::Default => "Default", + RolesType::Custom => "Custom", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(RolesType::Default), + 1 => Some(RolesType::Custom), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for RolesType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for RolesType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for S3StoreRegionType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"UsEast1" => S3StoreRegionType::UsEast1, + b"UsEast2" => S3StoreRegionType::UsEast2, + b"UsWest1" => S3StoreRegionType::UsWest1, + b"UsWest2" => S3StoreRegionType::UsWest2, + b"CaCentral1" => S3StoreRegionType::CaCentral1, + b"AfSouth1" => S3StoreRegionType::AfSouth1, + b"ApEast1" => S3StoreRegionType::ApEast1, + b"ApSouth1" => S3StoreRegionType::ApSouth1, + b"ApNortheast1" => S3StoreRegionType::ApNortheast1, + b"ApNortheast2" => S3StoreRegionType::ApNortheast2, + b"ApNortheast3" => S3StoreRegionType::ApNortheast3, + b"ApSoutheast1" => S3StoreRegionType::ApSoutheast1, + b"ApSoutheast2" => S3StoreRegionType::ApSoutheast2, + b"CnNorth1" => S3StoreRegionType::CnNorth1, + b"CnNorthwest1" => S3StoreRegionType::CnNorthwest1, + b"EuNorth1" => S3StoreRegionType::EuNorth1, + b"EuCentral1" => S3StoreRegionType::EuCentral1, + b"EuCentral2" => S3StoreRegionType::EuCentral2, + b"EuWest1" => S3StoreRegionType::EuWest1, + b"EuWest2" => S3StoreRegionType::EuWest2, + b"EuWest3" => S3StoreRegionType::EuWest3, + b"IlCentral1" => S3StoreRegionType::IlCentral1, + b"MeSouth1" => S3StoreRegionType::MeSouth1, + b"SaEast1" => S3StoreRegionType::SaEast1, + b"DoNyc3" => S3StoreRegionType::DoNyc3, + b"DoAms3" => S3StoreRegionType::DoAms3, + b"DoSgp1" => S3StoreRegionType::DoSgp1, + b"DoFra1" => S3StoreRegionType::DoFra1, + b"Yandex" => S3StoreRegionType::Yandex, + b"WaUsEast1" => S3StoreRegionType::WaUsEast1, + b"WaUsEast2" => S3StoreRegionType::WaUsEast2, + b"WaUsCentral1" => S3StoreRegionType::WaUsCentral1, + b"WaUsWest1" => S3StoreRegionType::WaUsWest1, + b"WaCaCentral1" => S3StoreRegionType::WaCaCentral1, + b"WaEuCentral1" => S3StoreRegionType::WaEuCentral1, + b"WaEuCentral2" => S3StoreRegionType::WaEuCentral2, + b"WaEuWest1" => S3StoreRegionType::WaEuWest1, + b"WaEuWest2" => S3StoreRegionType::WaEuWest2, + b"WaApNortheast1" => S3StoreRegionType::WaApNortheast1, + b"WaApNortheast2" => S3StoreRegionType::WaApNortheast2, + b"WaApSoutheast1" => S3StoreRegionType::WaApSoutheast1, + b"WaApSoutheast2" => S3StoreRegionType::WaApSoutheast2, + b"Custom" => S3StoreRegionType::Custom, + } + } + + fn as_str(&self) -> &'static str { + match self { + S3StoreRegionType::UsEast1 => "UsEast1", + S3StoreRegionType::UsEast2 => "UsEast2", + S3StoreRegionType::UsWest1 => "UsWest1", + S3StoreRegionType::UsWest2 => "UsWest2", + S3StoreRegionType::CaCentral1 => "CaCentral1", + S3StoreRegionType::AfSouth1 => "AfSouth1", + S3StoreRegionType::ApEast1 => "ApEast1", + S3StoreRegionType::ApSouth1 => "ApSouth1", + S3StoreRegionType::ApNortheast1 => "ApNortheast1", + S3StoreRegionType::ApNortheast2 => "ApNortheast2", + S3StoreRegionType::ApNortheast3 => "ApNortheast3", + S3StoreRegionType::ApSoutheast1 => "ApSoutheast1", + S3StoreRegionType::ApSoutheast2 => "ApSoutheast2", + S3StoreRegionType::CnNorth1 => "CnNorth1", + S3StoreRegionType::CnNorthwest1 => "CnNorthwest1", + S3StoreRegionType::EuNorth1 => "EuNorth1", + S3StoreRegionType::EuCentral1 => "EuCentral1", + S3StoreRegionType::EuCentral2 => "EuCentral2", + S3StoreRegionType::EuWest1 => "EuWest1", + S3StoreRegionType::EuWest2 => "EuWest2", + S3StoreRegionType::EuWest3 => "EuWest3", + S3StoreRegionType::IlCentral1 => "IlCentral1", + S3StoreRegionType::MeSouth1 => "MeSouth1", + S3StoreRegionType::SaEast1 => "SaEast1", + S3StoreRegionType::DoNyc3 => "DoNyc3", + S3StoreRegionType::DoAms3 => "DoAms3", + S3StoreRegionType::DoSgp1 => "DoSgp1", + S3StoreRegionType::DoFra1 => "DoFra1", + S3StoreRegionType::Yandex => "Yandex", + S3StoreRegionType::WaUsEast1 => "WaUsEast1", + S3StoreRegionType::WaUsEast2 => "WaUsEast2", + S3StoreRegionType::WaUsCentral1 => "WaUsCentral1", + S3StoreRegionType::WaUsWest1 => "WaUsWest1", + S3StoreRegionType::WaCaCentral1 => "WaCaCentral1", + S3StoreRegionType::WaEuCentral1 => "WaEuCentral1", + S3StoreRegionType::WaEuCentral2 => "WaEuCentral2", + S3StoreRegionType::WaEuWest1 => "WaEuWest1", + S3StoreRegionType::WaEuWest2 => "WaEuWest2", + S3StoreRegionType::WaApNortheast1 => "WaApNortheast1", + S3StoreRegionType::WaApNortheast2 => "WaApNortheast2", + S3StoreRegionType::WaApSoutheast1 => "WaApSoutheast1", + S3StoreRegionType::WaApSoutheast2 => "WaApSoutheast2", + S3StoreRegionType::Custom => "Custom", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(S3StoreRegionType::UsEast1), + 1 => Some(S3StoreRegionType::UsEast2), + 2 => Some(S3StoreRegionType::UsWest1), + 3 => Some(S3StoreRegionType::UsWest2), + 4 => Some(S3StoreRegionType::CaCentral1), + 5 => Some(S3StoreRegionType::AfSouth1), + 6 => Some(S3StoreRegionType::ApEast1), + 7 => Some(S3StoreRegionType::ApSouth1), + 8 => Some(S3StoreRegionType::ApNortheast1), + 9 => Some(S3StoreRegionType::ApNortheast2), + 10 => Some(S3StoreRegionType::ApNortheast3), + 11 => Some(S3StoreRegionType::ApSoutheast1), + 12 => Some(S3StoreRegionType::ApSoutheast2), + 13 => Some(S3StoreRegionType::CnNorth1), + 14 => Some(S3StoreRegionType::CnNorthwest1), + 15 => Some(S3StoreRegionType::EuNorth1), + 16 => Some(S3StoreRegionType::EuCentral1), + 17 => Some(S3StoreRegionType::EuCentral2), + 18 => Some(S3StoreRegionType::EuWest1), + 19 => Some(S3StoreRegionType::EuWest2), + 20 => Some(S3StoreRegionType::EuWest3), + 21 => Some(S3StoreRegionType::IlCentral1), + 22 => Some(S3StoreRegionType::MeSouth1), + 23 => Some(S3StoreRegionType::SaEast1), + 24 => Some(S3StoreRegionType::DoNyc3), + 25 => Some(S3StoreRegionType::DoAms3), + 26 => Some(S3StoreRegionType::DoSgp1), + 27 => Some(S3StoreRegionType::DoFra1), + 28 => Some(S3StoreRegionType::Yandex), + 29 => Some(S3StoreRegionType::WaUsEast1), + 30 => Some(S3StoreRegionType::WaUsEast2), + 31 => Some(S3StoreRegionType::WaUsCentral1), + 32 => Some(S3StoreRegionType::WaUsWest1), + 33 => Some(S3StoreRegionType::WaCaCentral1), + 34 => Some(S3StoreRegionType::WaEuCentral1), + 35 => Some(S3StoreRegionType::WaEuCentral2), + 36 => Some(S3StoreRegionType::WaEuWest1), + 37 => Some(S3StoreRegionType::WaEuWest2), + 38 => Some(S3StoreRegionType::WaApNortheast1), + 39 => Some(S3StoreRegionType::WaApNortheast2), + 40 => Some(S3StoreRegionType::WaApSoutheast1), + 41 => Some(S3StoreRegionType::WaApSoutheast2), + 42 => Some(S3StoreRegionType::Custom), + _ => None, + } + } + + const COUNT: usize = 43; +} + +impl serde::Serialize for S3StoreRegionType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for S3StoreRegionType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchCalendarField { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"title" => SearchCalendarField::Title, + b"description" => SearchCalendarField::Description, + b"location" => SearchCalendarField::Location, + b"owner" => SearchCalendarField::Owner, + b"attendee" => SearchCalendarField::Attendee, + b"start" => SearchCalendarField::Start, + b"uid" => SearchCalendarField::Uid, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchCalendarField::Title => "title", + SearchCalendarField::Description => "description", + SearchCalendarField::Location => "location", + SearchCalendarField::Owner => "owner", + SearchCalendarField::Attendee => "attendee", + SearchCalendarField::Start => "start", + SearchCalendarField::Uid => "uid", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchCalendarField::Title), + 1 => Some(SearchCalendarField::Description), + 2 => Some(SearchCalendarField::Location), + 3 => Some(SearchCalendarField::Owner), + 4 => Some(SearchCalendarField::Attendee), + 5 => Some(SearchCalendarField::Start), + 6 => Some(SearchCalendarField::Uid), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for SearchCalendarField { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchCalendarField { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchContactField { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"member" => SearchContactField::Member, + b"kind" => SearchContactField::Kind, + b"name" => SearchContactField::Name, + b"nickname" => SearchContactField::Nickname, + b"organization" => SearchContactField::Organization, + b"email" => SearchContactField::Email, + b"phone" => SearchContactField::Phone, + b"onlineService" => SearchContactField::OnlineService, + b"address" => SearchContactField::Address, + b"note" => SearchContactField::Note, + b"uid" => SearchContactField::Uid, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchContactField::Member => "member", + SearchContactField::Kind => "kind", + SearchContactField::Name => "name", + SearchContactField::Nickname => "nickname", + SearchContactField::Organization => "organization", + SearchContactField::Email => "email", + SearchContactField::Phone => "phone", + SearchContactField::OnlineService => "onlineService", + SearchContactField::Address => "address", + SearchContactField::Note => "note", + SearchContactField::Uid => "uid", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchContactField::Member), + 1 => Some(SearchContactField::Kind), + 2 => Some(SearchContactField::Name), + 3 => Some(SearchContactField::Nickname), + 4 => Some(SearchContactField::Organization), + 5 => Some(SearchContactField::Email), + 6 => Some(SearchContactField::Phone), + 7 => Some(SearchContactField::OnlineService), + 8 => Some(SearchContactField::Address), + 9 => Some(SearchContactField::Note), + 10 => Some(SearchContactField::Uid), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for SearchContactField { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchContactField { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchEmailField { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"from" => SearchEmailField::From, + b"to" => SearchEmailField::To, + b"cc" => SearchEmailField::Cc, + b"bcc" => SearchEmailField::Bcc, + b"subject" => SearchEmailField::Subject, + b"body" => SearchEmailField::Body, + b"attachment" => SearchEmailField::Attachment, + b"receivedAt" => SearchEmailField::ReceivedAt, + b"sentAt" => SearchEmailField::SentAt, + b"size" => SearchEmailField::Size, + b"hasAttachment" => SearchEmailField::HasAttachment, + b"headers" => SearchEmailField::Headers, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchEmailField::From => "from", + SearchEmailField::To => "to", + SearchEmailField::Cc => "cc", + SearchEmailField::Bcc => "bcc", + SearchEmailField::Subject => "subject", + SearchEmailField::Body => "body", + SearchEmailField::Attachment => "attachment", + SearchEmailField::ReceivedAt => "receivedAt", + SearchEmailField::SentAt => "sentAt", + SearchEmailField::Size => "size", + SearchEmailField::HasAttachment => "hasAttachment", + SearchEmailField::Headers => "headers", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchEmailField::From), + 1 => Some(SearchEmailField::To), + 2 => Some(SearchEmailField::Cc), + 3 => Some(SearchEmailField::Bcc), + 4 => Some(SearchEmailField::Subject), + 5 => Some(SearchEmailField::Body), + 6 => Some(SearchEmailField::Attachment), + 7 => Some(SearchEmailField::ReceivedAt), + 8 => Some(SearchEmailField::SentAt), + 9 => Some(SearchEmailField::Size), + 10 => Some(SearchEmailField::HasAttachment), + 11 => Some(SearchEmailField::Headers), + _ => None, + } + } + + const COUNT: usize = 12; +} + +impl serde::Serialize for SearchEmailField { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchEmailField { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchFileField { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"name" => SearchFileField::Name, + b"content" => SearchFileField::Content, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchFileField::Name => "name", + SearchFileField::Content => "content", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchFileField::Name), + 1 => Some(SearchFileField::Content), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for SearchFileField { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchFileField { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => SearchStoreType::Default, + b"ElasticSearch" => SearchStoreType::ElasticSearch, + b"Meilisearch" => SearchStoreType::Meilisearch, + b"FoundationDb" => SearchStoreType::FoundationDb, + b"PostgreSql" => SearchStoreType::PostgreSql, + b"MySql" => SearchStoreType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchStoreType::Default => "Default", + SearchStoreType::ElasticSearch => "ElasticSearch", + SearchStoreType::Meilisearch => "Meilisearch", + SearchStoreType::FoundationDb => "FoundationDb", + SearchStoreType::PostgreSql => "PostgreSql", + SearchStoreType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchStoreType::Default), + 1 => Some(SearchStoreType::ElasticSearch), + 2 => Some(SearchStoreType::Meilisearch), + 3 => Some(SearchStoreType::FoundationDb), + 4 => Some(SearchStoreType::PostgreSql), + 5 => Some(SearchStoreType::MySql), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for SearchStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SearchTracingField { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"eventType" => SearchTracingField::EventType, + b"queueId" => SearchTracingField::QueueId, + b"keywords" => SearchTracingField::Keywords, + } + } + + fn as_str(&self) -> &'static str { + match self { + SearchTracingField::EventType => "eventType", + SearchTracingField::QueueId => "queueId", + SearchTracingField::Keywords => "keywords", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SearchTracingField::EventType), + 1 => Some(SearchTracingField::QueueId), + 2 => Some(SearchTracingField::Keywords), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SearchTracingField { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SearchTracingField { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SecretKeyOptionalType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"None" => SecretKeyOptionalType::None, + b"Value" => SecretKeyOptionalType::Value, + b"EnvironmentVariable" => SecretKeyOptionalType::EnvironmentVariable, + b"File" => SecretKeyOptionalType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + SecretKeyOptionalType::None => "None", + SecretKeyOptionalType::Value => "Value", + SecretKeyOptionalType::EnvironmentVariable => "EnvironmentVariable", + SecretKeyOptionalType::File => "File", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SecretKeyOptionalType::None), + 1 => Some(SecretKeyOptionalType::Value), + 2 => Some(SecretKeyOptionalType::EnvironmentVariable), + 3 => Some(SecretKeyOptionalType::File), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for SecretKeyOptionalType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SecretKeyOptionalType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SecretKeyType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Value" => SecretKeyType::Value, + b"EnvironmentVariable" => SecretKeyType::EnvironmentVariable, + b"File" => SecretKeyType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + SecretKeyType::Value => "Value", + SecretKeyType::EnvironmentVariable => "EnvironmentVariable", + SecretKeyType::File => "File", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SecretKeyType::Value), + 1 => Some(SecretKeyType::EnvironmentVariable), + 2 => Some(SecretKeyType::File), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SecretKeyType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SecretKeyType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SecretTextOptionalType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"None" => SecretTextOptionalType::None, + b"Text" => SecretTextOptionalType::Text, + b"EnvironmentVariable" => SecretTextOptionalType::EnvironmentVariable, + b"File" => SecretTextOptionalType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + SecretTextOptionalType::None => "None", + SecretTextOptionalType::Text => "Text", + SecretTextOptionalType::EnvironmentVariable => "EnvironmentVariable", + SecretTextOptionalType::File => "File", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SecretTextOptionalType::None), + 1 => Some(SecretTextOptionalType::Text), + 2 => Some(SecretTextOptionalType::EnvironmentVariable), + 3 => Some(SecretTextOptionalType::File), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for SecretTextOptionalType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SecretTextOptionalType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SecretTextType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Text" => SecretTextType::Text, + b"EnvironmentVariable" => SecretTextType::EnvironmentVariable, + b"File" => SecretTextType::File, + } + } + + fn as_str(&self) -> &'static str { + match self { + SecretTextType::Text => "Text", + SecretTextType::EnvironmentVariable => "EnvironmentVariable", + SecretTextType::File => "File", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SecretTextType::Text), + 1 => Some(SecretTextType::EnvironmentVariable), + 2 => Some(SecretTextType::File), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SecretTextType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SecretTextType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for ServiceProtocol { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"jmap" => ServiceProtocol::Jmap, + b"imap" => ServiceProtocol::Imap, + b"pop3" => ServiceProtocol::Pop3, + b"smtp" => ServiceProtocol::Smtp, + b"caldav" => ServiceProtocol::Caldav, + b"carddav" => ServiceProtocol::Carddav, + b"webdav" => ServiceProtocol::Webdav, + b"managesieve" => ServiceProtocol::Managesieve, + } + } + + fn as_str(&self) -> &'static str { + match self { + ServiceProtocol::Jmap => "jmap", + ServiceProtocol::Imap => "imap", + ServiceProtocol::Pop3 => "pop3", + ServiceProtocol::Smtp => "smtp", + ServiceProtocol::Caldav => "caldav", + ServiceProtocol::Carddav => "carddav", + ServiceProtocol::Webdav => "webdav", + ServiceProtocol::Managesieve => "managesieve", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ServiceProtocol::Jmap), + 1 => Some(ServiceProtocol::Imap), + 2 => Some(ServiceProtocol::Pop3), + 3 => Some(ServiceProtocol::Smtp), + 4 => Some(ServiceProtocol::Caldav), + 5 => Some(ServiceProtocol::Carddav), + 6 => Some(ServiceProtocol::Webdav), + 7 => Some(ServiceProtocol::Managesieve), + _ => None, + } + } + + const COUNT: usize = 8; +} + +impl serde::Serialize for ServiceProtocol { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ServiceProtocol { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SieveCapability { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"envelope" => SieveCapability::Envelope, + b"envelope-dsn" => SieveCapability::EnvelopeDsn, + b"envelope-deliverby" => SieveCapability::EnvelopeDeliverby, + b"fileinto" => SieveCapability::Fileinto, + b"encoded-character" => SieveCapability::EncodedCharacter, + b"comparator-elbonia" => SieveCapability::ComparatorElbonia, + b"comparator-i;octet" => SieveCapability::ComparatorIOctet, + b"comparator-i;ascii-casemap" => SieveCapability::ComparatorIAsciiCasemap, + b"comparator-i;ascii-numeric" => SieveCapability::ComparatorIAsciiNumeric, + b"body" => SieveCapability::Body, + b"convert" => SieveCapability::Convert, + b"copy" => SieveCapability::Copy, + b"relational" => SieveCapability::Relational, + b"date" => SieveCapability::Date, + b"index" => SieveCapability::Index, + b"duplicate" => SieveCapability::Duplicate, + b"variables" => SieveCapability::Variables, + b"editheader" => SieveCapability::Editheader, + b"foreverypart" => SieveCapability::Foreverypart, + b"mime" => SieveCapability::Mime, + b"replace" => SieveCapability::Replace, + b"enclose" => SieveCapability::Enclose, + b"extracttext" => SieveCapability::Extracttext, + b"enotify" => SieveCapability::Enotify, + b"redirect-dsn" => SieveCapability::RedirectDsn, + b"redirect-deliverby" => SieveCapability::RedirectDeliverby, + b"environment" => SieveCapability::Environment, + b"reject" => SieveCapability::Reject, + b"ereject" => SieveCapability::Ereject, + b"extlists" => SieveCapability::Extlists, + b"subaddress" => SieveCapability::Subaddress, + b"vacation" => SieveCapability::Vacation, + b"vacation-seconds" => SieveCapability::VacationSeconds, + b"fcc" => SieveCapability::Fcc, + b"mailbox" => SieveCapability::Mailbox, + b"mailboxid" => SieveCapability::Mailboxid, + b"mboxmetadata" => SieveCapability::Mboxmetadata, + b"servermetadata" => SieveCapability::Servermetadata, + b"special-use" => SieveCapability::SpecialUse, + b"imap4flags" => SieveCapability::Imap4flags, + b"ihave" => SieveCapability::Ihave, + b"imapsieve" => SieveCapability::Imapsieve, + b"include" => SieveCapability::Include, + b"regex" => SieveCapability::Regex, + b"spamtest" => SieveCapability::Spamtest, + b"spamtestplus" => SieveCapability::Spamtestplus, + b"virustest" => SieveCapability::Virustest, + b"vnd.stalwart.while" => SieveCapability::VndStalwartWhile, + b"vnd.stalwart.expressions" => SieveCapability::VndStalwartExpressions, + } + } + + fn as_str(&self) -> &'static str { + match self { + SieveCapability::Envelope => "envelope", + SieveCapability::EnvelopeDsn => "envelope-dsn", + SieveCapability::EnvelopeDeliverby => "envelope-deliverby", + SieveCapability::Fileinto => "fileinto", + SieveCapability::EncodedCharacter => "encoded-character", + SieveCapability::ComparatorElbonia => "comparator-elbonia", + SieveCapability::ComparatorIOctet => "comparator-i;octet", + SieveCapability::ComparatorIAsciiCasemap => "comparator-i;ascii-casemap", + SieveCapability::ComparatorIAsciiNumeric => "comparator-i;ascii-numeric", + SieveCapability::Body => "body", + SieveCapability::Convert => "convert", + SieveCapability::Copy => "copy", + SieveCapability::Relational => "relational", + SieveCapability::Date => "date", + SieveCapability::Index => "index", + SieveCapability::Duplicate => "duplicate", + SieveCapability::Variables => "variables", + SieveCapability::Editheader => "editheader", + SieveCapability::Foreverypart => "foreverypart", + SieveCapability::Mime => "mime", + SieveCapability::Replace => "replace", + SieveCapability::Enclose => "enclose", + SieveCapability::Extracttext => "extracttext", + SieveCapability::Enotify => "enotify", + SieveCapability::RedirectDsn => "redirect-dsn", + SieveCapability::RedirectDeliverby => "redirect-deliverby", + SieveCapability::Environment => "environment", + SieveCapability::Reject => "reject", + SieveCapability::Ereject => "ereject", + SieveCapability::Extlists => "extlists", + SieveCapability::Subaddress => "subaddress", + SieveCapability::Vacation => "vacation", + SieveCapability::VacationSeconds => "vacation-seconds", + SieveCapability::Fcc => "fcc", + SieveCapability::Mailbox => "mailbox", + SieveCapability::Mailboxid => "mailboxid", + SieveCapability::Mboxmetadata => "mboxmetadata", + SieveCapability::Servermetadata => "servermetadata", + SieveCapability::SpecialUse => "special-use", + SieveCapability::Imap4flags => "imap4flags", + SieveCapability::Ihave => "ihave", + SieveCapability::Imapsieve => "imapsieve", + SieveCapability::Include => "include", + SieveCapability::Regex => "regex", + SieveCapability::Spamtest => "spamtest", + SieveCapability::Spamtestplus => "spamtestplus", + SieveCapability::Virustest => "virustest", + SieveCapability::VndStalwartWhile => "vnd.stalwart.while", + SieveCapability::VndStalwartExpressions => "vnd.stalwart.expressions", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SieveCapability::Envelope), + 1 => Some(SieveCapability::EnvelopeDsn), + 2 => Some(SieveCapability::EnvelopeDeliverby), + 3 => Some(SieveCapability::Fileinto), + 4 => Some(SieveCapability::EncodedCharacter), + 5 => Some(SieveCapability::ComparatorElbonia), + 6 => Some(SieveCapability::ComparatorIOctet), + 7 => Some(SieveCapability::ComparatorIAsciiCasemap), + 8 => Some(SieveCapability::ComparatorIAsciiNumeric), + 9 => Some(SieveCapability::Body), + 10 => Some(SieveCapability::Convert), + 11 => Some(SieveCapability::Copy), + 12 => Some(SieveCapability::Relational), + 13 => Some(SieveCapability::Date), + 14 => Some(SieveCapability::Index), + 15 => Some(SieveCapability::Duplicate), + 16 => Some(SieveCapability::Variables), + 17 => Some(SieveCapability::Editheader), + 18 => Some(SieveCapability::Foreverypart), + 19 => Some(SieveCapability::Mime), + 20 => Some(SieveCapability::Replace), + 21 => Some(SieveCapability::Enclose), + 22 => Some(SieveCapability::Extracttext), + 23 => Some(SieveCapability::Enotify), + 24 => Some(SieveCapability::RedirectDsn), + 25 => Some(SieveCapability::RedirectDeliverby), + 26 => Some(SieveCapability::Environment), + 27 => Some(SieveCapability::Reject), + 28 => Some(SieveCapability::Ereject), + 29 => Some(SieveCapability::Extlists), + 30 => Some(SieveCapability::Subaddress), + 31 => Some(SieveCapability::Vacation), + 32 => Some(SieveCapability::VacationSeconds), + 33 => Some(SieveCapability::Fcc), + 34 => Some(SieveCapability::Mailbox), + 35 => Some(SieveCapability::Mailboxid), + 36 => Some(SieveCapability::Mboxmetadata), + 37 => Some(SieveCapability::Servermetadata), + 38 => Some(SieveCapability::SpecialUse), + 39 => Some(SieveCapability::Imap4flags), + 40 => Some(SieveCapability::Ihave), + 41 => Some(SieveCapability::Imapsieve), + 42 => Some(SieveCapability::Include), + 43 => Some(SieveCapability::Regex), + 44 => Some(SieveCapability::Spamtest), + 45 => Some(SieveCapability::Spamtestplus), + 46 => Some(SieveCapability::Virustest), + 47 => Some(SieveCapability::VndStalwartWhile), + 48 => Some(SieveCapability::VndStalwartExpressions), + _ => None, + } + } + + const COUNT: usize = 49; +} + +impl serde::Serialize for SieveCapability { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SieveCapability { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for Sig0Algorithm { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"ecdsa-p256-sha256" => Sig0Algorithm::EcdsaP256Sha256, + b"ecdsa-p384-sha384" => Sig0Algorithm::EcdsaP384Sha384, + b"ed25519" => Sig0Algorithm::Ed25519, + } + } + + fn as_str(&self) -> &'static str { + match self { + Sig0Algorithm::EcdsaP256Sha256 => "ecdsa-p256-sha256", + Sig0Algorithm::EcdsaP384Sha384 => "ecdsa-p384-sha384", + Sig0Algorithm::Ed25519 => "ed25519", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(Sig0Algorithm::EcdsaP256Sha256), + 1 => Some(Sig0Algorithm::EcdsaP384Sha384), + 2 => Some(Sig0Algorithm::Ed25519), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for Sig0Algorithm { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for Sig0Algorithm { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamClassifierModelType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"FtrlFh" => SpamClassifierModelType::FtrlFh, + b"FtrlCcfh" => SpamClassifierModelType::FtrlCcfh, + b"Disabled" => SpamClassifierModelType::Disabled, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamClassifierModelType::FtrlFh => "FtrlFh", + SpamClassifierModelType::FtrlCcfh => "FtrlCcfh", + SpamClassifierModelType::Disabled => "Disabled", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamClassifierModelType::FtrlFh), + 1 => Some(SpamClassifierModelType::FtrlCcfh), + 2 => Some(SpamClassifierModelType::Disabled), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SpamClassifierModelType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamClassifierModelType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamClassifyParameters { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"bit7" => SpamClassifyParameters::Bit7, + b"bit8Mime - 8-bit MIME message content" => SpamClassifyParameters::Bit8Mime8BitMIMEMessageContent, + b"binaryMime" => SpamClassifyParameters::BinaryMime, + b"smtpUtf8" => SpamClassifyParameters::SmtpUtf8, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamClassifyParameters::Bit7 => "bit7", + SpamClassifyParameters::Bit8Mime8BitMIMEMessageContent => { + "bit8Mime - 8-bit MIME message content" + } + SpamClassifyParameters::BinaryMime => "binaryMime", + SpamClassifyParameters::SmtpUtf8 => "smtpUtf8", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamClassifyParameters::Bit7), + 1 => Some(SpamClassifyParameters::Bit8Mime8BitMIMEMessageContent), + 2 => Some(SpamClassifyParameters::BinaryMime), + 3 => Some(SpamClassifyParameters::SmtpUtf8), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for SpamClassifyParameters { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamClassifyParameters { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamClassifyResult { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"spam" => SpamClassifyResult::Spam, + b"ham" => SpamClassifyResult::Ham, + b"reject" => SpamClassifyResult::Reject, + b"discard" => SpamClassifyResult::Discard, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamClassifyResult::Spam => "spam", + SpamClassifyResult::Ham => "ham", + SpamClassifyResult::Reject => "reject", + SpamClassifyResult::Discard => "discard", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamClassifyResult::Spam), + 1 => Some(SpamClassifyResult::Ham), + 2 => Some(SpamClassifyResult::Reject), + 3 => Some(SpamClassifyResult::Discard), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for SpamClassifyResult { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamClassifyResult { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamClassifyTagDisposition { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"score" => SpamClassifyTagDisposition::Score, + b"reject" => SpamClassifyTagDisposition::Reject, + b"discard" => SpamClassifyTagDisposition::Discard, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamClassifyTagDisposition::Score => "score", + SpamClassifyTagDisposition::Reject => "reject", + SpamClassifyTagDisposition::Discard => "discard", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamClassifyTagDisposition::Score), + 1 => Some(SpamClassifyTagDisposition::Reject), + 2 => Some(SpamClassifyTagDisposition::Discard), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SpamClassifyTagDisposition { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamClassifyTagDisposition { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamDnsblServerType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Any" => SpamDnsblServerType::Any, + b"Url" => SpamDnsblServerType::Url, + b"Domain" => SpamDnsblServerType::Domain, + b"Email" => SpamDnsblServerType::Email, + b"Ip" => SpamDnsblServerType::Ip, + b"Header" => SpamDnsblServerType::Header, + b"Body" => SpamDnsblServerType::Body, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamDnsblServerType::Any => "Any", + SpamDnsblServerType::Url => "Url", + SpamDnsblServerType::Domain => "Domain", + SpamDnsblServerType::Email => "Email", + SpamDnsblServerType::Ip => "Ip", + SpamDnsblServerType::Header => "Header", + SpamDnsblServerType::Body => "Body", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamDnsblServerType::Any), + 1 => Some(SpamDnsblServerType::Url), + 2 => Some(SpamDnsblServerType::Domain), + 3 => Some(SpamDnsblServerType::Email), + 4 => Some(SpamDnsblServerType::Ip), + 5 => Some(SpamDnsblServerType::Header), + 6 => Some(SpamDnsblServerType::Body), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for SpamDnsblServerType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamDnsblServerType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamLlmType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disable" => SpamLlmType::Disable, + b"Enable" => SpamLlmType::Enable, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamLlmType::Disable => "Disable", + SpamLlmType::Enable => "Enable", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamLlmType::Disable), + 1 => Some(SpamLlmType::Enable), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for SpamLlmType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamLlmType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamRuleType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Any" => SpamRuleType::Any, + b"Url" => SpamRuleType::Url, + b"Domain" => SpamRuleType::Domain, + b"Email" => SpamRuleType::Email, + b"Ip" => SpamRuleType::Ip, + b"Header" => SpamRuleType::Header, + b"Body" => SpamRuleType::Body, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamRuleType::Any => "Any", + SpamRuleType::Url => "Url", + SpamRuleType::Domain => "Domain", + SpamRuleType::Email => "Email", + SpamRuleType::Ip => "Ip", + SpamRuleType::Header => "Header", + SpamRuleType::Body => "Body", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamRuleType::Any), + 1 => Some(SpamRuleType::Url), + 2 => Some(SpamRuleType::Domain), + 3 => Some(SpamRuleType::Email), + 4 => Some(SpamRuleType::Ip), + 5 => Some(SpamRuleType::Header), + 6 => Some(SpamRuleType::Body), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for SpamRuleType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamRuleType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpamTagType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Score" => SpamTagType::Score, + b"Discard" => SpamTagType::Discard, + b"Reject" => SpamTagType::Reject, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpamTagType::Score => "Score", + SpamTagType::Discard => "Discard", + SpamTagType::Reject => "Reject", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpamTagType::Score), + 1 => Some(SpamTagType::Discard), + 2 => Some(SpamTagType::Reject), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SpamTagType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpamTagType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpecialUse { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"inbox" => SpecialUse::Inbox, + b"trash" => SpecialUse::Trash, + b"junk" => SpecialUse::Junk, + b"drafts" => SpecialUse::Drafts, + b"archive" => SpecialUse::Archive, + b"sent" => SpecialUse::Sent, + b"shared" => SpecialUse::Shared, + b"important" => SpecialUse::Important, + b"memos" => SpecialUse::Memos, + b"scheduled" => SpecialUse::Scheduled, + b"snoozed" => SpecialUse::Snoozed, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpecialUse::Inbox => "inbox", + SpecialUse::Trash => "trash", + SpecialUse::Junk => "junk", + SpecialUse::Drafts => "drafts", + SpecialUse::Archive => "archive", + SpecialUse::Sent => "sent", + SpecialUse::Shared => "shared", + SpecialUse::Important => "important", + SpecialUse::Memos => "memos", + SpecialUse::Scheduled => "scheduled", + SpecialUse::Snoozed => "snoozed", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpecialUse::Inbox), + 1 => Some(SpecialUse::Trash), + 2 => Some(SpecialUse::Junk), + 3 => Some(SpecialUse::Drafts), + 4 => Some(SpecialUse::Archive), + 5 => Some(SpecialUse::Sent), + 6 => Some(SpecialUse::Shared), + 7 => Some(SpecialUse::Important), + 8 => Some(SpecialUse::Memos), + 9 => Some(SpecialUse::Scheduled), + 10 => Some(SpecialUse::Snoozed), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for SpecialUse { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpecialUse { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpfAuthResult { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"none" => SpfAuthResult::None, + b"neutral" => SpfAuthResult::Neutral, + b"pass" => SpfAuthResult::Pass, + b"fail" => SpfAuthResult::Fail, + b"softFail" => SpfAuthResult::SoftFail, + b"tempError" => SpfAuthResult::TempError, + b"permError" => SpfAuthResult::PermError, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpfAuthResult::None => "none", + SpfAuthResult::Neutral => "neutral", + SpfAuthResult::Pass => "pass", + SpfAuthResult::Fail => "fail", + SpfAuthResult::SoftFail => "softFail", + SpfAuthResult::TempError => "tempError", + SpfAuthResult::PermError => "permError", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpfAuthResult::None), + 1 => Some(SpfAuthResult::Neutral), + 2 => Some(SpfAuthResult::Pass), + 3 => Some(SpfAuthResult::Fail), + 4 => Some(SpfAuthResult::SoftFail), + 5 => Some(SpfAuthResult::TempError), + 6 => Some(SpfAuthResult::PermError), + _ => None, + } + } + + const COUNT: usize = 7; +} + +impl serde::Serialize for SpfAuthResult { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpfAuthResult { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SpfDomainScope { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"helo" => SpfDomainScope::Helo, + b"mailFrom" => SpfDomainScope::MailFrom, + b"unspecified" => SpfDomainScope::Unspecified, + } + } + + fn as_str(&self) -> &'static str { + match self { + SpfDomainScope::Helo => "helo", + SpfDomainScope::MailFrom => "mailFrom", + SpfDomainScope::Unspecified => "unspecified", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SpfDomainScope::Helo), + 1 => Some(SpfDomainScope::MailFrom), + 2 => Some(SpfDomainScope::Unspecified), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SpfDomainScope { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SpfDomainScope { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SqlAuthStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Default" => SqlAuthStoreType::Default, + b"PostgreSql" => SqlAuthStoreType::PostgreSql, + b"MySql" => SqlAuthStoreType::MySql, + b"Sqlite" => SqlAuthStoreType::Sqlite, + } + } + + fn as_str(&self) -> &'static str { + match self { + SqlAuthStoreType::Default => "Default", + SqlAuthStoreType::PostgreSql => "PostgreSql", + SqlAuthStoreType::MySql => "MySql", + SqlAuthStoreType::Sqlite => "Sqlite", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SqlAuthStoreType::Default), + 1 => Some(SqlAuthStoreType::PostgreSql), + 2 => Some(SqlAuthStoreType::MySql), + 3 => Some(SqlAuthStoreType::Sqlite), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for SqlAuthStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SqlAuthStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for StorageQuota { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"maxEmails" => StorageQuota::MaxEmails, + b"maxMailboxes" => StorageQuota::MaxMailboxes, + b"maxEmailSubmissions" => StorageQuota::MaxEmailSubmissions, + b"maxEmailIdentities" => StorageQuota::MaxEmailIdentities, + b"maxParticipantIdentities" => StorageQuota::MaxParticipantIdentities, + b"maxSieveScripts" => StorageQuota::MaxSieveScripts, + b"maxPushSubscriptions" => StorageQuota::MaxPushSubscriptions, + b"maxCalendars" => StorageQuota::MaxCalendars, + b"maxCalendarEvents" => StorageQuota::MaxCalendarEvents, + b"maxCalendarEventNotifications" => StorageQuota::MaxCalendarEventNotifications, + b"maxAddressBooks" => StorageQuota::MaxAddressBooks, + b"maxContactCards" => StorageQuota::MaxContactCards, + b"maxFiles" => StorageQuota::MaxFiles, + b"maxFolders" => StorageQuota::MaxFolders, + b"maxMaskedAddresses" => StorageQuota::MaxMaskedAddresses, + b"maxAppPasswords" => StorageQuota::MaxAppPasswords, + b"maxApiKeys" => StorageQuota::MaxApiKeys, + b"maxPublicKeys" => StorageQuota::MaxPublicKeys, + b"maxDiskQuota" => StorageQuota::MaxDiskQuota, + } + } + + fn as_str(&self) -> &'static str { + match self { + StorageQuota::MaxEmails => "maxEmails", + StorageQuota::MaxMailboxes => "maxMailboxes", + StorageQuota::MaxEmailSubmissions => "maxEmailSubmissions", + StorageQuota::MaxEmailIdentities => "maxEmailIdentities", + StorageQuota::MaxParticipantIdentities => "maxParticipantIdentities", + StorageQuota::MaxSieveScripts => "maxSieveScripts", + StorageQuota::MaxPushSubscriptions => "maxPushSubscriptions", + StorageQuota::MaxCalendars => "maxCalendars", + StorageQuota::MaxCalendarEvents => "maxCalendarEvents", + StorageQuota::MaxCalendarEventNotifications => "maxCalendarEventNotifications", + StorageQuota::MaxAddressBooks => "maxAddressBooks", + StorageQuota::MaxContactCards => "maxContactCards", + StorageQuota::MaxFiles => "maxFiles", + StorageQuota::MaxFolders => "maxFolders", + StorageQuota::MaxMaskedAddresses => "maxMaskedAddresses", + StorageQuota::MaxAppPasswords => "maxAppPasswords", + StorageQuota::MaxApiKeys => "maxApiKeys", + StorageQuota::MaxPublicKeys => "maxPublicKeys", + StorageQuota::MaxDiskQuota => "maxDiskQuota", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(StorageQuota::MaxEmails), + 1 => Some(StorageQuota::MaxMailboxes), + 2 => Some(StorageQuota::MaxEmailSubmissions), + 3 => Some(StorageQuota::MaxEmailIdentities), + 4 => Some(StorageQuota::MaxParticipantIdentities), + 5 => Some(StorageQuota::MaxSieveScripts), + 6 => Some(StorageQuota::MaxPushSubscriptions), + 7 => Some(StorageQuota::MaxCalendars), + 8 => Some(StorageQuota::MaxCalendarEvents), + 9 => Some(StorageQuota::MaxCalendarEventNotifications), + 10 => Some(StorageQuota::MaxAddressBooks), + 11 => Some(StorageQuota::MaxContactCards), + 12 => Some(StorageQuota::MaxFiles), + 13 => Some(StorageQuota::MaxFolders), + 14 => Some(StorageQuota::MaxMaskedAddresses), + 15 => Some(StorageQuota::MaxAppPasswords), + 16 => Some(StorageQuota::MaxApiKeys), + 17 => Some(StorageQuota::MaxPublicKeys), + 18 => Some(StorageQuota::MaxDiskQuota), + _ => None, + } + } + + const COUNT: usize = 19; +} + +impl serde::Serialize for StorageQuota { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for StorageQuota { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for SubAddressingType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Enabled" => SubAddressingType::Enabled, + b"Custom" => SubAddressingType::Custom, + b"Disabled" => SubAddressingType::Disabled, + } + } + + fn as_str(&self) -> &'static str { + match self { + SubAddressingType::Enabled => "Enabled", + SubAddressingType::Custom => "Custom", + SubAddressingType::Disabled => "Disabled", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(SubAddressingType::Enabled), + 1 => Some(SubAddressingType::Custom), + 2 => Some(SubAddressingType::Disabled), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for SubAddressingType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for SubAddressingType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskAccountMaintenanceType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"purge" => TaskAccountMaintenanceType::Purge, + b"reindex" => TaskAccountMaintenanceType::Reindex, + b"recalculateImapUid" => TaskAccountMaintenanceType::RecalculateImapUid, + b"recalculateQuota" => TaskAccountMaintenanceType::RecalculateQuota, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskAccountMaintenanceType::Purge => "purge", + TaskAccountMaintenanceType::Reindex => "reindex", + TaskAccountMaintenanceType::RecalculateImapUid => "recalculateImapUid", + TaskAccountMaintenanceType::RecalculateQuota => "recalculateQuota", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskAccountMaintenanceType::Purge), + 1 => Some(TaskAccountMaintenanceType::Reindex), + 2 => Some(TaskAccountMaintenanceType::RecalculateImapUid), + 3 => Some(TaskAccountMaintenanceType::RecalculateQuota), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for TaskAccountMaintenanceType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskAccountMaintenanceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskRetryStrategyType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"ExponentialBackoff" => TaskRetryStrategyType::ExponentialBackoff, + b"FixedDelay" => TaskRetryStrategyType::FixedDelay, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskRetryStrategyType::ExponentialBackoff => "ExponentialBackoff", + TaskRetryStrategyType::FixedDelay => "FixedDelay", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskRetryStrategyType::ExponentialBackoff), + 1 => Some(TaskRetryStrategyType::FixedDelay), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for TaskRetryStrategyType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskRetryStrategyType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskSpamFilterMaintenanceType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"train" => TaskSpamFilterMaintenanceType::Train, + b"retrain" => TaskSpamFilterMaintenanceType::Retrain, + b"abort" => TaskSpamFilterMaintenanceType::Abort, + b"reset" => TaskSpamFilterMaintenanceType::Reset, + b"updateRules" => TaskSpamFilterMaintenanceType::UpdateRules, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskSpamFilterMaintenanceType::Train => "train", + TaskSpamFilterMaintenanceType::Retrain => "retrain", + TaskSpamFilterMaintenanceType::Abort => "abort", + TaskSpamFilterMaintenanceType::Reset => "reset", + TaskSpamFilterMaintenanceType::UpdateRules => "updateRules", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskSpamFilterMaintenanceType::Train), + 1 => Some(TaskSpamFilterMaintenanceType::Retrain), + 2 => Some(TaskSpamFilterMaintenanceType::Abort), + 3 => Some(TaskSpamFilterMaintenanceType::Reset), + 4 => Some(TaskSpamFilterMaintenanceType::UpdateRules), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for TaskSpamFilterMaintenanceType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskSpamFilterMaintenanceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskStatusType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Pending" => TaskStatusType::Pending, + b"Retry" => TaskStatusType::Retry, + b"Failed" => TaskStatusType::Failed, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskStatusType::Pending => "Pending", + TaskStatusType::Retry => "Retry", + TaskStatusType::Failed => "Failed", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskStatusType::Pending), + 1 => Some(TaskStatusType::Retry), + 2 => Some(TaskStatusType::Failed), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for TaskStatusType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskStatusType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskStoreMaintenanceType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"reindexAccounts" => TaskStoreMaintenanceType::ReindexAccounts, + b"reindexTelemetry" => TaskStoreMaintenanceType::ReindexTelemetry, + b"purgeAccounts" => TaskStoreMaintenanceType::PurgeAccounts, + b"purgeData" => TaskStoreMaintenanceType::PurgeData, + b"purgeBlob" => TaskStoreMaintenanceType::PurgeBlob, + b"resetRateLimiters" => TaskStoreMaintenanceType::ResetRateLimiters, + b"resetUserQuotas" => TaskStoreMaintenanceType::ResetUserQuotas, + b"resetTenantQuotas" => TaskStoreMaintenanceType::ResetTenantQuotas, + b"resetBlobQuotas" => TaskStoreMaintenanceType::ResetBlobQuotas, + b"removeAuthTokens" => TaskStoreMaintenanceType::RemoveAuthTokens, + b"removeLockQueueMessage" => TaskStoreMaintenanceType::RemoveLockQueueMessage, + b"removeLockTask" => TaskStoreMaintenanceType::RemoveLockTask, + b"removeLockDav" => TaskStoreMaintenanceType::RemoveLockDav, + b"removeSieveId" => TaskStoreMaintenanceType::RemoveSieveId, + b"removeGreylist" => TaskStoreMaintenanceType::RemoveGreylist, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskStoreMaintenanceType::ReindexAccounts => "reindexAccounts", + TaskStoreMaintenanceType::ReindexTelemetry => "reindexTelemetry", + TaskStoreMaintenanceType::PurgeAccounts => "purgeAccounts", + TaskStoreMaintenanceType::PurgeData => "purgeData", + TaskStoreMaintenanceType::PurgeBlob => "purgeBlob", + TaskStoreMaintenanceType::ResetRateLimiters => "resetRateLimiters", + TaskStoreMaintenanceType::ResetUserQuotas => "resetUserQuotas", + TaskStoreMaintenanceType::ResetTenantQuotas => "resetTenantQuotas", + TaskStoreMaintenanceType::ResetBlobQuotas => "resetBlobQuotas", + TaskStoreMaintenanceType::RemoveAuthTokens => "removeAuthTokens", + TaskStoreMaintenanceType::RemoveLockQueueMessage => "removeLockQueueMessage", + TaskStoreMaintenanceType::RemoveLockTask => "removeLockTask", + TaskStoreMaintenanceType::RemoveLockDav => "removeLockDav", + TaskStoreMaintenanceType::RemoveSieveId => "removeSieveId", + TaskStoreMaintenanceType::RemoveGreylist => "removeGreylist", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskStoreMaintenanceType::ReindexAccounts), + 1 => Some(TaskStoreMaintenanceType::ReindexTelemetry), + 2 => Some(TaskStoreMaintenanceType::PurgeAccounts), + 3 => Some(TaskStoreMaintenanceType::PurgeData), + 4 => Some(TaskStoreMaintenanceType::PurgeBlob), + 5 => Some(TaskStoreMaintenanceType::ResetRateLimiters), + 6 => Some(TaskStoreMaintenanceType::ResetUserQuotas), + 7 => Some(TaskStoreMaintenanceType::ResetTenantQuotas), + 8 => Some(TaskStoreMaintenanceType::ResetBlobQuotas), + 9 => Some(TaskStoreMaintenanceType::RemoveAuthTokens), + 10 => Some(TaskStoreMaintenanceType::RemoveLockQueueMessage), + 11 => Some(TaskStoreMaintenanceType::RemoveLockTask), + 12 => Some(TaskStoreMaintenanceType::RemoveLockDav), + 13 => Some(TaskStoreMaintenanceType::RemoveSieveId), + 14 => Some(TaskStoreMaintenanceType::RemoveGreylist), + _ => None, + } + } + + const COUNT: usize = 15; +} + +impl serde::Serialize for TaskStoreMaintenanceType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskStoreMaintenanceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskTenantMaintenanceType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"recalculateQuota" => TaskTenantMaintenanceType::RecalculateQuota, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskTenantMaintenanceType::RecalculateQuota => "recalculateQuota", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskTenantMaintenanceType::RecalculateQuota), + _ => None, + } + } + + const COUNT: usize = 1; +} + +impl serde::Serialize for TaskTenantMaintenanceType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskTenantMaintenanceType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TaskType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"IndexDocument" => TaskType::IndexDocument, + b"UnindexDocument" => TaskType::UnindexDocument, + b"IndexTrace" => TaskType::IndexTrace, + b"CalendarAlarmEmail" => TaskType::CalendarAlarmEmail, + b"CalendarAlarmNotification" => TaskType::CalendarAlarmNotification, + b"CalendarItipMessage" => TaskType::CalendarItipMessage, + b"MergeThreads" => TaskType::MergeThreads, + b"DmarcReport" => TaskType::DmarcReport, + b"TlsReport" => TaskType::TlsReport, + b"RestoreArchivedItem" => TaskType::RestoreArchivedItem, + b"DestroyAccount" => TaskType::DestroyAccount, + b"AccountMaintenance" => TaskType::AccountMaintenance, + b"TenantMaintenance" => TaskType::TenantMaintenance, + b"StoreMaintenance" => TaskType::StoreMaintenance, + b"SpamFilterMaintenance" => TaskType::SpamFilterMaintenance, + b"AcmeRenewal" => TaskType::AcmeRenewal, + b"DkimManagement" => TaskType::DkimManagement, + b"DnsManagement" => TaskType::DnsManagement, + } + } + + fn as_str(&self) -> &'static str { + match self { + TaskType::IndexDocument => "IndexDocument", + TaskType::UnindexDocument => "UnindexDocument", + TaskType::IndexTrace => "IndexTrace", + TaskType::CalendarAlarmEmail => "CalendarAlarmEmail", + TaskType::CalendarAlarmNotification => "CalendarAlarmNotification", + TaskType::CalendarItipMessage => "CalendarItipMessage", + TaskType::MergeThreads => "MergeThreads", + TaskType::DmarcReport => "DmarcReport", + TaskType::TlsReport => "TlsReport", + TaskType::RestoreArchivedItem => "RestoreArchivedItem", + TaskType::DestroyAccount => "DestroyAccount", + TaskType::AccountMaintenance => "AccountMaintenance", + TaskType::TenantMaintenance => "TenantMaintenance", + TaskType::StoreMaintenance => "StoreMaintenance", + TaskType::SpamFilterMaintenance => "SpamFilterMaintenance", + TaskType::AcmeRenewal => "AcmeRenewal", + TaskType::DkimManagement => "DkimManagement", + TaskType::DnsManagement => "DnsManagement", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TaskType::IndexDocument), + 1 => Some(TaskType::UnindexDocument), + 2 => Some(TaskType::IndexTrace), + 3 => Some(TaskType::CalendarAlarmEmail), + 4 => Some(TaskType::CalendarAlarmNotification), + 5 => Some(TaskType::CalendarItipMessage), + 6 => Some(TaskType::MergeThreads), + 7 => Some(TaskType::DmarcReport), + 8 => Some(TaskType::TlsReport), + 9 => Some(TaskType::RestoreArchivedItem), + 10 => Some(TaskType::DestroyAccount), + 11 => Some(TaskType::AccountMaintenance), + 12 => Some(TaskType::TenantMaintenance), + 13 => Some(TaskType::StoreMaintenance), + 14 => Some(TaskType::SpamFilterMaintenance), + 15 => Some(TaskType::AcmeRenewal), + 16 => Some(TaskType::DkimManagement), + 17 => Some(TaskType::DnsManagement), + _ => None, + } + } + + const COUNT: usize = 18; +} + +impl serde::Serialize for TaskType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TaskType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TenantStorageQuota { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"maxAccounts" => TenantStorageQuota::MaxAccounts, + b"maxGroups" => TenantStorageQuota::MaxGroups, + b"maxDomains" => TenantStorageQuota::MaxDomains, + b"maxMailingLists" => TenantStorageQuota::MaxMailingLists, + b"maxRoles" => TenantStorageQuota::MaxRoles, + b"maxOauthClients" => TenantStorageQuota::MaxOauthClients, + b"maxDkimKeys" => TenantStorageQuota::MaxDkimKeys, + b"maxDnsServers" => TenantStorageQuota::MaxDnsServers, + b"maxDirectories" => TenantStorageQuota::MaxDirectories, + b"maxAcmeProviders" => TenantStorageQuota::MaxAcmeProviders, + b"maxDiskQuota" => TenantStorageQuota::MaxDiskQuota, + } + } + + fn as_str(&self) -> &'static str { + match self { + TenantStorageQuota::MaxAccounts => "maxAccounts", + TenantStorageQuota::MaxGroups => "maxGroups", + TenantStorageQuota::MaxDomains => "maxDomains", + TenantStorageQuota::MaxMailingLists => "maxMailingLists", + TenantStorageQuota::MaxRoles => "maxRoles", + TenantStorageQuota::MaxOauthClients => "maxOauthClients", + TenantStorageQuota::MaxDkimKeys => "maxDkimKeys", + TenantStorageQuota::MaxDnsServers => "maxDnsServers", + TenantStorageQuota::MaxDirectories => "maxDirectories", + TenantStorageQuota::MaxAcmeProviders => "maxAcmeProviders", + TenantStorageQuota::MaxDiskQuota => "maxDiskQuota", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TenantStorageQuota::MaxAccounts), + 1 => Some(TenantStorageQuota::MaxGroups), + 2 => Some(TenantStorageQuota::MaxDomains), + 3 => Some(TenantStorageQuota::MaxMailingLists), + 4 => Some(TenantStorageQuota::MaxRoles), + 5 => Some(TenantStorageQuota::MaxOauthClients), + 6 => Some(TenantStorageQuota::MaxDkimKeys), + 7 => Some(TenantStorageQuota::MaxDnsServers), + 8 => Some(TenantStorageQuota::MaxDirectories), + 9 => Some(TenantStorageQuota::MaxAcmeProviders), + 10 => Some(TenantStorageQuota::MaxDiskQuota), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for TenantStorageQuota { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TenantStorageQuota { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TimeZone { + fn parse(value: &str) -> Option { + hashify::map! { + value.as_bytes(), + TimeZone, + b"Africa/Abidjan" => TimeZone::AfricaAbidjan, + b"Africa/Accra" => TimeZone::AfricaAccra, + b"Africa/Addis_Ababa" => TimeZone::AfricaAddisAbaba, + b"Africa/Algiers" => TimeZone::AfricaAlgiers, + b"Africa/Asmara" => TimeZone::AfricaAsmara, + b"Africa/Asmera" => TimeZone::AfricaAsmera, + b"Africa/Bamako" => TimeZone::AfricaBamako, + b"Africa/Bangui" => TimeZone::AfricaBangui, + b"Africa/Banjul" => TimeZone::AfricaBanjul, + b"Africa/Bissau" => TimeZone::AfricaBissau, + b"Africa/Blantyre" => TimeZone::AfricaBlantyre, + b"Africa/Brazzaville" => TimeZone::AfricaBrazzaville, + b"Africa/Bujumbura" => TimeZone::AfricaBujumbura, + b"Africa/Cairo" => TimeZone::AfricaCairo, + b"Africa/Casablanca" => TimeZone::AfricaCasablanca, + b"Africa/Ceuta" => TimeZone::AfricaCeuta, + b"Africa/Conakry" => TimeZone::AfricaConakry, + b"Africa/Dakar" => TimeZone::AfricaDakar, + b"Africa/Dar_es_Salaam" => TimeZone::AfricaDarEsSalaam, + b"Africa/Djibouti" => TimeZone::AfricaDjibouti, + b"Africa/Douala" => TimeZone::AfricaDouala, + b"Africa/El_Aaiun" => TimeZone::AfricaElAaiun, + b"Africa/Freetown" => TimeZone::AfricaFreetown, + b"Africa/Gaborone" => TimeZone::AfricaGaborone, + b"Africa/Harare" => TimeZone::AfricaHarare, + b"Africa/Johannesburg" => TimeZone::AfricaJohannesburg, + b"Africa/Juba" => TimeZone::AfricaJuba, + b"Africa/Kampala" => TimeZone::AfricaKampala, + b"Africa/Khartoum" => TimeZone::AfricaKhartoum, + b"Africa/Kigali" => TimeZone::AfricaKigali, + b"Africa/Kinshasa" => TimeZone::AfricaKinshasa, + b"Africa/Lagos" => TimeZone::AfricaLagos, + b"Africa/Libreville" => TimeZone::AfricaLibreville, + b"Africa/Lome" => TimeZone::AfricaLome, + b"Africa/Luanda" => TimeZone::AfricaLuanda, + b"Africa/Lubumbashi" => TimeZone::AfricaLubumbashi, + b"Africa/Lusaka" => TimeZone::AfricaLusaka, + b"Africa/Malabo" => TimeZone::AfricaMalabo, + b"Africa/Maputo" => TimeZone::AfricaMaputo, + b"Africa/Maseru" => TimeZone::AfricaMaseru, + b"Africa/Mbabane" => TimeZone::AfricaMbabane, + b"Africa/Mogadishu" => TimeZone::AfricaMogadishu, + b"Africa/Monrovia" => TimeZone::AfricaMonrovia, + b"Africa/Nairobi" => TimeZone::AfricaNairobi, + b"Africa/Ndjamena" => TimeZone::AfricaNdjamena, + b"Africa/Niamey" => TimeZone::AfricaNiamey, + b"Africa/Nouakchott" => TimeZone::AfricaNouakchott, + b"Africa/Ouagadougou" => TimeZone::AfricaOuagadougou, + b"Africa/Porto-Novo" => TimeZone::AfricaPortoNovo, + b"Africa/Sao_Tome" => TimeZone::AfricaSaoTome, + b"Africa/Timbuktu" => TimeZone::AfricaTimbuktu, + b"Africa/Tripoli" => TimeZone::AfricaTripoli, + b"Africa/Tunis" => TimeZone::AfricaTunis, + b"Africa/Windhoek" => TimeZone::AfricaWindhoek, + b"America/Adak" => TimeZone::AmericaAdak, + b"America/Anchorage" => TimeZone::AmericaAnchorage, + b"America/Anguilla" => TimeZone::AmericaAnguilla, + b"America/Antigua" => TimeZone::AmericaAntigua, + b"America/Araguaina" => TimeZone::AmericaAraguaina, + b"America/Argentina/Buenos_Aires" => TimeZone::AmericaArgentinaBuenosAires, + b"America/Argentina/Catamarca" => TimeZone::AmericaArgentinaCatamarca, + b"America/Argentina/ComodRivadavia" => TimeZone::AmericaArgentinaComodRivadavia, + b"America/Argentina/Cordoba" => TimeZone::AmericaArgentinaCordoba, + b"America/Argentina/Jujuy" => TimeZone::AmericaArgentinaJujuy, + b"America/Argentina/La_Rioja" => TimeZone::AmericaArgentinaLaRioja, + b"America/Argentina/Mendoza" => TimeZone::AmericaArgentinaMendoza, + b"America/Argentina/Rio_Gallegos" => TimeZone::AmericaArgentinaRioGallegos, + b"America/Argentina/Salta" => TimeZone::AmericaArgentinaSalta, + b"America/Argentina/San_Juan" => TimeZone::AmericaArgentinaSanJuan, + b"America/Argentina/San_Luis" => TimeZone::AmericaArgentinaSanLuis, + b"America/Argentina/Tucuman" => TimeZone::AmericaArgentinaTucuman, + b"America/Argentina/Ushuaia" => TimeZone::AmericaArgentinaUshuaia, + b"America/Aruba" => TimeZone::AmericaAruba, + b"America/Asuncion" => TimeZone::AmericaAsuncion, + b"America/Atikokan" => TimeZone::AmericaAtikokan, + b"America/Atka" => TimeZone::AmericaAtka, + b"America/Bahia" => TimeZone::AmericaBahia, + b"America/Bahia_Banderas" => TimeZone::AmericaBahiaBanderas, + b"America/Barbados" => TimeZone::AmericaBarbados, + b"America/Belem" => TimeZone::AmericaBelem, + b"America/Belize" => TimeZone::AmericaBelize, + b"America/Blanc-Sablon" => TimeZone::AmericaBlancSablon, + b"America/Boa_Vista" => TimeZone::AmericaBoaVista, + b"America/Bogota" => TimeZone::AmericaBogota, + b"America/Boise" => TimeZone::AmericaBoise, + b"America/Buenos_Aires" => TimeZone::AmericaBuenosAires, + b"America/Cambridge_Bay" => TimeZone::AmericaCambridgeBay, + b"America/Campo_Grande" => TimeZone::AmericaCampoGrande, + b"America/Cancun" => TimeZone::AmericaCancun, + b"America/Caracas" => TimeZone::AmericaCaracas, + b"America/Catamarca" => TimeZone::AmericaCatamarca, + b"America/Cayenne" => TimeZone::AmericaCayenne, + b"America/Cayman" => TimeZone::AmericaCayman, + b"America/Chicago" => TimeZone::AmericaChicago, + b"America/Chihuahua" => TimeZone::AmericaChihuahua, + b"America/Ciudad_Juarez" => TimeZone::AmericaCiudadJuarez, + b"America/Coral_Harbour" => TimeZone::AmericaCoralHarbour, + b"America/Cordoba" => TimeZone::AmericaCordoba, + b"America/Costa_Rica" => TimeZone::AmericaCostaRica, + b"America/Coyhaique" => TimeZone::AmericaCoyhaique, + b"America/Creston" => TimeZone::AmericaCreston, + b"America/Cuiaba" => TimeZone::AmericaCuiaba, + b"America/Curacao" => TimeZone::AmericaCuracao, + b"America/Danmarkshavn" => TimeZone::AmericaDanmarkshavn, + b"America/Dawson" => TimeZone::AmericaDawson, + b"America/Dawson_Creek" => TimeZone::AmericaDawsonCreek, + b"America/Denver" => TimeZone::AmericaDenver, + b"America/Detroit" => TimeZone::AmericaDetroit, + b"America/Dominica" => TimeZone::AmericaDominica, + b"America/Edmonton" => TimeZone::AmericaEdmonton, + b"America/Eirunepe" => TimeZone::AmericaEirunepe, + b"America/El_Salvador" => TimeZone::AmericaElSalvador, + b"America/Ensenada" => TimeZone::AmericaEnsenada, + b"America/Fort_Nelson" => TimeZone::AmericaFortNelson, + b"America/Fort_Wayne" => TimeZone::AmericaFortWayne, + b"America/Fortaleza" => TimeZone::AmericaFortaleza, + b"America/Glace_Bay" => TimeZone::AmericaGlaceBay, + b"America/Godthab" => TimeZone::AmericaGodthab, + b"America/Goose_Bay" => TimeZone::AmericaGooseBay, + b"America/Grand_Turk" => TimeZone::AmericaGrandTurk, + b"America/Grenada" => TimeZone::AmericaGrenada, + b"America/Guadeloupe" => TimeZone::AmericaGuadeloupe, + b"America/Guatemala" => TimeZone::AmericaGuatemala, + b"America/Guayaquil" => TimeZone::AmericaGuayaquil, + b"America/Guyana" => TimeZone::AmericaGuyana, + b"America/Halifax" => TimeZone::AmericaHalifax, + b"America/Havana" => TimeZone::AmericaHavana, + b"America/Hermosillo" => TimeZone::AmericaHermosillo, + b"America/Indiana/Indianapolis" => TimeZone::AmericaIndianaIndianapolis, + b"America/Indiana/Knox" => TimeZone::AmericaIndianaKnox, + b"America/Indiana/Marengo" => TimeZone::AmericaIndianaMarengo, + b"America/Indiana/Petersburg" => TimeZone::AmericaIndianaPetersburg, + b"America/Indiana/Tell_City" => TimeZone::AmericaIndianaTellCity, + b"America/Indiana/Vevay" => TimeZone::AmericaIndianaVevay, + b"America/Indiana/Vincennes" => TimeZone::AmericaIndianaVincennes, + b"America/Indiana/Winamac" => TimeZone::AmericaIndianaWinamac, + b"America/Indianapolis" => TimeZone::AmericaIndianapolis, + b"America/Inuvik" => TimeZone::AmericaInuvik, + b"America/Iqaluit" => TimeZone::AmericaIqaluit, + b"America/Jamaica" => TimeZone::AmericaJamaica, + b"America/Jujuy" => TimeZone::AmericaJujuy, + b"America/Juneau" => TimeZone::AmericaJuneau, + b"America/Kentucky/Louisville" => TimeZone::AmericaKentuckyLouisville, + b"America/Kentucky/Monticello" => TimeZone::AmericaKentuckyMonticello, + b"America/Knox_IN" => TimeZone::AmericaKnoxIN, + b"America/Kralendijk" => TimeZone::AmericaKralendijk, + b"America/La_Paz" => TimeZone::AmericaLaPaz, + b"America/Lima" => TimeZone::AmericaLima, + b"America/Los_Angeles" => TimeZone::AmericaLosAngeles, + b"America/Louisville" => TimeZone::AmericaLouisville, + b"America/Lower_Princes" => TimeZone::AmericaLowerPrinces, + b"America/Maceio" => TimeZone::AmericaMaceio, + b"America/Managua" => TimeZone::AmericaManagua, + b"America/Manaus" => TimeZone::AmericaManaus, + b"America/Marigot" => TimeZone::AmericaMarigot, + b"America/Martinique" => TimeZone::AmericaMartinique, + b"America/Matamoros" => TimeZone::AmericaMatamoros, + b"America/Mazatlan" => TimeZone::AmericaMazatlan, + b"America/Mendoza" => TimeZone::AmericaMendoza, + b"America/Menominee" => TimeZone::AmericaMenominee, + b"America/Merida" => TimeZone::AmericaMerida, + b"America/Metlakatla" => TimeZone::AmericaMetlakatla, + b"America/Mexico_City" => TimeZone::AmericaMexicoCity, + b"America/Miquelon" => TimeZone::AmericaMiquelon, + b"America/Moncton" => TimeZone::AmericaMoncton, + b"America/Monterrey" => TimeZone::AmericaMonterrey, + b"America/Montevideo" => TimeZone::AmericaMontevideo, + b"America/Montreal" => TimeZone::AmericaMontreal, + b"America/Montserrat" => TimeZone::AmericaMontserrat, + b"America/Nassau" => TimeZone::AmericaNassau, + b"America/New_York" => TimeZone::AmericaNewYork, + b"America/Nipigon" => TimeZone::AmericaNipigon, + b"America/Nome" => TimeZone::AmericaNome, + b"America/Noronha" => TimeZone::AmericaNoronha, + b"America/North_Dakota/Beulah" => TimeZone::AmericaNorthDakotaBeulah, + b"America/North_Dakota/Center" => TimeZone::AmericaNorthDakotaCenter, + b"America/North_Dakota/New_Salem" => TimeZone::AmericaNorthDakotaNewSalem, + b"America/Nuuk" => TimeZone::AmericaNuuk, + b"America/Ojinaga" => TimeZone::AmericaOjinaga, + b"America/Panama" => TimeZone::AmericaPanama, + b"America/Pangnirtung" => TimeZone::AmericaPangnirtung, + b"America/Paramaribo" => TimeZone::AmericaParamaribo, + b"America/Phoenix" => TimeZone::AmericaPhoenix, + b"America/Port-au-Prince" => TimeZone::AmericaPortAuPrince, + b"America/Port_of_Spain" => TimeZone::AmericaPortOfSpain, + b"America/Porto_Acre" => TimeZone::AmericaPortoAcre, + b"America/Porto_Velho" => TimeZone::AmericaPortoVelho, + b"America/Puerto_Rico" => TimeZone::AmericaPuertoRico, + b"America/Punta_Arenas" => TimeZone::AmericaPuntaArenas, + b"America/Rainy_River" => TimeZone::AmericaRainyRiver, + b"America/Rankin_Inlet" => TimeZone::AmericaRankinInlet, + b"America/Recife" => TimeZone::AmericaRecife, + b"America/Regina" => TimeZone::AmericaRegina, + b"America/Resolute" => TimeZone::AmericaResolute, + b"America/Rio_Branco" => TimeZone::AmericaRioBranco, + b"America/Rosario" => TimeZone::AmericaRosario, + b"America/Santa_Isabel" => TimeZone::AmericaSantaIsabel, + b"America/Santarem" => TimeZone::AmericaSantarem, + b"America/Santiago" => TimeZone::AmericaSantiago, + b"America/Santo_Domingo" => TimeZone::AmericaSantoDomingo, + b"America/Sao_Paulo" => TimeZone::AmericaSaoPaulo, + b"America/Scoresbysund" => TimeZone::AmericaScoresbysund, + b"America/Shiprock" => TimeZone::AmericaShiprock, + b"America/Sitka" => TimeZone::AmericaSitka, + b"America/St_Barthelemy" => TimeZone::AmericaStBarthelemy, + b"America/St_Johns" => TimeZone::AmericaStJohns, + b"America/St_Kitts" => TimeZone::AmericaStKitts, + b"America/St_Lucia" => TimeZone::AmericaStLucia, + b"America/St_Thomas" => TimeZone::AmericaStThomas, + b"America/St_Vincent" => TimeZone::AmericaStVincent, + b"America/Swift_Current" => TimeZone::AmericaSwiftCurrent, + b"America/Tegucigalpa" => TimeZone::AmericaTegucigalpa, + b"America/Thule" => TimeZone::AmericaThule, + b"America/Thunder_Bay" => TimeZone::AmericaThunderBay, + b"America/Tijuana" => TimeZone::AmericaTijuana, + b"America/Toronto" => TimeZone::AmericaToronto, + b"America/Tortola" => TimeZone::AmericaTortola, + b"America/Vancouver" => TimeZone::AmericaVancouver, + b"America/Virgin" => TimeZone::AmericaVirgin, + b"America/Whitehorse" => TimeZone::AmericaWhitehorse, + b"America/Winnipeg" => TimeZone::AmericaWinnipeg, + b"America/Yakutat" => TimeZone::AmericaYakutat, + b"America/Yellowknife" => TimeZone::AmericaYellowknife, + b"Antarctica/Casey" => TimeZone::AntarcticaCasey, + b"Antarctica/Davis" => TimeZone::AntarcticaDavis, + b"Antarctica/DumontDUrville" => TimeZone::AntarcticaDumontDUrville, + b"Antarctica/Macquarie" => TimeZone::AntarcticaMacquarie, + b"Antarctica/Mawson" => TimeZone::AntarcticaMawson, + b"Antarctica/McMurdo" => TimeZone::AntarcticaMcMurdo, + b"Antarctica/Palmer" => TimeZone::AntarcticaPalmer, + b"Antarctica/Rothera" => TimeZone::AntarcticaRothera, + b"Antarctica/South_Pole" => TimeZone::AntarcticaSouthPole, + b"Antarctica/Syowa" => TimeZone::AntarcticaSyowa, + b"Antarctica/Troll" => TimeZone::AntarcticaTroll, + b"Antarctica/Vostok" => TimeZone::AntarcticaVostok, + b"Arctic/Longyearbyen" => TimeZone::ArcticLongyearbyen, + b"Asia/Aden" => TimeZone::AsiaAden, + b"Asia/Almaty" => TimeZone::AsiaAlmaty, + b"Asia/Amman" => TimeZone::AsiaAmman, + b"Asia/Anadyr" => TimeZone::AsiaAnadyr, + b"Asia/Aqtau" => TimeZone::AsiaAqtau, + b"Asia/Aqtobe" => TimeZone::AsiaAqtobe, + b"Asia/Ashgabat" => TimeZone::AsiaAshgabat, + b"Asia/Ashkhabad" => TimeZone::AsiaAshkhabad, + b"Asia/Atyrau" => TimeZone::AsiaAtyrau, + b"Asia/Baghdad" => TimeZone::AsiaBaghdad, + b"Asia/Bahrain" => TimeZone::AsiaBahrain, + b"Asia/Baku" => TimeZone::AsiaBaku, + b"Asia/Bangkok" => TimeZone::AsiaBangkok, + b"Asia/Barnaul" => TimeZone::AsiaBarnaul, + b"Asia/Beirut" => TimeZone::AsiaBeirut, + b"Asia/Bishkek" => TimeZone::AsiaBishkek, + b"Asia/Brunei" => TimeZone::AsiaBrunei, + b"Asia/Calcutta" => TimeZone::AsiaCalcutta, + b"Asia/Chita" => TimeZone::AsiaChita, + b"Asia/Choibalsan" => TimeZone::AsiaChoibalsan, + b"Asia/Chongqing" => TimeZone::AsiaChongqing, + b"Asia/Chungking" => TimeZone::AsiaChungking, + b"Asia/Colombo" => TimeZone::AsiaColombo, + b"Asia/Dacca" => TimeZone::AsiaDacca, + b"Asia/Damascus" => TimeZone::AsiaDamascus, + b"Asia/Dhaka" => TimeZone::AsiaDhaka, + b"Asia/Dili" => TimeZone::AsiaDili, + b"Asia/Dubai" => TimeZone::AsiaDubai, + b"Asia/Dushanbe" => TimeZone::AsiaDushanbe, + b"Asia/Famagusta" => TimeZone::AsiaFamagusta, + b"Asia/Gaza" => TimeZone::AsiaGaza, + b"Asia/Harbin" => TimeZone::AsiaHarbin, + b"Asia/Hebron" => TimeZone::AsiaHebron, + b"Asia/Ho_Chi_Minh" => TimeZone::AsiaHoChiMinh, + b"Asia/Hong_Kong" => TimeZone::AsiaHongKong, + b"Asia/Hovd" => TimeZone::AsiaHovd, + b"Asia/Irkutsk" => TimeZone::AsiaIrkutsk, + b"Asia/Istanbul" => TimeZone::AsiaIstanbul, + b"Asia/Jakarta" => TimeZone::AsiaJakarta, + b"Asia/Jayapura" => TimeZone::AsiaJayapura, + b"Asia/Jerusalem" => TimeZone::AsiaJerusalem, + b"Asia/Kabul" => TimeZone::AsiaKabul, + b"Asia/Kamchatka" => TimeZone::AsiaKamchatka, + b"Asia/Karachi" => TimeZone::AsiaKarachi, + b"Asia/Kashgar" => TimeZone::AsiaKashgar, + b"Asia/Kathmandu" => TimeZone::AsiaKathmandu, + b"Asia/Katmandu" => TimeZone::AsiaKatmandu, + b"Asia/Khandyga" => TimeZone::AsiaKhandyga, + b"Asia/Kolkata" => TimeZone::AsiaKolkata, + b"Asia/Krasnoyarsk" => TimeZone::AsiaKrasnoyarsk, + b"Asia/Kuala_Lumpur" => TimeZone::AsiaKualaLumpur, + b"Asia/Kuching" => TimeZone::AsiaKuching, + b"Asia/Kuwait" => TimeZone::AsiaKuwait, + b"Asia/Macao" => TimeZone::AsiaMacao, + b"Asia/Macau" => TimeZone::AsiaMacau, + b"Asia/Magadan" => TimeZone::AsiaMagadan, + b"Asia/Makassar" => TimeZone::AsiaMakassar, + b"Asia/Manila" => TimeZone::AsiaManila, + b"Asia/Muscat" => TimeZone::AsiaMuscat, + b"Asia/Nicosia" => TimeZone::AsiaNicosia, + b"Asia/Novokuznetsk" => TimeZone::AsiaNovokuznetsk, + b"Asia/Novosibirsk" => TimeZone::AsiaNovosibirsk, + b"Asia/Omsk" => TimeZone::AsiaOmsk, + b"Asia/Oral" => TimeZone::AsiaOral, + b"Asia/Phnom_Penh" => TimeZone::AsiaPhnomPenh, + b"Asia/Pontianak" => TimeZone::AsiaPontianak, + b"Asia/Pyongyang" => TimeZone::AsiaPyongyang, + b"Asia/Qatar" => TimeZone::AsiaQatar, + b"Asia/Qostanay" => TimeZone::AsiaQostanay, + b"Asia/Qyzylorda" => TimeZone::AsiaQyzylorda, + b"Asia/Rangoon" => TimeZone::AsiaRangoon, + b"Asia/Riyadh" => TimeZone::AsiaRiyadh, + b"Asia/Saigon" => TimeZone::AsiaSaigon, + b"Asia/Sakhalin" => TimeZone::AsiaSakhalin, + b"Asia/Samarkand" => TimeZone::AsiaSamarkand, + b"Asia/Seoul" => TimeZone::AsiaSeoul, + b"Asia/Shanghai" => TimeZone::AsiaShanghai, + b"Asia/Singapore" => TimeZone::AsiaSingapore, + b"Asia/Srednekolymsk" => TimeZone::AsiaSrednekolymsk, + b"Asia/Taipei" => TimeZone::AsiaTaipei, + b"Asia/Tashkent" => TimeZone::AsiaTashkent, + b"Asia/Tbilisi" => TimeZone::AsiaTbilisi, + b"Asia/Tehran" => TimeZone::AsiaTehran, + b"Asia/Tel_Aviv" => TimeZone::AsiaTelAviv, + b"Asia/Thimbu" => TimeZone::AsiaThimbu, + b"Asia/Thimphu" => TimeZone::AsiaThimphu, + b"Asia/Tokyo" => TimeZone::AsiaTokyo, + b"Asia/Tomsk" => TimeZone::AsiaTomsk, + b"Asia/Ujung_Pandang" => TimeZone::AsiaUjungPandang, + b"Asia/Ulaanbaatar" => TimeZone::AsiaUlaanbaatar, + b"Asia/Ulan_Bator" => TimeZone::AsiaUlanBator, + b"Asia/Urumqi" => TimeZone::AsiaUrumqi, + b"Asia/Ust-Nera" => TimeZone::AsiaUstNera, + b"Asia/Vientiane" => TimeZone::AsiaVientiane, + b"Asia/Vladivostok" => TimeZone::AsiaVladivostok, + b"Asia/Yakutsk" => TimeZone::AsiaYakutsk, + b"Asia/Yangon" => TimeZone::AsiaYangon, + b"Asia/Yekaterinburg" => TimeZone::AsiaYekaterinburg, + b"Asia/Yerevan" => TimeZone::AsiaYerevan, + b"Atlantic/Azores" => TimeZone::AtlanticAzores, + b"Atlantic/Bermuda" => TimeZone::AtlanticBermuda, + b"Atlantic/Canary" => TimeZone::AtlanticCanary, + b"Atlantic/Cape_Verde" => TimeZone::AtlanticCapeVerde, + b"Atlantic/Faeroe" => TimeZone::AtlanticFaeroe, + b"Atlantic/Faroe" => TimeZone::AtlanticFaroe, + b"Atlantic/Jan_Mayen" => TimeZone::AtlanticJanMayen, + b"Atlantic/Madeira" => TimeZone::AtlanticMadeira, + b"Atlantic/Reykjavik" => TimeZone::AtlanticReykjavik, + b"Atlantic/South_Georgia" => TimeZone::AtlanticSouthGeorgia, + b"Atlantic/St_Helena" => TimeZone::AtlanticStHelena, + b"Atlantic/Stanley" => TimeZone::AtlanticStanley, + b"Australia/ACT" => TimeZone::AustraliaACT, + b"Australia/Adelaide" => TimeZone::AustraliaAdelaide, + b"Australia/Brisbane" => TimeZone::AustraliaBrisbane, + b"Australia/Broken_Hill" => TimeZone::AustraliaBrokenHill, + b"Australia/Canberra" => TimeZone::AustraliaCanberra, + b"Australia/Currie" => TimeZone::AustraliaCurrie, + b"Australia/Darwin" => TimeZone::AustraliaDarwin, + b"Australia/Eucla" => TimeZone::AustraliaEucla, + b"Australia/Hobart" => TimeZone::AustraliaHobart, + b"Australia/LHI" => TimeZone::AustraliaLHI, + b"Australia/Lindeman" => TimeZone::AustraliaLindeman, + b"Australia/Lord_Howe" => TimeZone::AustraliaLordHowe, + b"Australia/Melbourne" => TimeZone::AustraliaMelbourne, + b"Australia/NSW" => TimeZone::AustraliaNSW, + b"Australia/North" => TimeZone::AustraliaNorth, + b"Australia/Perth" => TimeZone::AustraliaPerth, + b"Australia/Queensland" => TimeZone::AustraliaQueensland, + b"Australia/South" => TimeZone::AustraliaSouth, + b"Australia/Sydney" => TimeZone::AustraliaSydney, + b"Australia/Tasmania" => TimeZone::AustraliaTasmania, + b"Australia/Victoria" => TimeZone::AustraliaVictoria, + b"Australia/West" => TimeZone::AustraliaWest, + b"Australia/Yancowinna" => TimeZone::AustraliaYancowinna, + b"Brazil/Acre" => TimeZone::BrazilAcre, + b"Brazil/DeNoronha" => TimeZone::BrazilDeNoronha, + b"Brazil/East" => TimeZone::BrazilEast, + b"Brazil/West" => TimeZone::BrazilWest, + b"CET" => TimeZone::CET, + b"CST6CDT" => TimeZone::CST6CDT, + b"Canada/Atlantic" => TimeZone::CanadaAtlantic, + b"Canada/Central" => TimeZone::CanadaCentral, + b"Canada/Eastern" => TimeZone::CanadaEastern, + b"Canada/Mountain" => TimeZone::CanadaMountain, + b"Canada/Newfoundland" => TimeZone::CanadaNewfoundland, + b"Canada/Pacific" => TimeZone::CanadaPacific, + b"Canada/Saskatchewan" => TimeZone::CanadaSaskatchewan, + b"Canada/Yukon" => TimeZone::CanadaYukon, + b"Chile/Continental" => TimeZone::ChileContinental, + b"Chile/EasterIsland" => TimeZone::ChileEasterIsland, + b"Cuba" => TimeZone::Cuba, + b"EET" => TimeZone::EET, + b"EST" => TimeZone::EST, + b"EST5EDT" => TimeZone::EST5EDT, + b"Egypt" => TimeZone::Egypt, + b"Eire" => TimeZone::Eire, + b"Etc/GMT" => TimeZone::EtcGMT, + b"Etc/GMT+0" => TimeZone::EtcGMTPlus0, + b"Etc/GMT+1" => TimeZone::EtcGMTPlus1, + b"Etc/GMT+10" => TimeZone::EtcGMTPlus10, + b"Etc/GMT+11" => TimeZone::EtcGMTPlus11, + b"Etc/GMT+12" => TimeZone::EtcGMTPlus12, + b"Etc/GMT+2" => TimeZone::EtcGMTPlus2, + b"Etc/GMT+3" => TimeZone::EtcGMTPlus3, + b"Etc/GMT+4" => TimeZone::EtcGMTPlus4, + b"Etc/GMT+5" => TimeZone::EtcGMTPlus5, + b"Etc/GMT+6" => TimeZone::EtcGMTPlus6, + b"Etc/GMT+7" => TimeZone::EtcGMTPlus7, + b"Etc/GMT+8" => TimeZone::EtcGMTPlus8, + b"Etc/GMT+9" => TimeZone::EtcGMTPlus9, + b"Etc/GMT-0" => TimeZone::EtcGMTMinus0, + b"Etc/GMT-1" => TimeZone::EtcGMTMinus1, + b"Etc/GMT-10" => TimeZone::EtcGMTMinus10, + b"Etc/GMT-11" => TimeZone::EtcGMTMinus11, + b"Etc/GMT-12" => TimeZone::EtcGMTMinus12, + b"Etc/GMT-13" => TimeZone::EtcGMTMinus13, + b"Etc/GMT-14" => TimeZone::EtcGMTMinus14, + b"Etc/GMT-2" => TimeZone::EtcGMTMinus2, + b"Etc/GMT-3" => TimeZone::EtcGMTMinus3, + b"Etc/GMT-4" => TimeZone::EtcGMTMinus4, + b"Etc/GMT-5" => TimeZone::EtcGMTMinus5, + b"Etc/GMT-6" => TimeZone::EtcGMTMinus6, + b"Etc/GMT-7" => TimeZone::EtcGMTMinus7, + b"Etc/GMT-8" => TimeZone::EtcGMTMinus8, + b"Etc/GMT-9" => TimeZone::EtcGMTMinus9, + b"Etc/GMT0" => TimeZone::EtcGMT0, + b"Etc/Greenwich" => TimeZone::EtcGreenwich, + b"Etc/UCT" => TimeZone::EtcUCT, + b"Etc/UTC" => TimeZone::EtcUTC, + b"Etc/Universal" => TimeZone::EtcUniversal, + b"Etc/Zulu" => TimeZone::EtcZulu, + b"Europe/Amsterdam" => TimeZone::EuropeAmsterdam, + b"Europe/Andorra" => TimeZone::EuropeAndorra, + b"Europe/Astrakhan" => TimeZone::EuropeAstrakhan, + b"Europe/Athens" => TimeZone::EuropeAthens, + b"Europe/Belfast" => TimeZone::EuropeBelfast, + b"Europe/Belgrade" => TimeZone::EuropeBelgrade, + b"Europe/Berlin" => TimeZone::EuropeBerlin, + b"Europe/Bratislava" => TimeZone::EuropeBratislava, + b"Europe/Brussels" => TimeZone::EuropeBrussels, + b"Europe/Bucharest" => TimeZone::EuropeBucharest, + b"Europe/Budapest" => TimeZone::EuropeBudapest, + b"Europe/Busingen" => TimeZone::EuropeBusingen, + b"Europe/Chisinau" => TimeZone::EuropeChisinau, + b"Europe/Copenhagen" => TimeZone::EuropeCopenhagen, + b"Europe/Dublin" => TimeZone::EuropeDublin, + b"Europe/Gibraltar" => TimeZone::EuropeGibraltar, + b"Europe/Guernsey" => TimeZone::EuropeGuernsey, + b"Europe/Helsinki" => TimeZone::EuropeHelsinki, + b"Europe/Isle_of_Man" => TimeZone::EuropeIsleOfMan, + b"Europe/Istanbul" => TimeZone::EuropeIstanbul, + b"Europe/Jersey" => TimeZone::EuropeJersey, + b"Europe/Kaliningrad" => TimeZone::EuropeKaliningrad, + b"Europe/Kiev" => TimeZone::EuropeKiev, + b"Europe/Kirov" => TimeZone::EuropeKirov, + b"Europe/Kyiv" => TimeZone::EuropeKyiv, + b"Europe/Lisbon" => TimeZone::EuropeLisbon, + b"Europe/Ljubljana" => TimeZone::EuropeLjubljana, + b"Europe/London" => TimeZone::EuropeLondon, + b"Europe/Luxembourg" => TimeZone::EuropeLuxembourg, + b"Europe/Madrid" => TimeZone::EuropeMadrid, + b"Europe/Malta" => TimeZone::EuropeMalta, + b"Europe/Mariehamn" => TimeZone::EuropeMariehamn, + b"Europe/Minsk" => TimeZone::EuropeMinsk, + b"Europe/Monaco" => TimeZone::EuropeMonaco, + b"Europe/Moscow" => TimeZone::EuropeMoscow, + b"Europe/Nicosia" => TimeZone::EuropeNicosia, + b"Europe/Oslo" => TimeZone::EuropeOslo, + b"Europe/Paris" => TimeZone::EuropeParis, + b"Europe/Podgorica" => TimeZone::EuropePodgorica, + b"Europe/Prague" => TimeZone::EuropePrague, + b"Europe/Riga" => TimeZone::EuropeRiga, + b"Europe/Rome" => TimeZone::EuropeRome, + b"Europe/Samara" => TimeZone::EuropeSamara, + b"Europe/San_Marino" => TimeZone::EuropeSanMarino, + b"Europe/Sarajevo" => TimeZone::EuropeSarajevo, + b"Europe/Saratov" => TimeZone::EuropeSaratov, + b"Europe/Simferopol" => TimeZone::EuropeSimferopol, + b"Europe/Skopje" => TimeZone::EuropeSkopje, + b"Europe/Sofia" => TimeZone::EuropeSofia, + b"Europe/Stockholm" => TimeZone::EuropeStockholm, + b"Europe/Tallinn" => TimeZone::EuropeTallinn, + b"Europe/Tirane" => TimeZone::EuropeTirane, + b"Europe/Tiraspol" => TimeZone::EuropeTiraspol, + b"Europe/Ulyanovsk" => TimeZone::EuropeUlyanovsk, + b"Europe/Uzhgorod" => TimeZone::EuropeUzhgorod, + b"Europe/Vaduz" => TimeZone::EuropeVaduz, + b"Europe/Vatican" => TimeZone::EuropeVatican, + b"Europe/Vienna" => TimeZone::EuropeVienna, + b"Europe/Vilnius" => TimeZone::EuropeVilnius, + b"Europe/Volgograd" => TimeZone::EuropeVolgograd, + b"Europe/Warsaw" => TimeZone::EuropeWarsaw, + b"Europe/Zagreb" => TimeZone::EuropeZagreb, + b"Europe/Zaporozhye" => TimeZone::EuropeZaporozhye, + b"Europe/Zurich" => TimeZone::EuropeZurich, + b"Factory" => TimeZone::Factory, + b"GB" => TimeZone::GB, + b"GB-Eire" => TimeZone::GBEire, + b"GMT" => TimeZone::GMT, + b"GMT+0" => TimeZone::GMTPlus0, + b"GMT-0" => TimeZone::GMTMinus0, + b"GMT0" => TimeZone::GMT0, + b"Greenwich" => TimeZone::Greenwich, + b"HST" => TimeZone::HST, + b"Hongkong" => TimeZone::Hongkong, + b"Iceland" => TimeZone::Iceland, + b"Indian/Antananarivo" => TimeZone::IndianAntananarivo, + b"Indian/Chagos" => TimeZone::IndianChagos, + b"Indian/Christmas" => TimeZone::IndianChristmas, + b"Indian/Cocos" => TimeZone::IndianCocos, + b"Indian/Comoro" => TimeZone::IndianComoro, + b"Indian/Kerguelen" => TimeZone::IndianKerguelen, + b"Indian/Mahe" => TimeZone::IndianMahe, + b"Indian/Maldives" => TimeZone::IndianMaldives, + b"Indian/Mauritius" => TimeZone::IndianMauritius, + b"Indian/Mayotte" => TimeZone::IndianMayotte, + b"Indian/Reunion" => TimeZone::IndianReunion, + b"Iran" => TimeZone::Iran, + b"Israel" => TimeZone::Israel, + b"Jamaica" => TimeZone::Jamaica, + b"Japan" => TimeZone::Japan, + b"Kwajalein" => TimeZone::Kwajalein, + b"Libya" => TimeZone::Libya, + b"MET" => TimeZone::MET, + b"MST" => TimeZone::MST, + b"MST7MDT" => TimeZone::MST7MDT, + b"Mexico/BajaNorte" => TimeZone::MexicoBajaNorte, + b"Mexico/BajaSur" => TimeZone::MexicoBajaSur, + b"Mexico/General" => TimeZone::MexicoGeneral, + b"NZ" => TimeZone::NZ, + b"NZ-CHAT" => TimeZone::NZCHAT, + b"Navajo" => TimeZone::Navajo, + b"PRC" => TimeZone::PRC, + b"PST8PDT" => TimeZone::PST8PDT, + b"Pacific/Apia" => TimeZone::PacificApia, + b"Pacific/Auckland" => TimeZone::PacificAuckland, + b"Pacific/Bougainville" => TimeZone::PacificBougainville, + b"Pacific/Chatham" => TimeZone::PacificChatham, + b"Pacific/Chuuk" => TimeZone::PacificChuuk, + b"Pacific/Easter" => TimeZone::PacificEaster, + b"Pacific/Efate" => TimeZone::PacificEfate, + b"Pacific/Enderbury" => TimeZone::PacificEnderbury, + b"Pacific/Fakaofo" => TimeZone::PacificFakaofo, + b"Pacific/Fiji" => TimeZone::PacificFiji, + b"Pacific/Funafuti" => TimeZone::PacificFunafuti, + b"Pacific/Galapagos" => TimeZone::PacificGalapagos, + b"Pacific/Gambier" => TimeZone::PacificGambier, + b"Pacific/Guadalcanal" => TimeZone::PacificGuadalcanal, + b"Pacific/Guam" => TimeZone::PacificGuam, + b"Pacific/Honolulu" => TimeZone::PacificHonolulu, + b"Pacific/Johnston" => TimeZone::PacificJohnston, + b"Pacific/Kanton" => TimeZone::PacificKanton, + b"Pacific/Kiritimati" => TimeZone::PacificKiritimati, + b"Pacific/Kosrae" => TimeZone::PacificKosrae, + b"Pacific/Kwajalein" => TimeZone::PacificKwajalein, + b"Pacific/Majuro" => TimeZone::PacificMajuro, + b"Pacific/Marquesas" => TimeZone::PacificMarquesas, + b"Pacific/Midway" => TimeZone::PacificMidway, + b"Pacific/Nauru" => TimeZone::PacificNauru, + b"Pacific/Niue" => TimeZone::PacificNiue, + b"Pacific/Norfolk" => TimeZone::PacificNorfolk, + b"Pacific/Noumea" => TimeZone::PacificNoumea, + b"Pacific/Pago_Pago" => TimeZone::PacificPagoPago, + b"Pacific/Palau" => TimeZone::PacificPalau, + b"Pacific/Pitcairn" => TimeZone::PacificPitcairn, + b"Pacific/Pohnpei" => TimeZone::PacificPohnpei, + b"Pacific/Ponape" => TimeZone::PacificPonape, + b"Pacific/Port_Moresby" => TimeZone::PacificPortMoresby, + b"Pacific/Rarotonga" => TimeZone::PacificRarotonga, + b"Pacific/Saipan" => TimeZone::PacificSaipan, + b"Pacific/Samoa" => TimeZone::PacificSamoa, + b"Pacific/Tahiti" => TimeZone::PacificTahiti, + b"Pacific/Tarawa" => TimeZone::PacificTarawa, + b"Pacific/Tongatapu" => TimeZone::PacificTongatapu, + b"Pacific/Truk" => TimeZone::PacificTruk, + b"Pacific/Wake" => TimeZone::PacificWake, + b"Pacific/Wallis" => TimeZone::PacificWallis, + b"Pacific/Yap" => TimeZone::PacificYap, + b"Poland" => TimeZone::Poland, + b"Portugal" => TimeZone::Portugal, + b"ROC" => TimeZone::ROC, + b"ROK" => TimeZone::ROK, + b"Singapore" => TimeZone::Singapore, + b"Turkey" => TimeZone::Turkey, + b"UCT" => TimeZone::UCT, + b"US/Alaska" => TimeZone::USAlaska, + b"US/Aleutian" => TimeZone::USAleutian, + b"US/Arizona" => TimeZone::USArizona, + b"US/Central" => TimeZone::USCentral, + b"US/East-Indiana" => TimeZone::USEastIndiana, + b"US/Eastern" => TimeZone::USEastern, + b"US/Hawaii" => TimeZone::USHawaii, + b"US/Indiana-Starke" => TimeZone::USIndianaStarke, + b"US/Michigan" => TimeZone::USMichigan, + b"US/Mountain" => TimeZone::USMountain, + b"US/Pacific" => TimeZone::USPacific, + b"US/Samoa" => TimeZone::USSamoa, + b"UTC" => TimeZone::UTC, + b"Universal" => TimeZone::Universal, + b"W-SU" => TimeZone::WSU, + b"WET" => TimeZone::WET, + b"Zulu" => TimeZone::Zulu, + } + .copied() + } + + fn as_str(&self) -> &'static str { + match self { + TimeZone::AfricaAbidjan => "Africa/Abidjan", + TimeZone::AfricaAccra => "Africa/Accra", + TimeZone::AfricaAddisAbaba => "Africa/Addis_Ababa", + TimeZone::AfricaAlgiers => "Africa/Algiers", + TimeZone::AfricaAsmara => "Africa/Asmara", + TimeZone::AfricaAsmera => "Africa/Asmera", + TimeZone::AfricaBamako => "Africa/Bamako", + TimeZone::AfricaBangui => "Africa/Bangui", + TimeZone::AfricaBanjul => "Africa/Banjul", + TimeZone::AfricaBissau => "Africa/Bissau", + TimeZone::AfricaBlantyre => "Africa/Blantyre", + TimeZone::AfricaBrazzaville => "Africa/Brazzaville", + TimeZone::AfricaBujumbura => "Africa/Bujumbura", + TimeZone::AfricaCairo => "Africa/Cairo", + TimeZone::AfricaCasablanca => "Africa/Casablanca", + TimeZone::AfricaCeuta => "Africa/Ceuta", + TimeZone::AfricaConakry => "Africa/Conakry", + TimeZone::AfricaDakar => "Africa/Dakar", + TimeZone::AfricaDarEsSalaam => "Africa/Dar_es_Salaam", + TimeZone::AfricaDjibouti => "Africa/Djibouti", + TimeZone::AfricaDouala => "Africa/Douala", + TimeZone::AfricaElAaiun => "Africa/El_Aaiun", + TimeZone::AfricaFreetown => "Africa/Freetown", + TimeZone::AfricaGaborone => "Africa/Gaborone", + TimeZone::AfricaHarare => "Africa/Harare", + TimeZone::AfricaJohannesburg => "Africa/Johannesburg", + TimeZone::AfricaJuba => "Africa/Juba", + TimeZone::AfricaKampala => "Africa/Kampala", + TimeZone::AfricaKhartoum => "Africa/Khartoum", + TimeZone::AfricaKigali => "Africa/Kigali", + TimeZone::AfricaKinshasa => "Africa/Kinshasa", + TimeZone::AfricaLagos => "Africa/Lagos", + TimeZone::AfricaLibreville => "Africa/Libreville", + TimeZone::AfricaLome => "Africa/Lome", + TimeZone::AfricaLuanda => "Africa/Luanda", + TimeZone::AfricaLubumbashi => "Africa/Lubumbashi", + TimeZone::AfricaLusaka => "Africa/Lusaka", + TimeZone::AfricaMalabo => "Africa/Malabo", + TimeZone::AfricaMaputo => "Africa/Maputo", + TimeZone::AfricaMaseru => "Africa/Maseru", + TimeZone::AfricaMbabane => "Africa/Mbabane", + TimeZone::AfricaMogadishu => "Africa/Mogadishu", + TimeZone::AfricaMonrovia => "Africa/Monrovia", + TimeZone::AfricaNairobi => "Africa/Nairobi", + TimeZone::AfricaNdjamena => "Africa/Ndjamena", + TimeZone::AfricaNiamey => "Africa/Niamey", + TimeZone::AfricaNouakchott => "Africa/Nouakchott", + TimeZone::AfricaOuagadougou => "Africa/Ouagadougou", + TimeZone::AfricaPortoNovo => "Africa/Porto-Novo", + TimeZone::AfricaSaoTome => "Africa/Sao_Tome", + TimeZone::AfricaTimbuktu => "Africa/Timbuktu", + TimeZone::AfricaTripoli => "Africa/Tripoli", + TimeZone::AfricaTunis => "Africa/Tunis", + TimeZone::AfricaWindhoek => "Africa/Windhoek", + TimeZone::AmericaAdak => "America/Adak", + TimeZone::AmericaAnchorage => "America/Anchorage", + TimeZone::AmericaAnguilla => "America/Anguilla", + TimeZone::AmericaAntigua => "America/Antigua", + TimeZone::AmericaAraguaina => "America/Araguaina", + TimeZone::AmericaArgentinaBuenosAires => "America/Argentina/Buenos_Aires", + TimeZone::AmericaArgentinaCatamarca => "America/Argentina/Catamarca", + TimeZone::AmericaArgentinaComodRivadavia => "America/Argentina/ComodRivadavia", + TimeZone::AmericaArgentinaCordoba => "America/Argentina/Cordoba", + TimeZone::AmericaArgentinaJujuy => "America/Argentina/Jujuy", + TimeZone::AmericaArgentinaLaRioja => "America/Argentina/La_Rioja", + TimeZone::AmericaArgentinaMendoza => "America/Argentina/Mendoza", + TimeZone::AmericaArgentinaRioGallegos => "America/Argentina/Rio_Gallegos", + TimeZone::AmericaArgentinaSalta => "America/Argentina/Salta", + TimeZone::AmericaArgentinaSanJuan => "America/Argentina/San_Juan", + TimeZone::AmericaArgentinaSanLuis => "America/Argentina/San_Luis", + TimeZone::AmericaArgentinaTucuman => "America/Argentina/Tucuman", + TimeZone::AmericaArgentinaUshuaia => "America/Argentina/Ushuaia", + TimeZone::AmericaAruba => "America/Aruba", + TimeZone::AmericaAsuncion => "America/Asuncion", + TimeZone::AmericaAtikokan => "America/Atikokan", + TimeZone::AmericaAtka => "America/Atka", + TimeZone::AmericaBahia => "America/Bahia", + TimeZone::AmericaBahiaBanderas => "America/Bahia_Banderas", + TimeZone::AmericaBarbados => "America/Barbados", + TimeZone::AmericaBelem => "America/Belem", + TimeZone::AmericaBelize => "America/Belize", + TimeZone::AmericaBlancSablon => "America/Blanc-Sablon", + TimeZone::AmericaBoaVista => "America/Boa_Vista", + TimeZone::AmericaBogota => "America/Bogota", + TimeZone::AmericaBoise => "America/Boise", + TimeZone::AmericaBuenosAires => "America/Buenos_Aires", + TimeZone::AmericaCambridgeBay => "America/Cambridge_Bay", + TimeZone::AmericaCampoGrande => "America/Campo_Grande", + TimeZone::AmericaCancun => "America/Cancun", + TimeZone::AmericaCaracas => "America/Caracas", + TimeZone::AmericaCatamarca => "America/Catamarca", + TimeZone::AmericaCayenne => "America/Cayenne", + TimeZone::AmericaCayman => "America/Cayman", + TimeZone::AmericaChicago => "America/Chicago", + TimeZone::AmericaChihuahua => "America/Chihuahua", + TimeZone::AmericaCiudadJuarez => "America/Ciudad_Juarez", + TimeZone::AmericaCoralHarbour => "America/Coral_Harbour", + TimeZone::AmericaCordoba => "America/Cordoba", + TimeZone::AmericaCostaRica => "America/Costa_Rica", + TimeZone::AmericaCoyhaique => "America/Coyhaique", + TimeZone::AmericaCreston => "America/Creston", + TimeZone::AmericaCuiaba => "America/Cuiaba", + TimeZone::AmericaCuracao => "America/Curacao", + TimeZone::AmericaDanmarkshavn => "America/Danmarkshavn", + TimeZone::AmericaDawson => "America/Dawson", + TimeZone::AmericaDawsonCreek => "America/Dawson_Creek", + TimeZone::AmericaDenver => "America/Denver", + TimeZone::AmericaDetroit => "America/Detroit", + TimeZone::AmericaDominica => "America/Dominica", + TimeZone::AmericaEdmonton => "America/Edmonton", + TimeZone::AmericaEirunepe => "America/Eirunepe", + TimeZone::AmericaElSalvador => "America/El_Salvador", + TimeZone::AmericaEnsenada => "America/Ensenada", + TimeZone::AmericaFortNelson => "America/Fort_Nelson", + TimeZone::AmericaFortWayne => "America/Fort_Wayne", + TimeZone::AmericaFortaleza => "America/Fortaleza", + TimeZone::AmericaGlaceBay => "America/Glace_Bay", + TimeZone::AmericaGodthab => "America/Godthab", + TimeZone::AmericaGooseBay => "America/Goose_Bay", + TimeZone::AmericaGrandTurk => "America/Grand_Turk", + TimeZone::AmericaGrenada => "America/Grenada", + TimeZone::AmericaGuadeloupe => "America/Guadeloupe", + TimeZone::AmericaGuatemala => "America/Guatemala", + TimeZone::AmericaGuayaquil => "America/Guayaquil", + TimeZone::AmericaGuyana => "America/Guyana", + TimeZone::AmericaHalifax => "America/Halifax", + TimeZone::AmericaHavana => "America/Havana", + TimeZone::AmericaHermosillo => "America/Hermosillo", + TimeZone::AmericaIndianaIndianapolis => "America/Indiana/Indianapolis", + TimeZone::AmericaIndianaKnox => "America/Indiana/Knox", + TimeZone::AmericaIndianaMarengo => "America/Indiana/Marengo", + TimeZone::AmericaIndianaPetersburg => "America/Indiana/Petersburg", + TimeZone::AmericaIndianaTellCity => "America/Indiana/Tell_City", + TimeZone::AmericaIndianaVevay => "America/Indiana/Vevay", + TimeZone::AmericaIndianaVincennes => "America/Indiana/Vincennes", + TimeZone::AmericaIndianaWinamac => "America/Indiana/Winamac", + TimeZone::AmericaIndianapolis => "America/Indianapolis", + TimeZone::AmericaInuvik => "America/Inuvik", + TimeZone::AmericaIqaluit => "America/Iqaluit", + TimeZone::AmericaJamaica => "America/Jamaica", + TimeZone::AmericaJujuy => "America/Jujuy", + TimeZone::AmericaJuneau => "America/Juneau", + TimeZone::AmericaKentuckyLouisville => "America/Kentucky/Louisville", + TimeZone::AmericaKentuckyMonticello => "America/Kentucky/Monticello", + TimeZone::AmericaKnoxIN => "America/Knox_IN", + TimeZone::AmericaKralendijk => "America/Kralendijk", + TimeZone::AmericaLaPaz => "America/La_Paz", + TimeZone::AmericaLima => "America/Lima", + TimeZone::AmericaLosAngeles => "America/Los_Angeles", + TimeZone::AmericaLouisville => "America/Louisville", + TimeZone::AmericaLowerPrinces => "America/Lower_Princes", + TimeZone::AmericaMaceio => "America/Maceio", + TimeZone::AmericaManagua => "America/Managua", + TimeZone::AmericaManaus => "America/Manaus", + TimeZone::AmericaMarigot => "America/Marigot", + TimeZone::AmericaMartinique => "America/Martinique", + TimeZone::AmericaMatamoros => "America/Matamoros", + TimeZone::AmericaMazatlan => "America/Mazatlan", + TimeZone::AmericaMendoza => "America/Mendoza", + TimeZone::AmericaMenominee => "America/Menominee", + TimeZone::AmericaMerida => "America/Merida", + TimeZone::AmericaMetlakatla => "America/Metlakatla", + TimeZone::AmericaMexicoCity => "America/Mexico_City", + TimeZone::AmericaMiquelon => "America/Miquelon", + TimeZone::AmericaMoncton => "America/Moncton", + TimeZone::AmericaMonterrey => "America/Monterrey", + TimeZone::AmericaMontevideo => "America/Montevideo", + TimeZone::AmericaMontreal => "America/Montreal", + TimeZone::AmericaMontserrat => "America/Montserrat", + TimeZone::AmericaNassau => "America/Nassau", + TimeZone::AmericaNewYork => "America/New_York", + TimeZone::AmericaNipigon => "America/Nipigon", + TimeZone::AmericaNome => "America/Nome", + TimeZone::AmericaNoronha => "America/Noronha", + TimeZone::AmericaNorthDakotaBeulah => "America/North_Dakota/Beulah", + TimeZone::AmericaNorthDakotaCenter => "America/North_Dakota/Center", + TimeZone::AmericaNorthDakotaNewSalem => "America/North_Dakota/New_Salem", + TimeZone::AmericaNuuk => "America/Nuuk", + TimeZone::AmericaOjinaga => "America/Ojinaga", + TimeZone::AmericaPanama => "America/Panama", + TimeZone::AmericaPangnirtung => "America/Pangnirtung", + TimeZone::AmericaParamaribo => "America/Paramaribo", + TimeZone::AmericaPhoenix => "America/Phoenix", + TimeZone::AmericaPortAuPrince => "America/Port-au-Prince", + TimeZone::AmericaPortOfSpain => "America/Port_of_Spain", + TimeZone::AmericaPortoAcre => "America/Porto_Acre", + TimeZone::AmericaPortoVelho => "America/Porto_Velho", + TimeZone::AmericaPuertoRico => "America/Puerto_Rico", + TimeZone::AmericaPuntaArenas => "America/Punta_Arenas", + TimeZone::AmericaRainyRiver => "America/Rainy_River", + TimeZone::AmericaRankinInlet => "America/Rankin_Inlet", + TimeZone::AmericaRecife => "America/Recife", + TimeZone::AmericaRegina => "America/Regina", + TimeZone::AmericaResolute => "America/Resolute", + TimeZone::AmericaRioBranco => "America/Rio_Branco", + TimeZone::AmericaRosario => "America/Rosario", + TimeZone::AmericaSantaIsabel => "America/Santa_Isabel", + TimeZone::AmericaSantarem => "America/Santarem", + TimeZone::AmericaSantiago => "America/Santiago", + TimeZone::AmericaSantoDomingo => "America/Santo_Domingo", + TimeZone::AmericaSaoPaulo => "America/Sao_Paulo", + TimeZone::AmericaScoresbysund => "America/Scoresbysund", + TimeZone::AmericaShiprock => "America/Shiprock", + TimeZone::AmericaSitka => "America/Sitka", + TimeZone::AmericaStBarthelemy => "America/St_Barthelemy", + TimeZone::AmericaStJohns => "America/St_Johns", + TimeZone::AmericaStKitts => "America/St_Kitts", + TimeZone::AmericaStLucia => "America/St_Lucia", + TimeZone::AmericaStThomas => "America/St_Thomas", + TimeZone::AmericaStVincent => "America/St_Vincent", + TimeZone::AmericaSwiftCurrent => "America/Swift_Current", + TimeZone::AmericaTegucigalpa => "America/Tegucigalpa", + TimeZone::AmericaThule => "America/Thule", + TimeZone::AmericaThunderBay => "America/Thunder_Bay", + TimeZone::AmericaTijuana => "America/Tijuana", + TimeZone::AmericaToronto => "America/Toronto", + TimeZone::AmericaTortola => "America/Tortola", + TimeZone::AmericaVancouver => "America/Vancouver", + TimeZone::AmericaVirgin => "America/Virgin", + TimeZone::AmericaWhitehorse => "America/Whitehorse", + TimeZone::AmericaWinnipeg => "America/Winnipeg", + TimeZone::AmericaYakutat => "America/Yakutat", + TimeZone::AmericaYellowknife => "America/Yellowknife", + TimeZone::AntarcticaCasey => "Antarctica/Casey", + TimeZone::AntarcticaDavis => "Antarctica/Davis", + TimeZone::AntarcticaDumontDUrville => "Antarctica/DumontDUrville", + TimeZone::AntarcticaMacquarie => "Antarctica/Macquarie", + TimeZone::AntarcticaMawson => "Antarctica/Mawson", + TimeZone::AntarcticaMcMurdo => "Antarctica/McMurdo", + TimeZone::AntarcticaPalmer => "Antarctica/Palmer", + TimeZone::AntarcticaRothera => "Antarctica/Rothera", + TimeZone::AntarcticaSouthPole => "Antarctica/South_Pole", + TimeZone::AntarcticaSyowa => "Antarctica/Syowa", + TimeZone::AntarcticaTroll => "Antarctica/Troll", + TimeZone::AntarcticaVostok => "Antarctica/Vostok", + TimeZone::ArcticLongyearbyen => "Arctic/Longyearbyen", + TimeZone::AsiaAden => "Asia/Aden", + TimeZone::AsiaAlmaty => "Asia/Almaty", + TimeZone::AsiaAmman => "Asia/Amman", + TimeZone::AsiaAnadyr => "Asia/Anadyr", + TimeZone::AsiaAqtau => "Asia/Aqtau", + TimeZone::AsiaAqtobe => "Asia/Aqtobe", + TimeZone::AsiaAshgabat => "Asia/Ashgabat", + TimeZone::AsiaAshkhabad => "Asia/Ashkhabad", + TimeZone::AsiaAtyrau => "Asia/Atyrau", + TimeZone::AsiaBaghdad => "Asia/Baghdad", + TimeZone::AsiaBahrain => "Asia/Bahrain", + TimeZone::AsiaBaku => "Asia/Baku", + TimeZone::AsiaBangkok => "Asia/Bangkok", + TimeZone::AsiaBarnaul => "Asia/Barnaul", + TimeZone::AsiaBeirut => "Asia/Beirut", + TimeZone::AsiaBishkek => "Asia/Bishkek", + TimeZone::AsiaBrunei => "Asia/Brunei", + TimeZone::AsiaCalcutta => "Asia/Calcutta", + TimeZone::AsiaChita => "Asia/Chita", + TimeZone::AsiaChoibalsan => "Asia/Choibalsan", + TimeZone::AsiaChongqing => "Asia/Chongqing", + TimeZone::AsiaChungking => "Asia/Chungking", + TimeZone::AsiaColombo => "Asia/Colombo", + TimeZone::AsiaDacca => "Asia/Dacca", + TimeZone::AsiaDamascus => "Asia/Damascus", + TimeZone::AsiaDhaka => "Asia/Dhaka", + TimeZone::AsiaDili => "Asia/Dili", + TimeZone::AsiaDubai => "Asia/Dubai", + TimeZone::AsiaDushanbe => "Asia/Dushanbe", + TimeZone::AsiaFamagusta => "Asia/Famagusta", + TimeZone::AsiaGaza => "Asia/Gaza", + TimeZone::AsiaHarbin => "Asia/Harbin", + TimeZone::AsiaHebron => "Asia/Hebron", + TimeZone::AsiaHoChiMinh => "Asia/Ho_Chi_Minh", + TimeZone::AsiaHongKong => "Asia/Hong_Kong", + TimeZone::AsiaHovd => "Asia/Hovd", + TimeZone::AsiaIrkutsk => "Asia/Irkutsk", + TimeZone::AsiaIstanbul => "Asia/Istanbul", + TimeZone::AsiaJakarta => "Asia/Jakarta", + TimeZone::AsiaJayapura => "Asia/Jayapura", + TimeZone::AsiaJerusalem => "Asia/Jerusalem", + TimeZone::AsiaKabul => "Asia/Kabul", + TimeZone::AsiaKamchatka => "Asia/Kamchatka", + TimeZone::AsiaKarachi => "Asia/Karachi", + TimeZone::AsiaKashgar => "Asia/Kashgar", + TimeZone::AsiaKathmandu => "Asia/Kathmandu", + TimeZone::AsiaKatmandu => "Asia/Katmandu", + TimeZone::AsiaKhandyga => "Asia/Khandyga", + TimeZone::AsiaKolkata => "Asia/Kolkata", + TimeZone::AsiaKrasnoyarsk => "Asia/Krasnoyarsk", + TimeZone::AsiaKualaLumpur => "Asia/Kuala_Lumpur", + TimeZone::AsiaKuching => "Asia/Kuching", + TimeZone::AsiaKuwait => "Asia/Kuwait", + TimeZone::AsiaMacao => "Asia/Macao", + TimeZone::AsiaMacau => "Asia/Macau", + TimeZone::AsiaMagadan => "Asia/Magadan", + TimeZone::AsiaMakassar => "Asia/Makassar", + TimeZone::AsiaManila => "Asia/Manila", + TimeZone::AsiaMuscat => "Asia/Muscat", + TimeZone::AsiaNicosia => "Asia/Nicosia", + TimeZone::AsiaNovokuznetsk => "Asia/Novokuznetsk", + TimeZone::AsiaNovosibirsk => "Asia/Novosibirsk", + TimeZone::AsiaOmsk => "Asia/Omsk", + TimeZone::AsiaOral => "Asia/Oral", + TimeZone::AsiaPhnomPenh => "Asia/Phnom_Penh", + TimeZone::AsiaPontianak => "Asia/Pontianak", + TimeZone::AsiaPyongyang => "Asia/Pyongyang", + TimeZone::AsiaQatar => "Asia/Qatar", + TimeZone::AsiaQostanay => "Asia/Qostanay", + TimeZone::AsiaQyzylorda => "Asia/Qyzylorda", + TimeZone::AsiaRangoon => "Asia/Rangoon", + TimeZone::AsiaRiyadh => "Asia/Riyadh", + TimeZone::AsiaSaigon => "Asia/Saigon", + TimeZone::AsiaSakhalin => "Asia/Sakhalin", + TimeZone::AsiaSamarkand => "Asia/Samarkand", + TimeZone::AsiaSeoul => "Asia/Seoul", + TimeZone::AsiaShanghai => "Asia/Shanghai", + TimeZone::AsiaSingapore => "Asia/Singapore", + TimeZone::AsiaSrednekolymsk => "Asia/Srednekolymsk", + TimeZone::AsiaTaipei => "Asia/Taipei", + TimeZone::AsiaTashkent => "Asia/Tashkent", + TimeZone::AsiaTbilisi => "Asia/Tbilisi", + TimeZone::AsiaTehran => "Asia/Tehran", + TimeZone::AsiaTelAviv => "Asia/Tel_Aviv", + TimeZone::AsiaThimbu => "Asia/Thimbu", + TimeZone::AsiaThimphu => "Asia/Thimphu", + TimeZone::AsiaTokyo => "Asia/Tokyo", + TimeZone::AsiaTomsk => "Asia/Tomsk", + TimeZone::AsiaUjungPandang => "Asia/Ujung_Pandang", + TimeZone::AsiaUlaanbaatar => "Asia/Ulaanbaatar", + TimeZone::AsiaUlanBator => "Asia/Ulan_Bator", + TimeZone::AsiaUrumqi => "Asia/Urumqi", + TimeZone::AsiaUstNera => "Asia/Ust-Nera", + TimeZone::AsiaVientiane => "Asia/Vientiane", + TimeZone::AsiaVladivostok => "Asia/Vladivostok", + TimeZone::AsiaYakutsk => "Asia/Yakutsk", + TimeZone::AsiaYangon => "Asia/Yangon", + TimeZone::AsiaYekaterinburg => "Asia/Yekaterinburg", + TimeZone::AsiaYerevan => "Asia/Yerevan", + TimeZone::AtlanticAzores => "Atlantic/Azores", + TimeZone::AtlanticBermuda => "Atlantic/Bermuda", + TimeZone::AtlanticCanary => "Atlantic/Canary", + TimeZone::AtlanticCapeVerde => "Atlantic/Cape_Verde", + TimeZone::AtlanticFaeroe => "Atlantic/Faeroe", + TimeZone::AtlanticFaroe => "Atlantic/Faroe", + TimeZone::AtlanticJanMayen => "Atlantic/Jan_Mayen", + TimeZone::AtlanticMadeira => "Atlantic/Madeira", + TimeZone::AtlanticReykjavik => "Atlantic/Reykjavik", + TimeZone::AtlanticSouthGeorgia => "Atlantic/South_Georgia", + TimeZone::AtlanticStHelena => "Atlantic/St_Helena", + TimeZone::AtlanticStanley => "Atlantic/Stanley", + TimeZone::AustraliaACT => "Australia/ACT", + TimeZone::AustraliaAdelaide => "Australia/Adelaide", + TimeZone::AustraliaBrisbane => "Australia/Brisbane", + TimeZone::AustraliaBrokenHill => "Australia/Broken_Hill", + TimeZone::AustraliaCanberra => "Australia/Canberra", + TimeZone::AustraliaCurrie => "Australia/Currie", + TimeZone::AustraliaDarwin => "Australia/Darwin", + TimeZone::AustraliaEucla => "Australia/Eucla", + TimeZone::AustraliaHobart => "Australia/Hobart", + TimeZone::AustraliaLHI => "Australia/LHI", + TimeZone::AustraliaLindeman => "Australia/Lindeman", + TimeZone::AustraliaLordHowe => "Australia/Lord_Howe", + TimeZone::AustraliaMelbourne => "Australia/Melbourne", + TimeZone::AustraliaNSW => "Australia/NSW", + TimeZone::AustraliaNorth => "Australia/North", + TimeZone::AustraliaPerth => "Australia/Perth", + TimeZone::AustraliaQueensland => "Australia/Queensland", + TimeZone::AustraliaSouth => "Australia/South", + TimeZone::AustraliaSydney => "Australia/Sydney", + TimeZone::AustraliaTasmania => "Australia/Tasmania", + TimeZone::AustraliaVictoria => "Australia/Victoria", + TimeZone::AustraliaWest => "Australia/West", + TimeZone::AustraliaYancowinna => "Australia/Yancowinna", + TimeZone::BrazilAcre => "Brazil/Acre", + TimeZone::BrazilDeNoronha => "Brazil/DeNoronha", + TimeZone::BrazilEast => "Brazil/East", + TimeZone::BrazilWest => "Brazil/West", + TimeZone::CET => "CET", + TimeZone::CST6CDT => "CST6CDT", + TimeZone::CanadaAtlantic => "Canada/Atlantic", + TimeZone::CanadaCentral => "Canada/Central", + TimeZone::CanadaEastern => "Canada/Eastern", + TimeZone::CanadaMountain => "Canada/Mountain", + TimeZone::CanadaNewfoundland => "Canada/Newfoundland", + TimeZone::CanadaPacific => "Canada/Pacific", + TimeZone::CanadaSaskatchewan => "Canada/Saskatchewan", + TimeZone::CanadaYukon => "Canada/Yukon", + TimeZone::ChileContinental => "Chile/Continental", + TimeZone::ChileEasterIsland => "Chile/EasterIsland", + TimeZone::Cuba => "Cuba", + TimeZone::EET => "EET", + TimeZone::EST => "EST", + TimeZone::EST5EDT => "EST5EDT", + TimeZone::Egypt => "Egypt", + TimeZone::Eire => "Eire", + TimeZone::EtcGMT => "Etc/GMT", + TimeZone::EtcGMTPlus0 => "Etc/GMT+0", + TimeZone::EtcGMTPlus1 => "Etc/GMT+1", + TimeZone::EtcGMTPlus10 => "Etc/GMT+10", + TimeZone::EtcGMTPlus11 => "Etc/GMT+11", + TimeZone::EtcGMTPlus12 => "Etc/GMT+12", + TimeZone::EtcGMTPlus2 => "Etc/GMT+2", + TimeZone::EtcGMTPlus3 => "Etc/GMT+3", + TimeZone::EtcGMTPlus4 => "Etc/GMT+4", + TimeZone::EtcGMTPlus5 => "Etc/GMT+5", + TimeZone::EtcGMTPlus6 => "Etc/GMT+6", + TimeZone::EtcGMTPlus7 => "Etc/GMT+7", + TimeZone::EtcGMTPlus8 => "Etc/GMT+8", + TimeZone::EtcGMTPlus9 => "Etc/GMT+9", + TimeZone::EtcGMTMinus0 => "Etc/GMT-0", + TimeZone::EtcGMTMinus1 => "Etc/GMT-1", + TimeZone::EtcGMTMinus10 => "Etc/GMT-10", + TimeZone::EtcGMTMinus11 => "Etc/GMT-11", + TimeZone::EtcGMTMinus12 => "Etc/GMT-12", + TimeZone::EtcGMTMinus13 => "Etc/GMT-13", + TimeZone::EtcGMTMinus14 => "Etc/GMT-14", + TimeZone::EtcGMTMinus2 => "Etc/GMT-2", + TimeZone::EtcGMTMinus3 => "Etc/GMT-3", + TimeZone::EtcGMTMinus4 => "Etc/GMT-4", + TimeZone::EtcGMTMinus5 => "Etc/GMT-5", + TimeZone::EtcGMTMinus6 => "Etc/GMT-6", + TimeZone::EtcGMTMinus7 => "Etc/GMT-7", + TimeZone::EtcGMTMinus8 => "Etc/GMT-8", + TimeZone::EtcGMTMinus9 => "Etc/GMT-9", + TimeZone::EtcGMT0 => "Etc/GMT0", + TimeZone::EtcGreenwich => "Etc/Greenwich", + TimeZone::EtcUCT => "Etc/UCT", + TimeZone::EtcUTC => "Etc/UTC", + TimeZone::EtcUniversal => "Etc/Universal", + TimeZone::EtcZulu => "Etc/Zulu", + TimeZone::EuropeAmsterdam => "Europe/Amsterdam", + TimeZone::EuropeAndorra => "Europe/Andorra", + TimeZone::EuropeAstrakhan => "Europe/Astrakhan", + TimeZone::EuropeAthens => "Europe/Athens", + TimeZone::EuropeBelfast => "Europe/Belfast", + TimeZone::EuropeBelgrade => "Europe/Belgrade", + TimeZone::EuropeBerlin => "Europe/Berlin", + TimeZone::EuropeBratislava => "Europe/Bratislava", + TimeZone::EuropeBrussels => "Europe/Brussels", + TimeZone::EuropeBucharest => "Europe/Bucharest", + TimeZone::EuropeBudapest => "Europe/Budapest", + TimeZone::EuropeBusingen => "Europe/Busingen", + TimeZone::EuropeChisinau => "Europe/Chisinau", + TimeZone::EuropeCopenhagen => "Europe/Copenhagen", + TimeZone::EuropeDublin => "Europe/Dublin", + TimeZone::EuropeGibraltar => "Europe/Gibraltar", + TimeZone::EuropeGuernsey => "Europe/Guernsey", + TimeZone::EuropeHelsinki => "Europe/Helsinki", + TimeZone::EuropeIsleOfMan => "Europe/Isle_of_Man", + TimeZone::EuropeIstanbul => "Europe/Istanbul", + TimeZone::EuropeJersey => "Europe/Jersey", + TimeZone::EuropeKaliningrad => "Europe/Kaliningrad", + TimeZone::EuropeKiev => "Europe/Kiev", + TimeZone::EuropeKirov => "Europe/Kirov", + TimeZone::EuropeKyiv => "Europe/Kyiv", + TimeZone::EuropeLisbon => "Europe/Lisbon", + TimeZone::EuropeLjubljana => "Europe/Ljubljana", + TimeZone::EuropeLondon => "Europe/London", + TimeZone::EuropeLuxembourg => "Europe/Luxembourg", + TimeZone::EuropeMadrid => "Europe/Madrid", + TimeZone::EuropeMalta => "Europe/Malta", + TimeZone::EuropeMariehamn => "Europe/Mariehamn", + TimeZone::EuropeMinsk => "Europe/Minsk", + TimeZone::EuropeMonaco => "Europe/Monaco", + TimeZone::EuropeMoscow => "Europe/Moscow", + TimeZone::EuropeNicosia => "Europe/Nicosia", + TimeZone::EuropeOslo => "Europe/Oslo", + TimeZone::EuropeParis => "Europe/Paris", + TimeZone::EuropePodgorica => "Europe/Podgorica", + TimeZone::EuropePrague => "Europe/Prague", + TimeZone::EuropeRiga => "Europe/Riga", + TimeZone::EuropeRome => "Europe/Rome", + TimeZone::EuropeSamara => "Europe/Samara", + TimeZone::EuropeSanMarino => "Europe/San_Marino", + TimeZone::EuropeSarajevo => "Europe/Sarajevo", + TimeZone::EuropeSaratov => "Europe/Saratov", + TimeZone::EuropeSimferopol => "Europe/Simferopol", + TimeZone::EuropeSkopje => "Europe/Skopje", + TimeZone::EuropeSofia => "Europe/Sofia", + TimeZone::EuropeStockholm => "Europe/Stockholm", + TimeZone::EuropeTallinn => "Europe/Tallinn", + TimeZone::EuropeTirane => "Europe/Tirane", + TimeZone::EuropeTiraspol => "Europe/Tiraspol", + TimeZone::EuropeUlyanovsk => "Europe/Ulyanovsk", + TimeZone::EuropeUzhgorod => "Europe/Uzhgorod", + TimeZone::EuropeVaduz => "Europe/Vaduz", + TimeZone::EuropeVatican => "Europe/Vatican", + TimeZone::EuropeVienna => "Europe/Vienna", + TimeZone::EuropeVilnius => "Europe/Vilnius", + TimeZone::EuropeVolgograd => "Europe/Volgograd", + TimeZone::EuropeWarsaw => "Europe/Warsaw", + TimeZone::EuropeZagreb => "Europe/Zagreb", + TimeZone::EuropeZaporozhye => "Europe/Zaporozhye", + TimeZone::EuropeZurich => "Europe/Zurich", + TimeZone::Factory => "Factory", + TimeZone::GB => "GB", + TimeZone::GBEire => "GB-Eire", + TimeZone::GMT => "GMT", + TimeZone::GMTPlus0 => "GMT+0", + TimeZone::GMTMinus0 => "GMT-0", + TimeZone::GMT0 => "GMT0", + TimeZone::Greenwich => "Greenwich", + TimeZone::HST => "HST", + TimeZone::Hongkong => "Hongkong", + TimeZone::Iceland => "Iceland", + TimeZone::IndianAntananarivo => "Indian/Antananarivo", + TimeZone::IndianChagos => "Indian/Chagos", + TimeZone::IndianChristmas => "Indian/Christmas", + TimeZone::IndianCocos => "Indian/Cocos", + TimeZone::IndianComoro => "Indian/Comoro", + TimeZone::IndianKerguelen => "Indian/Kerguelen", + TimeZone::IndianMahe => "Indian/Mahe", + TimeZone::IndianMaldives => "Indian/Maldives", + TimeZone::IndianMauritius => "Indian/Mauritius", + TimeZone::IndianMayotte => "Indian/Mayotte", + TimeZone::IndianReunion => "Indian/Reunion", + TimeZone::Iran => "Iran", + TimeZone::Israel => "Israel", + TimeZone::Jamaica => "Jamaica", + TimeZone::Japan => "Japan", + TimeZone::Kwajalein => "Kwajalein", + TimeZone::Libya => "Libya", + TimeZone::MET => "MET", + TimeZone::MST => "MST", + TimeZone::MST7MDT => "MST7MDT", + TimeZone::MexicoBajaNorte => "Mexico/BajaNorte", + TimeZone::MexicoBajaSur => "Mexico/BajaSur", + TimeZone::MexicoGeneral => "Mexico/General", + TimeZone::NZ => "NZ", + TimeZone::NZCHAT => "NZ-CHAT", + TimeZone::Navajo => "Navajo", + TimeZone::PRC => "PRC", + TimeZone::PST8PDT => "PST8PDT", + TimeZone::PacificApia => "Pacific/Apia", + TimeZone::PacificAuckland => "Pacific/Auckland", + TimeZone::PacificBougainville => "Pacific/Bougainville", + TimeZone::PacificChatham => "Pacific/Chatham", + TimeZone::PacificChuuk => "Pacific/Chuuk", + TimeZone::PacificEaster => "Pacific/Easter", + TimeZone::PacificEfate => "Pacific/Efate", + TimeZone::PacificEnderbury => "Pacific/Enderbury", + TimeZone::PacificFakaofo => "Pacific/Fakaofo", + TimeZone::PacificFiji => "Pacific/Fiji", + TimeZone::PacificFunafuti => "Pacific/Funafuti", + TimeZone::PacificGalapagos => "Pacific/Galapagos", + TimeZone::PacificGambier => "Pacific/Gambier", + TimeZone::PacificGuadalcanal => "Pacific/Guadalcanal", + TimeZone::PacificGuam => "Pacific/Guam", + TimeZone::PacificHonolulu => "Pacific/Honolulu", + TimeZone::PacificJohnston => "Pacific/Johnston", + TimeZone::PacificKanton => "Pacific/Kanton", + TimeZone::PacificKiritimati => "Pacific/Kiritimati", + TimeZone::PacificKosrae => "Pacific/Kosrae", + TimeZone::PacificKwajalein => "Pacific/Kwajalein", + TimeZone::PacificMajuro => "Pacific/Majuro", + TimeZone::PacificMarquesas => "Pacific/Marquesas", + TimeZone::PacificMidway => "Pacific/Midway", + TimeZone::PacificNauru => "Pacific/Nauru", + TimeZone::PacificNiue => "Pacific/Niue", + TimeZone::PacificNorfolk => "Pacific/Norfolk", + TimeZone::PacificNoumea => "Pacific/Noumea", + TimeZone::PacificPagoPago => "Pacific/Pago_Pago", + TimeZone::PacificPalau => "Pacific/Palau", + TimeZone::PacificPitcairn => "Pacific/Pitcairn", + TimeZone::PacificPohnpei => "Pacific/Pohnpei", + TimeZone::PacificPonape => "Pacific/Ponape", + TimeZone::PacificPortMoresby => "Pacific/Port_Moresby", + TimeZone::PacificRarotonga => "Pacific/Rarotonga", + TimeZone::PacificSaipan => "Pacific/Saipan", + TimeZone::PacificSamoa => "Pacific/Samoa", + TimeZone::PacificTahiti => "Pacific/Tahiti", + TimeZone::PacificTarawa => "Pacific/Tarawa", + TimeZone::PacificTongatapu => "Pacific/Tongatapu", + TimeZone::PacificTruk => "Pacific/Truk", + TimeZone::PacificWake => "Pacific/Wake", + TimeZone::PacificWallis => "Pacific/Wallis", + TimeZone::PacificYap => "Pacific/Yap", + TimeZone::Poland => "Poland", + TimeZone::Portugal => "Portugal", + TimeZone::ROC => "ROC", + TimeZone::ROK => "ROK", + TimeZone::Singapore => "Singapore", + TimeZone::Turkey => "Turkey", + TimeZone::UCT => "UCT", + TimeZone::USAlaska => "US/Alaska", + TimeZone::USAleutian => "US/Aleutian", + TimeZone::USArizona => "US/Arizona", + TimeZone::USCentral => "US/Central", + TimeZone::USEastIndiana => "US/East-Indiana", + TimeZone::USEastern => "US/Eastern", + TimeZone::USHawaii => "US/Hawaii", + TimeZone::USIndianaStarke => "US/Indiana-Starke", + TimeZone::USMichigan => "US/Michigan", + TimeZone::USMountain => "US/Mountain", + TimeZone::USPacific => "US/Pacific", + TimeZone::USSamoa => "US/Samoa", + TimeZone::UTC => "UTC", + TimeZone::Universal => "Universal", + TimeZone::WSU => "W-SU", + TimeZone::WET => "WET", + TimeZone::Zulu => "Zulu", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TimeZone::AfricaAbidjan), + 1 => Some(TimeZone::AfricaAccra), + 2 => Some(TimeZone::AfricaAddisAbaba), + 3 => Some(TimeZone::AfricaAlgiers), + 4 => Some(TimeZone::AfricaAsmara), + 5 => Some(TimeZone::AfricaAsmera), + 6 => Some(TimeZone::AfricaBamako), + 7 => Some(TimeZone::AfricaBangui), + 8 => Some(TimeZone::AfricaBanjul), + 9 => Some(TimeZone::AfricaBissau), + 10 => Some(TimeZone::AfricaBlantyre), + 11 => Some(TimeZone::AfricaBrazzaville), + 12 => Some(TimeZone::AfricaBujumbura), + 13 => Some(TimeZone::AfricaCairo), + 14 => Some(TimeZone::AfricaCasablanca), + 15 => Some(TimeZone::AfricaCeuta), + 16 => Some(TimeZone::AfricaConakry), + 17 => Some(TimeZone::AfricaDakar), + 18 => Some(TimeZone::AfricaDarEsSalaam), + 19 => Some(TimeZone::AfricaDjibouti), + 20 => Some(TimeZone::AfricaDouala), + 21 => Some(TimeZone::AfricaElAaiun), + 22 => Some(TimeZone::AfricaFreetown), + 23 => Some(TimeZone::AfricaGaborone), + 24 => Some(TimeZone::AfricaHarare), + 25 => Some(TimeZone::AfricaJohannesburg), + 26 => Some(TimeZone::AfricaJuba), + 27 => Some(TimeZone::AfricaKampala), + 28 => Some(TimeZone::AfricaKhartoum), + 29 => Some(TimeZone::AfricaKigali), + 30 => Some(TimeZone::AfricaKinshasa), + 31 => Some(TimeZone::AfricaLagos), + 32 => Some(TimeZone::AfricaLibreville), + 33 => Some(TimeZone::AfricaLome), + 34 => Some(TimeZone::AfricaLuanda), + 35 => Some(TimeZone::AfricaLubumbashi), + 36 => Some(TimeZone::AfricaLusaka), + 37 => Some(TimeZone::AfricaMalabo), + 38 => Some(TimeZone::AfricaMaputo), + 39 => Some(TimeZone::AfricaMaseru), + 40 => Some(TimeZone::AfricaMbabane), + 41 => Some(TimeZone::AfricaMogadishu), + 42 => Some(TimeZone::AfricaMonrovia), + 43 => Some(TimeZone::AfricaNairobi), + 44 => Some(TimeZone::AfricaNdjamena), + 45 => Some(TimeZone::AfricaNiamey), + 46 => Some(TimeZone::AfricaNouakchott), + 47 => Some(TimeZone::AfricaOuagadougou), + 48 => Some(TimeZone::AfricaPortoNovo), + 49 => Some(TimeZone::AfricaSaoTome), + 50 => Some(TimeZone::AfricaTimbuktu), + 51 => Some(TimeZone::AfricaTripoli), + 52 => Some(TimeZone::AfricaTunis), + 53 => Some(TimeZone::AfricaWindhoek), + 54 => Some(TimeZone::AmericaAdak), + 55 => Some(TimeZone::AmericaAnchorage), + 56 => Some(TimeZone::AmericaAnguilla), + 57 => Some(TimeZone::AmericaAntigua), + 58 => Some(TimeZone::AmericaAraguaina), + 59 => Some(TimeZone::AmericaArgentinaBuenosAires), + 60 => Some(TimeZone::AmericaArgentinaCatamarca), + 61 => Some(TimeZone::AmericaArgentinaComodRivadavia), + 62 => Some(TimeZone::AmericaArgentinaCordoba), + 63 => Some(TimeZone::AmericaArgentinaJujuy), + 64 => Some(TimeZone::AmericaArgentinaLaRioja), + 65 => Some(TimeZone::AmericaArgentinaMendoza), + 66 => Some(TimeZone::AmericaArgentinaRioGallegos), + 67 => Some(TimeZone::AmericaArgentinaSalta), + 68 => Some(TimeZone::AmericaArgentinaSanJuan), + 69 => Some(TimeZone::AmericaArgentinaSanLuis), + 70 => Some(TimeZone::AmericaArgentinaTucuman), + 71 => Some(TimeZone::AmericaArgentinaUshuaia), + 72 => Some(TimeZone::AmericaAruba), + 73 => Some(TimeZone::AmericaAsuncion), + 74 => Some(TimeZone::AmericaAtikokan), + 75 => Some(TimeZone::AmericaAtka), + 76 => Some(TimeZone::AmericaBahia), + 77 => Some(TimeZone::AmericaBahiaBanderas), + 78 => Some(TimeZone::AmericaBarbados), + 79 => Some(TimeZone::AmericaBelem), + 80 => Some(TimeZone::AmericaBelize), + 81 => Some(TimeZone::AmericaBlancSablon), + 82 => Some(TimeZone::AmericaBoaVista), + 83 => Some(TimeZone::AmericaBogota), + 84 => Some(TimeZone::AmericaBoise), + 85 => Some(TimeZone::AmericaBuenosAires), + 86 => Some(TimeZone::AmericaCambridgeBay), + 87 => Some(TimeZone::AmericaCampoGrande), + 88 => Some(TimeZone::AmericaCancun), + 89 => Some(TimeZone::AmericaCaracas), + 90 => Some(TimeZone::AmericaCatamarca), + 91 => Some(TimeZone::AmericaCayenne), + 92 => Some(TimeZone::AmericaCayman), + 93 => Some(TimeZone::AmericaChicago), + 94 => Some(TimeZone::AmericaChihuahua), + 95 => Some(TimeZone::AmericaCiudadJuarez), + 96 => Some(TimeZone::AmericaCoralHarbour), + 97 => Some(TimeZone::AmericaCordoba), + 98 => Some(TimeZone::AmericaCostaRica), + 99 => Some(TimeZone::AmericaCoyhaique), + 100 => Some(TimeZone::AmericaCreston), + 101 => Some(TimeZone::AmericaCuiaba), + 102 => Some(TimeZone::AmericaCuracao), + 103 => Some(TimeZone::AmericaDanmarkshavn), + 104 => Some(TimeZone::AmericaDawson), + 105 => Some(TimeZone::AmericaDawsonCreek), + 106 => Some(TimeZone::AmericaDenver), + 107 => Some(TimeZone::AmericaDetroit), + 108 => Some(TimeZone::AmericaDominica), + 109 => Some(TimeZone::AmericaEdmonton), + 110 => Some(TimeZone::AmericaEirunepe), + 111 => Some(TimeZone::AmericaElSalvador), + 112 => Some(TimeZone::AmericaEnsenada), + 113 => Some(TimeZone::AmericaFortNelson), + 114 => Some(TimeZone::AmericaFortWayne), + 115 => Some(TimeZone::AmericaFortaleza), + 116 => Some(TimeZone::AmericaGlaceBay), + 117 => Some(TimeZone::AmericaGodthab), + 118 => Some(TimeZone::AmericaGooseBay), + 119 => Some(TimeZone::AmericaGrandTurk), + 120 => Some(TimeZone::AmericaGrenada), + 121 => Some(TimeZone::AmericaGuadeloupe), + 122 => Some(TimeZone::AmericaGuatemala), + 123 => Some(TimeZone::AmericaGuayaquil), + 124 => Some(TimeZone::AmericaGuyana), + 125 => Some(TimeZone::AmericaHalifax), + 126 => Some(TimeZone::AmericaHavana), + 127 => Some(TimeZone::AmericaHermosillo), + 128 => Some(TimeZone::AmericaIndianaIndianapolis), + 129 => Some(TimeZone::AmericaIndianaKnox), + 130 => Some(TimeZone::AmericaIndianaMarengo), + 131 => Some(TimeZone::AmericaIndianaPetersburg), + 132 => Some(TimeZone::AmericaIndianaTellCity), + 133 => Some(TimeZone::AmericaIndianaVevay), + 134 => Some(TimeZone::AmericaIndianaVincennes), + 135 => Some(TimeZone::AmericaIndianaWinamac), + 136 => Some(TimeZone::AmericaIndianapolis), + 137 => Some(TimeZone::AmericaInuvik), + 138 => Some(TimeZone::AmericaIqaluit), + 139 => Some(TimeZone::AmericaJamaica), + 140 => Some(TimeZone::AmericaJujuy), + 141 => Some(TimeZone::AmericaJuneau), + 142 => Some(TimeZone::AmericaKentuckyLouisville), + 143 => Some(TimeZone::AmericaKentuckyMonticello), + 144 => Some(TimeZone::AmericaKnoxIN), + 145 => Some(TimeZone::AmericaKralendijk), + 146 => Some(TimeZone::AmericaLaPaz), + 147 => Some(TimeZone::AmericaLima), + 148 => Some(TimeZone::AmericaLosAngeles), + 149 => Some(TimeZone::AmericaLouisville), + 150 => Some(TimeZone::AmericaLowerPrinces), + 151 => Some(TimeZone::AmericaMaceio), + 152 => Some(TimeZone::AmericaManagua), + 153 => Some(TimeZone::AmericaManaus), + 154 => Some(TimeZone::AmericaMarigot), + 155 => Some(TimeZone::AmericaMartinique), + 156 => Some(TimeZone::AmericaMatamoros), + 157 => Some(TimeZone::AmericaMazatlan), + 158 => Some(TimeZone::AmericaMendoza), + 159 => Some(TimeZone::AmericaMenominee), + 160 => Some(TimeZone::AmericaMerida), + 161 => Some(TimeZone::AmericaMetlakatla), + 162 => Some(TimeZone::AmericaMexicoCity), + 163 => Some(TimeZone::AmericaMiquelon), + 164 => Some(TimeZone::AmericaMoncton), + 165 => Some(TimeZone::AmericaMonterrey), + 166 => Some(TimeZone::AmericaMontevideo), + 167 => Some(TimeZone::AmericaMontreal), + 168 => Some(TimeZone::AmericaMontserrat), + 169 => Some(TimeZone::AmericaNassau), + 170 => Some(TimeZone::AmericaNewYork), + 171 => Some(TimeZone::AmericaNipigon), + 172 => Some(TimeZone::AmericaNome), + 173 => Some(TimeZone::AmericaNoronha), + 174 => Some(TimeZone::AmericaNorthDakotaBeulah), + 175 => Some(TimeZone::AmericaNorthDakotaCenter), + 176 => Some(TimeZone::AmericaNorthDakotaNewSalem), + 177 => Some(TimeZone::AmericaNuuk), + 178 => Some(TimeZone::AmericaOjinaga), + 179 => Some(TimeZone::AmericaPanama), + 180 => Some(TimeZone::AmericaPangnirtung), + 181 => Some(TimeZone::AmericaParamaribo), + 182 => Some(TimeZone::AmericaPhoenix), + 183 => Some(TimeZone::AmericaPortAuPrince), + 184 => Some(TimeZone::AmericaPortOfSpain), + 185 => Some(TimeZone::AmericaPortoAcre), + 186 => Some(TimeZone::AmericaPortoVelho), + 187 => Some(TimeZone::AmericaPuertoRico), + 188 => Some(TimeZone::AmericaPuntaArenas), + 189 => Some(TimeZone::AmericaRainyRiver), + 190 => Some(TimeZone::AmericaRankinInlet), + 191 => Some(TimeZone::AmericaRecife), + 192 => Some(TimeZone::AmericaRegina), + 193 => Some(TimeZone::AmericaResolute), + 194 => Some(TimeZone::AmericaRioBranco), + 195 => Some(TimeZone::AmericaRosario), + 196 => Some(TimeZone::AmericaSantaIsabel), + 197 => Some(TimeZone::AmericaSantarem), + 198 => Some(TimeZone::AmericaSantiago), + 199 => Some(TimeZone::AmericaSantoDomingo), + 200 => Some(TimeZone::AmericaSaoPaulo), + 201 => Some(TimeZone::AmericaScoresbysund), + 202 => Some(TimeZone::AmericaShiprock), + 203 => Some(TimeZone::AmericaSitka), + 204 => Some(TimeZone::AmericaStBarthelemy), + 205 => Some(TimeZone::AmericaStJohns), + 206 => Some(TimeZone::AmericaStKitts), + 207 => Some(TimeZone::AmericaStLucia), + 208 => Some(TimeZone::AmericaStThomas), + 209 => Some(TimeZone::AmericaStVincent), + 210 => Some(TimeZone::AmericaSwiftCurrent), + 211 => Some(TimeZone::AmericaTegucigalpa), + 212 => Some(TimeZone::AmericaThule), + 213 => Some(TimeZone::AmericaThunderBay), + 214 => Some(TimeZone::AmericaTijuana), + 215 => Some(TimeZone::AmericaToronto), + 216 => Some(TimeZone::AmericaTortola), + 217 => Some(TimeZone::AmericaVancouver), + 218 => Some(TimeZone::AmericaVirgin), + 219 => Some(TimeZone::AmericaWhitehorse), + 220 => Some(TimeZone::AmericaWinnipeg), + 221 => Some(TimeZone::AmericaYakutat), + 222 => Some(TimeZone::AmericaYellowknife), + 223 => Some(TimeZone::AntarcticaCasey), + 224 => Some(TimeZone::AntarcticaDavis), + 225 => Some(TimeZone::AntarcticaDumontDUrville), + 226 => Some(TimeZone::AntarcticaMacquarie), + 227 => Some(TimeZone::AntarcticaMawson), + 228 => Some(TimeZone::AntarcticaMcMurdo), + 229 => Some(TimeZone::AntarcticaPalmer), + 230 => Some(TimeZone::AntarcticaRothera), + 231 => Some(TimeZone::AntarcticaSouthPole), + 232 => Some(TimeZone::AntarcticaSyowa), + 233 => Some(TimeZone::AntarcticaTroll), + 234 => Some(TimeZone::AntarcticaVostok), + 235 => Some(TimeZone::ArcticLongyearbyen), + 236 => Some(TimeZone::AsiaAden), + 237 => Some(TimeZone::AsiaAlmaty), + 238 => Some(TimeZone::AsiaAmman), + 239 => Some(TimeZone::AsiaAnadyr), + 240 => Some(TimeZone::AsiaAqtau), + 241 => Some(TimeZone::AsiaAqtobe), + 242 => Some(TimeZone::AsiaAshgabat), + 243 => Some(TimeZone::AsiaAshkhabad), + 244 => Some(TimeZone::AsiaAtyrau), + 245 => Some(TimeZone::AsiaBaghdad), + 246 => Some(TimeZone::AsiaBahrain), + 247 => Some(TimeZone::AsiaBaku), + 248 => Some(TimeZone::AsiaBangkok), + 249 => Some(TimeZone::AsiaBarnaul), + 250 => Some(TimeZone::AsiaBeirut), + 251 => Some(TimeZone::AsiaBishkek), + 252 => Some(TimeZone::AsiaBrunei), + 253 => Some(TimeZone::AsiaCalcutta), + 254 => Some(TimeZone::AsiaChita), + 255 => Some(TimeZone::AsiaChoibalsan), + 256 => Some(TimeZone::AsiaChongqing), + 257 => Some(TimeZone::AsiaChungking), + 258 => Some(TimeZone::AsiaColombo), + 259 => Some(TimeZone::AsiaDacca), + 260 => Some(TimeZone::AsiaDamascus), + 261 => Some(TimeZone::AsiaDhaka), + 262 => Some(TimeZone::AsiaDili), + 263 => Some(TimeZone::AsiaDubai), + 264 => Some(TimeZone::AsiaDushanbe), + 265 => Some(TimeZone::AsiaFamagusta), + 266 => Some(TimeZone::AsiaGaza), + 267 => Some(TimeZone::AsiaHarbin), + 268 => Some(TimeZone::AsiaHebron), + 269 => Some(TimeZone::AsiaHoChiMinh), + 270 => Some(TimeZone::AsiaHongKong), + 271 => Some(TimeZone::AsiaHovd), + 272 => Some(TimeZone::AsiaIrkutsk), + 273 => Some(TimeZone::AsiaIstanbul), + 274 => Some(TimeZone::AsiaJakarta), + 275 => Some(TimeZone::AsiaJayapura), + 276 => Some(TimeZone::AsiaJerusalem), + 277 => Some(TimeZone::AsiaKabul), + 278 => Some(TimeZone::AsiaKamchatka), + 279 => Some(TimeZone::AsiaKarachi), + 280 => Some(TimeZone::AsiaKashgar), + 281 => Some(TimeZone::AsiaKathmandu), + 282 => Some(TimeZone::AsiaKatmandu), + 283 => Some(TimeZone::AsiaKhandyga), + 284 => Some(TimeZone::AsiaKolkata), + 285 => Some(TimeZone::AsiaKrasnoyarsk), + 286 => Some(TimeZone::AsiaKualaLumpur), + 287 => Some(TimeZone::AsiaKuching), + 288 => Some(TimeZone::AsiaKuwait), + 289 => Some(TimeZone::AsiaMacao), + 290 => Some(TimeZone::AsiaMacau), + 291 => Some(TimeZone::AsiaMagadan), + 292 => Some(TimeZone::AsiaMakassar), + 293 => Some(TimeZone::AsiaManila), + 294 => Some(TimeZone::AsiaMuscat), + 295 => Some(TimeZone::AsiaNicosia), + 296 => Some(TimeZone::AsiaNovokuznetsk), + 297 => Some(TimeZone::AsiaNovosibirsk), + 298 => Some(TimeZone::AsiaOmsk), + 299 => Some(TimeZone::AsiaOral), + 300 => Some(TimeZone::AsiaPhnomPenh), + 301 => Some(TimeZone::AsiaPontianak), + 302 => Some(TimeZone::AsiaPyongyang), + 303 => Some(TimeZone::AsiaQatar), + 304 => Some(TimeZone::AsiaQostanay), + 305 => Some(TimeZone::AsiaQyzylorda), + 306 => Some(TimeZone::AsiaRangoon), + 307 => Some(TimeZone::AsiaRiyadh), + 308 => Some(TimeZone::AsiaSaigon), + 309 => Some(TimeZone::AsiaSakhalin), + 310 => Some(TimeZone::AsiaSamarkand), + 311 => Some(TimeZone::AsiaSeoul), + 312 => Some(TimeZone::AsiaShanghai), + 313 => Some(TimeZone::AsiaSingapore), + 314 => Some(TimeZone::AsiaSrednekolymsk), + 315 => Some(TimeZone::AsiaTaipei), + 316 => Some(TimeZone::AsiaTashkent), + 317 => Some(TimeZone::AsiaTbilisi), + 318 => Some(TimeZone::AsiaTehran), + 319 => Some(TimeZone::AsiaTelAviv), + 320 => Some(TimeZone::AsiaThimbu), + 321 => Some(TimeZone::AsiaThimphu), + 322 => Some(TimeZone::AsiaTokyo), + 323 => Some(TimeZone::AsiaTomsk), + 324 => Some(TimeZone::AsiaUjungPandang), + 325 => Some(TimeZone::AsiaUlaanbaatar), + 326 => Some(TimeZone::AsiaUlanBator), + 327 => Some(TimeZone::AsiaUrumqi), + 328 => Some(TimeZone::AsiaUstNera), + 329 => Some(TimeZone::AsiaVientiane), + 330 => Some(TimeZone::AsiaVladivostok), + 331 => Some(TimeZone::AsiaYakutsk), + 332 => Some(TimeZone::AsiaYangon), + 333 => Some(TimeZone::AsiaYekaterinburg), + 334 => Some(TimeZone::AsiaYerevan), + 335 => Some(TimeZone::AtlanticAzores), + 336 => Some(TimeZone::AtlanticBermuda), + 337 => Some(TimeZone::AtlanticCanary), + 338 => Some(TimeZone::AtlanticCapeVerde), + 339 => Some(TimeZone::AtlanticFaeroe), + 340 => Some(TimeZone::AtlanticFaroe), + 341 => Some(TimeZone::AtlanticJanMayen), + 342 => Some(TimeZone::AtlanticMadeira), + 343 => Some(TimeZone::AtlanticReykjavik), + 344 => Some(TimeZone::AtlanticSouthGeorgia), + 345 => Some(TimeZone::AtlanticStHelena), + 346 => Some(TimeZone::AtlanticStanley), + 347 => Some(TimeZone::AustraliaACT), + 348 => Some(TimeZone::AustraliaAdelaide), + 349 => Some(TimeZone::AustraliaBrisbane), + 350 => Some(TimeZone::AustraliaBrokenHill), + 351 => Some(TimeZone::AustraliaCanberra), + 352 => Some(TimeZone::AustraliaCurrie), + 353 => Some(TimeZone::AustraliaDarwin), + 354 => Some(TimeZone::AustraliaEucla), + 355 => Some(TimeZone::AustraliaHobart), + 356 => Some(TimeZone::AustraliaLHI), + 357 => Some(TimeZone::AustraliaLindeman), + 358 => Some(TimeZone::AustraliaLordHowe), + 359 => Some(TimeZone::AustraliaMelbourne), + 360 => Some(TimeZone::AustraliaNSW), + 361 => Some(TimeZone::AustraliaNorth), + 362 => Some(TimeZone::AustraliaPerth), + 363 => Some(TimeZone::AustraliaQueensland), + 364 => Some(TimeZone::AustraliaSouth), + 365 => Some(TimeZone::AustraliaSydney), + 366 => Some(TimeZone::AustraliaTasmania), + 367 => Some(TimeZone::AustraliaVictoria), + 368 => Some(TimeZone::AustraliaWest), + 369 => Some(TimeZone::AustraliaYancowinna), + 370 => Some(TimeZone::BrazilAcre), + 371 => Some(TimeZone::BrazilDeNoronha), + 372 => Some(TimeZone::BrazilEast), + 373 => Some(TimeZone::BrazilWest), + 374 => Some(TimeZone::CET), + 375 => Some(TimeZone::CST6CDT), + 376 => Some(TimeZone::CanadaAtlantic), + 377 => Some(TimeZone::CanadaCentral), + 378 => Some(TimeZone::CanadaEastern), + 379 => Some(TimeZone::CanadaMountain), + 380 => Some(TimeZone::CanadaNewfoundland), + 381 => Some(TimeZone::CanadaPacific), + 382 => Some(TimeZone::CanadaSaskatchewan), + 383 => Some(TimeZone::CanadaYukon), + 384 => Some(TimeZone::ChileContinental), + 385 => Some(TimeZone::ChileEasterIsland), + 386 => Some(TimeZone::Cuba), + 387 => Some(TimeZone::EET), + 388 => Some(TimeZone::EST), + 389 => Some(TimeZone::EST5EDT), + 390 => Some(TimeZone::Egypt), + 391 => Some(TimeZone::Eire), + 392 => Some(TimeZone::EtcGMT), + 393 => Some(TimeZone::EtcGMTPlus0), + 394 => Some(TimeZone::EtcGMTPlus1), + 395 => Some(TimeZone::EtcGMTPlus10), + 396 => Some(TimeZone::EtcGMTPlus11), + 397 => Some(TimeZone::EtcGMTPlus12), + 398 => Some(TimeZone::EtcGMTPlus2), + 399 => Some(TimeZone::EtcGMTPlus3), + 400 => Some(TimeZone::EtcGMTPlus4), + 401 => Some(TimeZone::EtcGMTPlus5), + 402 => Some(TimeZone::EtcGMTPlus6), + 403 => Some(TimeZone::EtcGMTPlus7), + 404 => Some(TimeZone::EtcGMTPlus8), + 405 => Some(TimeZone::EtcGMTPlus9), + 406 => Some(TimeZone::EtcGMTMinus0), + 407 => Some(TimeZone::EtcGMTMinus1), + 408 => Some(TimeZone::EtcGMTMinus10), + 409 => Some(TimeZone::EtcGMTMinus11), + 410 => Some(TimeZone::EtcGMTMinus12), + 411 => Some(TimeZone::EtcGMTMinus13), + 412 => Some(TimeZone::EtcGMTMinus14), + 413 => Some(TimeZone::EtcGMTMinus2), + 414 => Some(TimeZone::EtcGMTMinus3), + 415 => Some(TimeZone::EtcGMTMinus4), + 416 => Some(TimeZone::EtcGMTMinus5), + 417 => Some(TimeZone::EtcGMTMinus6), + 418 => Some(TimeZone::EtcGMTMinus7), + 419 => Some(TimeZone::EtcGMTMinus8), + 420 => Some(TimeZone::EtcGMTMinus9), + 421 => Some(TimeZone::EtcGMT0), + 422 => Some(TimeZone::EtcGreenwich), + 423 => Some(TimeZone::EtcUCT), + 424 => Some(TimeZone::EtcUTC), + 425 => Some(TimeZone::EtcUniversal), + 426 => Some(TimeZone::EtcZulu), + 427 => Some(TimeZone::EuropeAmsterdam), + 428 => Some(TimeZone::EuropeAndorra), + 429 => Some(TimeZone::EuropeAstrakhan), + 430 => Some(TimeZone::EuropeAthens), + 431 => Some(TimeZone::EuropeBelfast), + 432 => Some(TimeZone::EuropeBelgrade), + 433 => Some(TimeZone::EuropeBerlin), + 434 => Some(TimeZone::EuropeBratislava), + 435 => Some(TimeZone::EuropeBrussels), + 436 => Some(TimeZone::EuropeBucharest), + 437 => Some(TimeZone::EuropeBudapest), + 438 => Some(TimeZone::EuropeBusingen), + 439 => Some(TimeZone::EuropeChisinau), + 440 => Some(TimeZone::EuropeCopenhagen), + 441 => Some(TimeZone::EuropeDublin), + 442 => Some(TimeZone::EuropeGibraltar), + 443 => Some(TimeZone::EuropeGuernsey), + 444 => Some(TimeZone::EuropeHelsinki), + 445 => Some(TimeZone::EuropeIsleOfMan), + 446 => Some(TimeZone::EuropeIstanbul), + 447 => Some(TimeZone::EuropeJersey), + 448 => Some(TimeZone::EuropeKaliningrad), + 449 => Some(TimeZone::EuropeKiev), + 450 => Some(TimeZone::EuropeKirov), + 451 => Some(TimeZone::EuropeKyiv), + 452 => Some(TimeZone::EuropeLisbon), + 453 => Some(TimeZone::EuropeLjubljana), + 454 => Some(TimeZone::EuropeLondon), + 455 => Some(TimeZone::EuropeLuxembourg), + 456 => Some(TimeZone::EuropeMadrid), + 457 => Some(TimeZone::EuropeMalta), + 458 => Some(TimeZone::EuropeMariehamn), + 459 => Some(TimeZone::EuropeMinsk), + 460 => Some(TimeZone::EuropeMonaco), + 461 => Some(TimeZone::EuropeMoscow), + 462 => Some(TimeZone::EuropeNicosia), + 463 => Some(TimeZone::EuropeOslo), + 464 => Some(TimeZone::EuropeParis), + 465 => Some(TimeZone::EuropePodgorica), + 466 => Some(TimeZone::EuropePrague), + 467 => Some(TimeZone::EuropeRiga), + 468 => Some(TimeZone::EuropeRome), + 469 => Some(TimeZone::EuropeSamara), + 470 => Some(TimeZone::EuropeSanMarino), + 471 => Some(TimeZone::EuropeSarajevo), + 472 => Some(TimeZone::EuropeSaratov), + 473 => Some(TimeZone::EuropeSimferopol), + 474 => Some(TimeZone::EuropeSkopje), + 475 => Some(TimeZone::EuropeSofia), + 476 => Some(TimeZone::EuropeStockholm), + 477 => Some(TimeZone::EuropeTallinn), + 478 => Some(TimeZone::EuropeTirane), + 479 => Some(TimeZone::EuropeTiraspol), + 480 => Some(TimeZone::EuropeUlyanovsk), + 481 => Some(TimeZone::EuropeUzhgorod), + 482 => Some(TimeZone::EuropeVaduz), + 483 => Some(TimeZone::EuropeVatican), + 484 => Some(TimeZone::EuropeVienna), + 485 => Some(TimeZone::EuropeVilnius), + 486 => Some(TimeZone::EuropeVolgograd), + 487 => Some(TimeZone::EuropeWarsaw), + 488 => Some(TimeZone::EuropeZagreb), + 489 => Some(TimeZone::EuropeZaporozhye), + 490 => Some(TimeZone::EuropeZurich), + 491 => Some(TimeZone::Factory), + 492 => Some(TimeZone::GB), + 493 => Some(TimeZone::GBEire), + 494 => Some(TimeZone::GMT), + 495 => Some(TimeZone::GMTPlus0), + 496 => Some(TimeZone::GMTMinus0), + 497 => Some(TimeZone::GMT0), + 498 => Some(TimeZone::Greenwich), + 499 => Some(TimeZone::HST), + 500 => Some(TimeZone::Hongkong), + 501 => Some(TimeZone::Iceland), + 502 => Some(TimeZone::IndianAntananarivo), + 503 => Some(TimeZone::IndianChagos), + 504 => Some(TimeZone::IndianChristmas), + 505 => Some(TimeZone::IndianCocos), + 506 => Some(TimeZone::IndianComoro), + 507 => Some(TimeZone::IndianKerguelen), + 508 => Some(TimeZone::IndianMahe), + 509 => Some(TimeZone::IndianMaldives), + 510 => Some(TimeZone::IndianMauritius), + 511 => Some(TimeZone::IndianMayotte), + 512 => Some(TimeZone::IndianReunion), + 513 => Some(TimeZone::Iran), + 514 => Some(TimeZone::Israel), + 515 => Some(TimeZone::Jamaica), + 516 => Some(TimeZone::Japan), + 517 => Some(TimeZone::Kwajalein), + 518 => Some(TimeZone::Libya), + 519 => Some(TimeZone::MET), + 520 => Some(TimeZone::MST), + 521 => Some(TimeZone::MST7MDT), + 522 => Some(TimeZone::MexicoBajaNorte), + 523 => Some(TimeZone::MexicoBajaSur), + 524 => Some(TimeZone::MexicoGeneral), + 525 => Some(TimeZone::NZ), + 526 => Some(TimeZone::NZCHAT), + 527 => Some(TimeZone::Navajo), + 528 => Some(TimeZone::PRC), + 529 => Some(TimeZone::PST8PDT), + 530 => Some(TimeZone::PacificApia), + 531 => Some(TimeZone::PacificAuckland), + 532 => Some(TimeZone::PacificBougainville), + 533 => Some(TimeZone::PacificChatham), + 534 => Some(TimeZone::PacificChuuk), + 535 => Some(TimeZone::PacificEaster), + 536 => Some(TimeZone::PacificEfate), + 537 => Some(TimeZone::PacificEnderbury), + 538 => Some(TimeZone::PacificFakaofo), + 539 => Some(TimeZone::PacificFiji), + 540 => Some(TimeZone::PacificFunafuti), + 541 => Some(TimeZone::PacificGalapagos), + 542 => Some(TimeZone::PacificGambier), + 543 => Some(TimeZone::PacificGuadalcanal), + 544 => Some(TimeZone::PacificGuam), + 545 => Some(TimeZone::PacificHonolulu), + 546 => Some(TimeZone::PacificJohnston), + 547 => Some(TimeZone::PacificKanton), + 548 => Some(TimeZone::PacificKiritimati), + 549 => Some(TimeZone::PacificKosrae), + 550 => Some(TimeZone::PacificKwajalein), + 551 => Some(TimeZone::PacificMajuro), + 552 => Some(TimeZone::PacificMarquesas), + 553 => Some(TimeZone::PacificMidway), + 554 => Some(TimeZone::PacificNauru), + 555 => Some(TimeZone::PacificNiue), + 556 => Some(TimeZone::PacificNorfolk), + 557 => Some(TimeZone::PacificNoumea), + 558 => Some(TimeZone::PacificPagoPago), + 559 => Some(TimeZone::PacificPalau), + 560 => Some(TimeZone::PacificPitcairn), + 561 => Some(TimeZone::PacificPohnpei), + 562 => Some(TimeZone::PacificPonape), + 563 => Some(TimeZone::PacificPortMoresby), + 564 => Some(TimeZone::PacificRarotonga), + 565 => Some(TimeZone::PacificSaipan), + 566 => Some(TimeZone::PacificSamoa), + 567 => Some(TimeZone::PacificTahiti), + 568 => Some(TimeZone::PacificTarawa), + 569 => Some(TimeZone::PacificTongatapu), + 570 => Some(TimeZone::PacificTruk), + 571 => Some(TimeZone::PacificWake), + 572 => Some(TimeZone::PacificWallis), + 573 => Some(TimeZone::PacificYap), + 574 => Some(TimeZone::Poland), + 575 => Some(TimeZone::Portugal), + 576 => Some(TimeZone::ROC), + 577 => Some(TimeZone::ROK), + 578 => Some(TimeZone::Singapore), + 579 => Some(TimeZone::Turkey), + 580 => Some(TimeZone::UCT), + 581 => Some(TimeZone::USAlaska), + 582 => Some(TimeZone::USAleutian), + 583 => Some(TimeZone::USArizona), + 584 => Some(TimeZone::USCentral), + 585 => Some(TimeZone::USEastIndiana), + 586 => Some(TimeZone::USEastern), + 587 => Some(TimeZone::USHawaii), + 588 => Some(TimeZone::USIndianaStarke), + 589 => Some(TimeZone::USMichigan), + 590 => Some(TimeZone::USMountain), + 591 => Some(TimeZone::USPacific), + 592 => Some(TimeZone::USSamoa), + 593 => Some(TimeZone::UTC), + 594 => Some(TimeZone::Universal), + 595 => Some(TimeZone::WSU), + 596 => Some(TimeZone::WET), + 597 => Some(TimeZone::Zulu), + _ => None, + } + } + + const COUNT: usize = 598; +} + +impl serde::Serialize for TimeZone { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TimeZone { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TlsCipherSuite { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"tls13-aes-256-gcm-sha384" => TlsCipherSuite::Tls13Aes256GcmSha384, + b"tls13-aes-128-gcm-sha256" => TlsCipherSuite::Tls13Aes128GcmSha256, + b"tls13-chacha20-poly1305-sha256" => TlsCipherSuite::Tls13Chacha20Poly1305Sha256, + b"tls-ecdhe-ecdsa-with-aes-256-gcm-sha384" => TlsCipherSuite::TlsEcdheEcdsaWithAes256GcmSha384, + b"tls-ecdhe-ecdsa-with-aes-128-gcm-sha256" => TlsCipherSuite::TlsEcdheEcdsaWithAes128GcmSha256, + b"tls-ecdhe-ecdsa-with-chacha20-poly1305-sha256" => TlsCipherSuite::TlsEcdheEcdsaWithChacha20Poly1305Sha256, + b"tls-ecdhe-rsa-with-aes-256-gcm-sha384" => TlsCipherSuite::TlsEcdheRsaWithAes256GcmSha384, + b"tls-ecdhe-rsa-with-aes-128-gcm-sha256" => TlsCipherSuite::TlsEcdheRsaWithAes128GcmSha256, + b"tls-ecdhe-rsa-with-chacha20-poly1305-sha256" => TlsCipherSuite::TlsEcdheRsaWithChacha20Poly1305Sha256, + } + } + + fn as_str(&self) -> &'static str { + match self { + TlsCipherSuite::Tls13Aes256GcmSha384 => "tls13-aes-256-gcm-sha384", + TlsCipherSuite::Tls13Aes128GcmSha256 => "tls13-aes-128-gcm-sha256", + TlsCipherSuite::Tls13Chacha20Poly1305Sha256 => "tls13-chacha20-poly1305-sha256", + TlsCipherSuite::TlsEcdheEcdsaWithAes256GcmSha384 => { + "tls-ecdhe-ecdsa-with-aes-256-gcm-sha384" + } + TlsCipherSuite::TlsEcdheEcdsaWithAes128GcmSha256 => { + "tls-ecdhe-ecdsa-with-aes-128-gcm-sha256" + } + TlsCipherSuite::TlsEcdheEcdsaWithChacha20Poly1305Sha256 => { + "tls-ecdhe-ecdsa-with-chacha20-poly1305-sha256" + } + TlsCipherSuite::TlsEcdheRsaWithAes256GcmSha384 => { + "tls-ecdhe-rsa-with-aes-256-gcm-sha384" + } + TlsCipherSuite::TlsEcdheRsaWithAes128GcmSha256 => { + "tls-ecdhe-rsa-with-aes-128-gcm-sha256" + } + TlsCipherSuite::TlsEcdheRsaWithChacha20Poly1305Sha256 => { + "tls-ecdhe-rsa-with-chacha20-poly1305-sha256" + } + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TlsCipherSuite::Tls13Aes256GcmSha384), + 1 => Some(TlsCipherSuite::Tls13Aes128GcmSha256), + 2 => Some(TlsCipherSuite::Tls13Chacha20Poly1305Sha256), + 3 => Some(TlsCipherSuite::TlsEcdheEcdsaWithAes256GcmSha384), + 4 => Some(TlsCipherSuite::TlsEcdheEcdsaWithAes128GcmSha256), + 5 => Some(TlsCipherSuite::TlsEcdheEcdsaWithChacha20Poly1305Sha256), + 6 => Some(TlsCipherSuite::TlsEcdheRsaWithAes256GcmSha384), + 7 => Some(TlsCipherSuite::TlsEcdheRsaWithAes128GcmSha256), + 8 => Some(TlsCipherSuite::TlsEcdheRsaWithChacha20Poly1305Sha256), + _ => None, + } + } + + const COUNT: usize = 9; +} + +impl serde::Serialize for TlsCipherSuite { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TlsCipherSuite { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TlsPolicyType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"tlsa" => TlsPolicyType::Tlsa, + b"sts" => TlsPolicyType::Sts, + b"noPolicyFound" => TlsPolicyType::NoPolicyFound, + b"other" => TlsPolicyType::Other, + } + } + + fn as_str(&self) -> &'static str { + match self { + TlsPolicyType::Tlsa => "tlsa", + TlsPolicyType::Sts => "sts", + TlsPolicyType::NoPolicyFound => "noPolicyFound", + TlsPolicyType::Other => "other", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TlsPolicyType::Tlsa), + 1 => Some(TlsPolicyType::Sts), + 2 => Some(TlsPolicyType::NoPolicyFound), + 3 => Some(TlsPolicyType::Other), + _ => None, + } + } + + const COUNT: usize = 4; +} + +impl serde::Serialize for TlsPolicyType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TlsPolicyType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TlsResultType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"startTlsNotSupported" => TlsResultType::StartTlsNotSupported, + b"certificateHostMismatch" => TlsResultType::CertificateHostMismatch, + b"certificateExpired" => TlsResultType::CertificateExpired, + b"certificateNotTrusted" => TlsResultType::CertificateNotTrusted, + b"validationFailure" => TlsResultType::ValidationFailure, + b"tlsaInvalid" => TlsResultType::TlsaInvalid, + b"dnssecInvalid" => TlsResultType::DnssecInvalid, + b"daneRequired" => TlsResultType::DaneRequired, + b"stsPolicyFetchError" => TlsResultType::StsPolicyFetchError, + b"stsPolicyInvalid" => TlsResultType::StsPolicyInvalid, + b"stsWebpkiInvalid" => TlsResultType::StsWebpkiInvalid, + b"other" => TlsResultType::Other, + } + } + + fn as_str(&self) -> &'static str { + match self { + TlsResultType::StartTlsNotSupported => "startTlsNotSupported", + TlsResultType::CertificateHostMismatch => "certificateHostMismatch", + TlsResultType::CertificateExpired => "certificateExpired", + TlsResultType::CertificateNotTrusted => "certificateNotTrusted", + TlsResultType::ValidationFailure => "validationFailure", + TlsResultType::TlsaInvalid => "tlsaInvalid", + TlsResultType::DnssecInvalid => "dnssecInvalid", + TlsResultType::DaneRequired => "daneRequired", + TlsResultType::StsPolicyFetchError => "stsPolicyFetchError", + TlsResultType::StsPolicyInvalid => "stsPolicyInvalid", + TlsResultType::StsWebpkiInvalid => "stsWebpkiInvalid", + TlsResultType::Other => "other", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TlsResultType::StartTlsNotSupported), + 1 => Some(TlsResultType::CertificateHostMismatch), + 2 => Some(TlsResultType::CertificateExpired), + 3 => Some(TlsResultType::CertificateNotTrusted), + 4 => Some(TlsResultType::ValidationFailure), + 5 => Some(TlsResultType::TlsaInvalid), + 6 => Some(TlsResultType::DnssecInvalid), + 7 => Some(TlsResultType::DaneRequired), + 8 => Some(TlsResultType::StsPolicyFetchError), + 9 => Some(TlsResultType::StsPolicyInvalid), + 10 => Some(TlsResultType::StsWebpkiInvalid), + 11 => Some(TlsResultType::Other), + _ => None, + } + } + + const COUNT: usize = 12; +} + +impl serde::Serialize for TlsResultType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TlsResultType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TlsVersion { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"tls12" => TlsVersion::Tls12, + b"tls13" => TlsVersion::Tls13, + } + } + + fn as_str(&self) -> &'static str { + match self { + TlsVersion::Tls12 => "tls12", + TlsVersion::Tls13 => "tls13", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TlsVersion::Tls12), + 1 => Some(TlsVersion::Tls13), + _ => None, + } + } + + const COUNT: usize = 2; +} + +impl serde::Serialize for TlsVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TlsVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TraceValueType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"String" => TraceValueType::String, + b"UnsignedInt" => TraceValueType::UnsignedInt, + b"Integer" => TraceValueType::Integer, + b"Boolean" => TraceValueType::Boolean, + b"Float" => TraceValueType::Float, + b"UTCDateTime" => TraceValueType::UTCDateTime, + b"Duration" => TraceValueType::Duration, + b"IpAddr" => TraceValueType::IpAddr, + b"List" => TraceValueType::List, + b"Event" => TraceValueType::Event, + b"Null" => TraceValueType::Null, + } + } + + fn as_str(&self) -> &'static str { + match self { + TraceValueType::String => "String", + TraceValueType::UnsignedInt => "UnsignedInt", + TraceValueType::Integer => "Integer", + TraceValueType::Boolean => "Boolean", + TraceValueType::Float => "Float", + TraceValueType::UTCDateTime => "UTCDateTime", + TraceValueType::Duration => "Duration", + TraceValueType::IpAddr => "IpAddr", + TraceValueType::List => "List", + TraceValueType::Event => "Event", + TraceValueType::Null => "Null", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TraceValueType::String), + 1 => Some(TraceValueType::UnsignedInt), + 2 => Some(TraceValueType::Integer), + 3 => Some(TraceValueType::Boolean), + 4 => Some(TraceValueType::Float), + 5 => Some(TraceValueType::UTCDateTime), + 6 => Some(TraceValueType::Duration), + 7 => Some(TraceValueType::IpAddr), + 8 => Some(TraceValueType::List), + 9 => Some(TraceValueType::Event), + 10 => Some(TraceValueType::Null), + _ => None, + } + } + + const COUNT: usize = 11; +} + +impl serde::Serialize for TraceValueType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TraceValueType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TracerType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Log" => TracerType::Log, + b"Stdout" => TracerType::Stdout, + b"Journal" => TracerType::Journal, + b"OtelHttp" => TracerType::OtelHttp, + b"OtelGrpc" => TracerType::OtelGrpc, + } + } + + fn as_str(&self) -> &'static str { + match self { + TracerType::Log => "Log", + TracerType::Stdout => "Stdout", + TracerType::Journal => "Journal", + TracerType::OtelHttp => "OtelHttp", + TracerType::OtelGrpc => "OtelGrpc", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TracerType::Log), + 1 => Some(TracerType::Stdout), + 2 => Some(TracerType::Journal), + 3 => Some(TracerType::OtelHttp), + 4 => Some(TracerType::OtelGrpc), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for TracerType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TracerType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TracingLevel { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"error" => TracingLevel::Error, + b"warn" => TracingLevel::Warn, + b"info" => TracingLevel::Info, + b"debug" => TracingLevel::Debug, + b"trace" => TracingLevel::Trace, + } + } + + fn as_str(&self) -> &'static str { + match self { + TracingLevel::Error => "error", + TracingLevel::Warn => "warn", + TracingLevel::Info => "info", + TracingLevel::Debug => "debug", + TracingLevel::Trace => "trace", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TracingLevel::Error), + 1 => Some(TracingLevel::Warn), + 2 => Some(TracingLevel::Info), + 3 => Some(TracingLevel::Debug), + 4 => Some(TracingLevel::Trace), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for TracingLevel { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TracingLevel { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TracingLevelOpt { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"disable" => TracingLevelOpt::Disable, + b"error" => TracingLevelOpt::Error, + b"warn" => TracingLevelOpt::Warn, + b"info" => TracingLevelOpt::Info, + b"debug" => TracingLevelOpt::Debug, + b"trace" => TracingLevelOpt::Trace, + } + } + + fn as_str(&self) -> &'static str { + match self { + TracingLevelOpt::Disable => "disable", + TracingLevelOpt::Error => "error", + TracingLevelOpt::Warn => "warn", + TracingLevelOpt::Info => "info", + TracingLevelOpt::Debug => "debug", + TracingLevelOpt::Trace => "trace", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TracingLevelOpt::Disable), + 1 => Some(TracingLevelOpt::Error), + 2 => Some(TracingLevelOpt::Warn), + 3 => Some(TracingLevelOpt::Info), + 4 => Some(TracingLevelOpt::Debug), + 5 => Some(TracingLevelOpt::Trace), + _ => None, + } + } + + const COUNT: usize = 6; +} + +impl serde::Serialize for TracingLevelOpt { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TracingLevelOpt { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TracingStoreType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Disabled" => TracingStoreType::Disabled, + b"Default" => TracingStoreType::Default, + b"FoundationDb" => TracingStoreType::FoundationDb, + b"PostgreSql" => TracingStoreType::PostgreSql, + b"MySql" => TracingStoreType::MySql, + } + } + + fn as_str(&self) -> &'static str { + match self { + TracingStoreType::Disabled => "Disabled", + TracingStoreType::Default => "Default", + TracingStoreType::FoundationDb => "FoundationDb", + TracingStoreType::PostgreSql => "PostgreSql", + TracingStoreType::MySql => "MySql", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TracingStoreType::Disabled), + 1 => Some(TracingStoreType::Default), + 2 => Some(TracingStoreType::FoundationDb), + 3 => Some(TracingStoreType::PostgreSql), + 4 => Some(TracingStoreType::MySql), + _ => None, + } + } + + const COUNT: usize = 5; +} + +impl serde::Serialize for TracingStoreType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TracingStoreType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for TsigAlgorithm { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"hmac-md5" => TsigAlgorithm::HmacMd5, + b"gss" => TsigAlgorithm::Gss, + b"hmac-sha1" => TsigAlgorithm::HmacSha1, + b"hmac-sha224" => TsigAlgorithm::HmacSha224, + b"hmac-sha256" => TsigAlgorithm::HmacSha256, + b"hmac-sha256-128" => TsigAlgorithm::HmacSha256128, + b"hmac-sha384" => TsigAlgorithm::HmacSha384, + b"hmac-sha384-192" => TsigAlgorithm::HmacSha384192, + b"hmac-sha512" => TsigAlgorithm::HmacSha512, + b"hmac-sha512-256" => TsigAlgorithm::HmacSha512256, + } + } + + fn as_str(&self) -> &'static str { + match self { + TsigAlgorithm::HmacMd5 => "hmac-md5", + TsigAlgorithm::Gss => "gss", + TsigAlgorithm::HmacSha1 => "hmac-sha1", + TsigAlgorithm::HmacSha224 => "hmac-sha224", + TsigAlgorithm::HmacSha256 => "hmac-sha256", + TsigAlgorithm::HmacSha256128 => "hmac-sha256-128", + TsigAlgorithm::HmacSha384 => "hmac-sha384", + TsigAlgorithm::HmacSha384192 => "hmac-sha384-192", + TsigAlgorithm::HmacSha512 => "hmac-sha512", + TsigAlgorithm::HmacSha512256 => "hmac-sha512-256", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(TsigAlgorithm::HmacMd5), + 1 => Some(TsigAlgorithm::Gss), + 2 => Some(TsigAlgorithm::HmacSha1), + 3 => Some(TsigAlgorithm::HmacSha224), + 4 => Some(TsigAlgorithm::HmacSha256), + 5 => Some(TsigAlgorithm::HmacSha256128), + 6 => Some(TsigAlgorithm::HmacSha384), + 7 => Some(TsigAlgorithm::HmacSha384192), + 8 => Some(TsigAlgorithm::HmacSha512), + 9 => Some(TsigAlgorithm::HmacSha512256), + _ => None, + } + } + + const COUNT: usize = 10; +} + +impl serde::Serialize for TsigAlgorithm { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for TsigAlgorithm { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for UserRolesType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"User" => UserRolesType::User, + b"Admin" => UserRolesType::Admin, + b"Custom" => UserRolesType::Custom, + } + } + + fn as_str(&self) -> &'static str { + match self { + UserRolesType::User => "User", + UserRolesType::Admin => "Admin", + UserRolesType::Custom => "Custom", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(UserRolesType::User), + 1 => Some(UserRolesType::Admin), + 2 => Some(UserRolesType::Custom), + _ => None, + } + } + + const COUNT: usize = 3; +} + +impl serde::Serialize for UserRolesType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for UserRolesType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} diff --git a/crates/registry/src/schema/mod.rs b/crates/registry/src/schema/mod.rs index 61e5c67a..4ee88b4e 100644 --- a/crates/registry/src/schema/mod.rs +++ b/crates/registry/src/schema/mod.rs @@ -18,6 +18,7 @@ use trc::TOTAL_EVENT_COUNT; pub mod enums; pub mod enums_impl; pub mod prelude; +#[allow(clippy::large_enum_variant)] pub mod properties; pub mod properties_impl; #[allow(clippy::large_enum_variant)] diff --git a/crates/registry/src/schema/properties.rs b/crates/registry/src/schema/properties.rs new file mode 100644 index 00000000..8cc4cb91 --- /dev/null +++ b/crates/registry/src/schema/properties.rs @@ -0,0 +1,1131 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +use crate::schema::prelude::*; +#[derive(Debug, Clone, Serialize, PartialEq, Eq)] +#[serde(untagged)] +pub enum ObjectInner { + Account(Account), + AccountPassword(AccountPassword), + AccountSettings(AccountSettings), + AcmeProvider(AcmeProvider), + Action(Action), + AddressBook(AddressBook), + AiModel(AiModel), + Alert(Alert), + AllowedIp(AllowedIp), + ApiKey(ApiKey), + AppPassword(AppPassword), + Application(Application), + ArchivedItem(ArchivedItem), + ArfExternalReport(ArfExternalReport), + Asn(Asn), + Authentication(Authentication), + BlobStore(BlobStore), + BlockedIp(BlockedIp), + Bootstrap(Bootstrap), + Cache(Cache), + Calendar(Calendar), + CalendarAlarm(CalendarAlarm), + CalendarScheduling(CalendarScheduling), + Certificate(Certificate), + ClusterNode(ClusterNode), + ClusterRole(ClusterRole), + Coordinator(Coordinator), + DataRetention(DataRetention), + DataStore(DataStore), + Directory(Directory), + DkimReportSettings(DkimReportSettings), + DkimSignature(DkimSignature), + DmarcExternalReport(DmarcExternalReport), + DmarcInternalReport(DmarcInternalReport), + DmarcReportSettings(DmarcReportSettings), + DnsResolver(DnsResolver), + DnsServer(DnsServer), + Domain(Domain), + DsnReportSettings(DsnReportSettings), + Email(Email), + Enterprise(Enterprise), + EventTracingLevel(EventTracingLevel), + FileStorage(FileStorage), + Http(Http), + HttpForm(HttpForm), + HttpLookup(HttpLookup), + Imap(Imap), + InMemoryStore(InMemoryStore), + Jmap(Jmap), + Log(Log), + MailingList(MailingList), + MaskedEmail(MaskedEmail), + MemoryLookupKey(MemoryLookupKey), + MemoryLookupKeyValue(MemoryLookupKeyValue), + Metric(Metric), + Metrics(Metrics), + MetricsStore(MetricsStore), + MtaConnectionStrategy(MtaConnectionStrategy), + MtaDeliverySchedule(MtaDeliverySchedule), + MtaExtensions(MtaExtensions), + MtaHook(MtaHook), + MtaInboundSession(MtaInboundSession), + MtaInboundThrottle(MtaInboundThrottle), + MtaMilter(MtaMilter), + MtaOutboundStrategy(MtaOutboundStrategy), + MtaOutboundThrottle(MtaOutboundThrottle), + MtaQueueQuota(MtaQueueQuota), + MtaRoute(MtaRoute), + MtaStageAuth(MtaStageAuth), + MtaStageConnect(MtaStageConnect), + MtaStageData(MtaStageData), + MtaStageEhlo(MtaStageEhlo), + MtaStageMail(MtaStageMail), + MtaStageRcpt(MtaStageRcpt), + MtaSts(MtaSts), + MtaTlsStrategy(MtaTlsStrategy), + MtaVirtualQueue(MtaVirtualQueue), + NetworkListener(NetworkListener), + OAuthClient(OAuthClient), + OidcProvider(OidcProvider), + PublicKey(PublicKey), + QueuedMessage(QueuedMessage), + ReportSettings(ReportSettings), + Role(Role), + Search(Search), + SearchStore(SearchStore), + Security(Security), + SenderAuth(SenderAuth), + Sharing(Sharing), + SieveSystemInterpreter(SieveSystemInterpreter), + SieveSystemScript(SieveSystemScript), + SieveUserInterpreter(SieveUserInterpreter), + SieveUserScript(SieveUserScript), + SpamClassifier(SpamClassifier), + SpamDnsblServer(SpamDnsblServer), + SpamDnsblSettings(SpamDnsblSettings), + SpamFileExtension(SpamFileExtension), + SpamLlm(SpamLlm), + SpamPyzor(SpamPyzor), + SpamRule(SpamRule), + SpamSettings(SpamSettings), + SpamTag(SpamTag), + SpamTrainingSample(SpamTrainingSample), + SpfReportSettings(SpfReportSettings), + StoreLookup(StoreLookup), + SystemSettings(SystemSettings), + Task(Task), + TaskManager(TaskManager), + Tenant(Tenant), + TlsExternalReport(TlsExternalReport), + TlsInternalReport(TlsInternalReport), + TlsReportSettings(TlsReportSettings), + Trace(Trace), + Tracer(Tracer), + TracingStore(TracingStore), + WebDav(WebDav), + WebHook(WebHook), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum ObjectType { + Account = 0, + AccountPassword = 1, + AccountSettings = 2, + AcmeProvider = 3, + Action = 4, + AddressBook = 5, + AiModel = 6, + Alert = 7, + AllowedIp = 8, + ApiKey = 9, + AppPassword = 10, + Application = 11, + ArchivedItem = 12, + ArfExternalReport = 13, + Asn = 14, + Authentication = 15, + BlobStore = 16, + BlockedIp = 17, + Bootstrap = 18, + Cache = 19, + Calendar = 20, + CalendarAlarm = 21, + CalendarScheduling = 22, + Certificate = 23, + ClusterNode = 24, + ClusterRole = 25, + Coordinator = 26, + DataRetention = 27, + DataStore = 28, + Directory = 29, + DkimReportSettings = 30, + DkimSignature = 31, + DmarcExternalReport = 32, + DmarcInternalReport = 33, + DmarcReportSettings = 34, + DnsResolver = 35, + DnsServer = 36, + Domain = 37, + DsnReportSettings = 38, + Email = 39, + Enterprise = 40, + EventTracingLevel = 41, + FileStorage = 42, + Http = 43, + HttpForm = 44, + HttpLookup = 45, + Imap = 46, + InMemoryStore = 47, + Jmap = 48, + Log = 49, + MailingList = 50, + MaskedEmail = 51, + MemoryLookupKey = 52, + MemoryLookupKeyValue = 53, + Metric = 54, + Metrics = 55, + MetricsStore = 56, + MtaConnectionStrategy = 57, + MtaDeliverySchedule = 58, + MtaExtensions = 59, + MtaHook = 60, + MtaInboundSession = 61, + MtaInboundThrottle = 62, + MtaMilter = 63, + MtaOutboundStrategy = 64, + MtaOutboundThrottle = 65, + MtaQueueQuota = 66, + MtaRoute = 67, + MtaStageAuth = 68, + MtaStageConnect = 69, + MtaStageData = 70, + MtaStageEhlo = 71, + MtaStageMail = 72, + MtaStageRcpt = 73, + MtaSts = 74, + MtaTlsStrategy = 75, + MtaVirtualQueue = 76, + NetworkListener = 77, + OAuthClient = 78, + OidcProvider = 79, + PublicKey = 80, + QueuedMessage = 81, + ReportSettings = 82, + Role = 83, + Search = 84, + SearchStore = 85, + Security = 86, + SenderAuth = 87, + Sharing = 88, + SieveSystemInterpreter = 89, + SieveSystemScript = 90, + SieveUserInterpreter = 91, + SieveUserScript = 92, + SpamClassifier = 93, + SpamDnsblServer = 94, + SpamDnsblSettings = 95, + SpamFileExtension = 96, + SpamLlm = 97, + SpamPyzor = 98, + SpamRule = 99, + SpamSettings = 100, + SpamTag = 101, + SpamTrainingSample = 102, + SpfReportSettings = 103, + StoreLookup = 104, + SystemSettings = 105, + Task = 106, + TaskManager = 107, + Tenant = 108, + TlsExternalReport = 109, + TlsInternalReport = 110, + TlsReportSettings = 111, + Trace = 112, + Tracer = 113, + TracingStore = 114, + WebDav = 115, + WebHook = 116, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u16)] +pub enum Property { + Type = 0, + AbuseBanPeriod = 678, + AbuseBanRate = 677, + AccessKey = 118, + AccessKeyId = 327, + AccessTokenExpiry = 619, + AccessTokens = 132, + AccountDomainId = 810, + AccountId = 57, + AccountIdentifier = 315, + AccountKey = 15, + AccountName = 809, + AccountType = 811, + AccountUri = 16, + Accounts = 151, + AcmeProviderId = 182, + AddAuthResultsHeader = 554, + AddDateHeader = 555, + AddDeliveredToHeader = 556, + AddMessageIdHeader = 557, + AddReceivedHeader = 558, + AddReceivedSpfHeader = 559, + AddReturnPathHeader = 560, + AdditionalInformation = 838, + Address = 44, + Addresses = 579, + AggregateContactInfo = 268, + AggregateDkimSignDomain = 274, + AggregateFromAddress = 269, + AggregateFromName = 270, + AggregateMaxReportSize = 271, + AggregateOrgName = 272, + AggregateSendFrequency = 273, + AggregateSubject = 275, + AlarmId = 798, + Algorithms = 225, + Aliases = 339, + AllowCount = 768, + AllowDirectoryQueries = 695, + AllowExternalRcpts = 164, + AllowInvalidCerts = 26, + AllowPlainTextAuth = 424, + AllowRelaying = 348, + AllowSpamTraining = 369, + AllowedEndpoints = 398, + AllowedIps = 49, + AllowedNotifyUris = 712, + Alpha = 388, + AnonymousClientRegistration = 614, + Ansi = 858, + ApiKey = 325, + ApplicationKey = 321, + ApplicationSecret = 322, + ArcResult = 292, + ArcVerify = 690, + ArchiveDeletedAccountsFor = 203, + ArchiveDeletedItemsFor = 202, + ArchivedAt = 58, + ArchivedItemType = 820, + ArchivedUntil = 59, + ArrivalDate = 68, + AsnUrls = 102, + AttemptNumber = 829, + Attempts = 303, + AttrClass = 470, + AttrDescription = 471, + AttrEmail = 472, + AttrEmailAlias = 473, + AttrMemberOf = 474, + AttrSecret = 475, + AttrSecretChanged = 476, + Auid = 215, + AuthBanPeriod = 680, + AuthBanRate = 679, + AuthCodeExpiry = 616, + AuthCodeMaxAttempts = 613, + AuthFailure = 81, + AuthSecret = 501, + AuthToken = 314, + AuthUsername = 502, + AuthenticatedAs = 740, + AuthenticationResults = 69, + AutoAddInvitations = 171, + AutoUpdateFrequency = 53, + BaseDn = 463, + BearerToken = 403, + Beta = 389, + Bind = 589, + BindAuthentication = 466, + BindDn = 464, + BindSecret = 465, + BlobCleanupSchedule = 200, + BlobId = 60, + BlobSize = 655, + BlobStore = 126, + BlockCount = 766, + Body = 38, + Brokers = 459, + Bucket = 658, + BufferSize = 656, + Buffered = 863, + Canonicalization = 216, + CapacityClient = 584, + CapacityReadBuffer = 585, + CapacitySubscription = 586, + CatchAllAddress = 346, + Categories = 759, + Certificate = 176, + CertificateManagement = 342, + ChallengeType = 10, + ChangesMaxResults = 435, + Chunking = 517, + ClaimGroups = 612, + ClaimName = 611, + ClaimUsername = 609, + Cleartext = 693, + ClientId = 604, + ClusterFile = 382, + ColumnClass = 781, + ColumnDescription = 782, + ColumnEmail = 779, + ColumnSecret = 780, + Comment = 240, + CompressionAlgorithm = 359, + Concurrency = 304, + Condition = 34, + Confidence = 760, + Config = 873, + ConnectTimeout = 505, + Connection = 539, + ConsumerKey = 323, + Contact = 11, + ContactInfo = 844, + Contacts = 133, + Container = 117, + Content = 65, + ContentTypes = 758, + Contents = 708, + Count = 258, + Create = 367, + CreatedAt = 46, + CreatedBy = 486, + CredentialId = 627, + Credentials = 588, + CurrentSecret = 4, + CustomEndpoint = 662, + CustomRegion = 663, + CustomRule = 787, + Dane = 569, + DataCleanupSchedule = 199, + DataStore = 125, + DataTimeout = 506, + Database = 575, + DatacenterId = 383, + DateRangeBegin = 245, + DateRangeEnd = 246, + DateRangeStart = 845, + Day = 192, + DeadPropertyMaxSize = 868, + DefaultAdminRoleIds = 108, + DefaultCertificateId = 790, + DefaultDisplayName = 20, + DefaultDomain = 122, + DefaultDomainId = 789, + DefaultExpiryDuplicate = 709, + DefaultExpiryVacation = 710, + DefaultFolders = 360, + DefaultFromAddress = 405, + DefaultFromName = 697, + DefaultGroupRoleIds = 106, + DefaultHostname = 788, + DefaultHrefName = 21, + DefaultLanguage = 665, + DefaultName = 408, + DefaultReturnPath = 701, + DefaultSubject = 411, + DefaultSubjectPrefix = 714, + DefaultTenantRoleIds = 107, + DefaultUserRoleIds = 105, + Definition = 235, + Delay = 825, + DeleteAfter = 229, + DeleteAfterUse = 777, + DeliverAt = 238, + DeliverBy = 518, + DeliverTo = 404, + DeliveryResult = 82, + Depth = 381, + Description = 6, + Details = 297, + Directory = 12, + DirectoryId = 104, + DisableCapabilities = 711, + DisableLanguages = 666, + DisabledPermissions = 629, + DiscardAfter = 872, + Disposition = 747, + DkimAdspDns = 83, + DkimCanonicalizedBody = 84, + DkimCanonicalizedHeader = 85, + DkimDomain = 86, + DkimIdentity = 87, + DkimManagement = 343, + DkimPass = 291, + DkimResults = 266, + DkimSelector = 88, + DkimSelectorDns = 89, + DkimSignDomain = 231, + DkimSignatures = 155, + DkimStrict = 686, + DkimVerify = 687, + DmarcPass = 294, + DmarcPolicy = 295, + DmarcResult = 293, + DmarcVerify = 691, + DnsIpv4 = 134, + DnsIpv6 = 135, + DnsManagement = 344, + DnsMtaSts = 136, + DnsMx = 137, + DnsPtr = 138, + DnsRbl = 139, + DnsServer = 130, + DnsServerId = 300, + DnsTlsa = 140, + DnsTxt = 141, + DnsZoneFile = 345, + DocumentId = 804, + DocumentType = 814, + Domain = 232, + DomainId = 221, + DomainLimit = 750, + DomainNames = 147, + DomainNamesNegative = 148, + Domains = 146, + Dsn = 519, + Due = 797, + DuplicateExpiry = 699, + Duration = 515, + EabHmacKey = 13, + EabKeyId = 14, + EhloDomain = 283, + EhloHostname = 503, + EhloTimeout = 507, + Elapsed = 296, + Else = 375, + Email = 242, + EmailAddress = 393, + EmailAddresses = 149, + EmailAddressesNegative = 150, + EmailAlert = 35, + EmailDomain = 488, + EmailLimit = 751, + EmailPrefix = 487, + EmailTemplate = 174, + Enable = 37, + EnableAssistedDiscovery = 865, + EnableEdns = 305, + EnableHsts = 399, + EnableLogExporter = 860, + EnableSpamFilter = 562, + EnableSpanExporter = 861, + Enabled = 50, + EnabledPermissions = 628, + EncryptAtRest = 358, + EncryptOnAppend = 357, + EncryptionAtRest = 9, + EncryptionKey = 622, + Endpoint = 499, + EnvFrom = 742, + EnvFromParameters = 743, + EnvId = 639, + EnvRcptTo = 744, + EnvelopeFrom = 264, + EnvelopeTo = 263, + ErrorCommand = 210, + ErrorMessage = 209, + ErrorType = 208, + Errors = 247, + EvaluatedDisposition = 259, + EvaluatedDkim = 260, + EvaluatedSpf = 261, + Event = 372, + EventAlert = 36, + EventEnd = 801, + EventEndTz = 803, + EventId = 799, + EventMessage = 43, + EventSourceThrottle = 447, + EventStart = 800, + EventStartTz = 802, + Events = 142, + EventsPolicy = 855, + Expire = 217, + Expires = 100, + ExpiresAt = 47, + ExpiresAttempts = 632, + Expiry = 512, + Expn = 520, + ExpungeSchedule = 198, + ExpungeSchedulingInboxAfter = 197, + ExpungeShareNotifyAfter = 196, + ExpungeSubmissionsAfter = 195, + ExpungeTrashAfter = 194, + Extension = 754, + Extensions = 257, + ExtraContactInfo = 243, + Factor = 821, + FailOnTimeout = 490, + FailedAt = 826, + FailedAttemptNumber = 827, + FailedSessionCount = 837, + FailureDetails = 851, + FailureDkimSignDomain = 279, + FailureFromAddress = 276, + FailureFromName = 277, + FailureReason = 828, + FailureReasonCode = 839, + FailureSendFrequency = 278, + FailureSubject = 280, + FeatureL2Normalize = 738, + FeatureLogScale = 739, + FeedbackType = 67, + FieldEmail = 406, + FieldHoneyPot = 407, + FieldName = 409, + FieldSubject = 412, + FilePath = 676, + Files = 144, + FilterLogin = 467, + FilterMailbox = 468, + FilterMemberOf = 469, + Flags = 638, + FlagsAction = 537, + FlagsProtocol = 538, + ForDomain = 485, + Format = 415, + From = 62, + FromAddress = 39, + FromEmail = 165, + FromName = 40, + FutureRelease = 521, + GenerateDkimKeys = 124, + GeoUrls = 103, + GetMaxResults = 436, + GreetingTimeout = 508, + GreylistFor = 770, + GroupClass = 477, + GroupId = 460, + HeaderFrom = 265, + Headers = 93, + HoldMetricsFor = 206, + HoldMtaReportsFor = 204, + HoldSamplesFor = 730, + HoldTracesFor = 205, + Host = 333, + HostedZoneId = 331, + Hostname = 185, + Hour = 190, + HttpAuth = 32, + HttpHeaders = 33, + HttpRsvpEnable = 168, + HttpRsvpLinkExpiry = 169, + HttpRsvpTemplate = 175, + HttpRsvpUrl = 170, + HttpRua = 842, + HumanResult = 234, + ICalendarData = 807, + Id = 1, + IdTokenExpiry = 621, + IdentityAlignment = 91, + If = 376, + ImpersonateServiceAccount = 320, + ImplicitTls = 546, + InMemoryStore = 128, + InboundReportAddresses = 651, + InboundReportForwarding = 652, + Incidents = 70, + IncludeSource = 352, + IndexAsn = 94, + IndexAsnName = 95, + IndexBatchSize = 664, + IndexCalendar = 667, + IndexCalendarFields = 668, + IndexContactFields = 670, + IndexContacts = 669, + IndexCountry = 96, + IndexEmail = 671, + IndexEmailFields = 672, + IndexKey = 421, + IndexTelemetry = 673, + IndexTracingFields = 674, + IndexValue = 422, + IndicatorParameters = 736, + InitialDelay = 822, + Interval = 500, + Intervals = 516, + IpLimit = 752, + IpLookupStrategy = 543, + IpRevPtr = 290, + IpRevResult = 289, + IsActive = 707, + IsArchive = 755, + IsBad = 756, + IsEnabled = 340, + IsFromOrganizer = 806, + IsGlobPattern = 491, + IsGzipped = 416, + IsNz = 757, + IsSenderAllowed = 564, + IsSpam = 776, + IsTls = 741, + Issuer = 181, + IssuerUrl = 606, + ItipMaxSize = 172, + Jitter = 824, + Key = 334, + KeyName = 337, + KeyPrefix = 120, + KeyValues = 853, + L1Ratio = 391, + L2Ratio = 392, + LastRenewal = 186, + LearnHamFromCard = 727, + LearnHamFromReply = 735, + LearnSpamFromRblHits = 728, + LearnSpamFromTraps = 729, + Level = 373, + LicenseKey = 370, + ListenerIds = 183, + Listeners = 188, + LivePropertyMaxSize = 869, + Locale = 7, + Logo = 341, + LogoUrl = 371, + LoiterBanPeriod = 682, + LoiterBanRate = 681, + Lossy = 854, + MachineId = 384, + MailExchangers = 793, + MailFrom = 284, + MailFromTimeout = 509, + MailRua = 841, + MailingLists = 154, + MaintenanceType = 796, + ManagedZone = 318, + Match = 374, + MaxAddressBooks = 23, + MaxAge = 566, + MaxAllowedPacket = 576, + MaxApiKeys = 115, + MaxAppPasswords = 114, + MaxAttachmentSize = 353, + MaxAttempts = 511, + MaxAttendees = 157, + MaxAuthFailures = 425, + MaxCalendars = 160, + MaxChangesHistory = 201, + MaxConcurrent = 426, + MaxConcurrentRequests = 439, + MaxConcurrentUploads = 442, + MaxConnections = 603, + MaxContacts = 24, + MaxCpuCycles = 702, + MaxDelay = 823, + MaxDuration = 530, + MaxEntries = 417, + MaxEntrySize = 418, + MaxEventNotifications = 163, + MaxEvents = 161, + MaxFailures = 547, + MaxFiles = 378, + MaxFolders = 379, + MaxHeaderSize = 715, + MaxICalendarSize = 159, + MaxIdentities = 363, + MaxIncludes = 716, + MaxLocalVars = 717, + MaxLockTimeout = 866, + MaxLocks = 867, + MaxMailboxDepth = 355, + MaxMailboxNameLength = 356, + MaxMailboxes = 364, + MaxMaskedAddresses = 365, + MaxMatchVars = 718, + MaxMessageSize = 354, + MaxMessages = 361, + MaxMethodCalls = 438, + MaxMultihomed = 544, + MaxMxHosts = 545, + MaxNestedBlocks = 720, + MaxNestedForEvery = 721, + MaxNestedIncludes = 703, + MaxNestedTests = 722, + MaxOutMessages = 704, + MaxParticipantIdentities = 162, + MaxPublicKeys = 366, + MaxReceivedHeaders = 561, + MaxRecipients = 173, + MaxReconnects = 580, + MaxRecurrenceExpansions = 158, + MaxRedirects = 705, + MaxReportSize = 852, + MaxRequestRate = 427, + MaxRequestSize = 428, + MaxResponseSize = 527, + MaxResults = 871, + MaxRetries = 18, + MaxRetryWait = 648, + MaxScriptNameLength = 719, + MaxScriptSize = 723, + MaxScripts = 726, + MaxShares = 696, + MaxSize = 101, + MaxStringLength = 724, + MaxSubmissions = 362, + MaxSubscriptions = 458, + MaxUploadCount = 444, + MaxUploadSize = 443, + MaxVCardSize = 22, + MaxVarNameLength = 725, + MaxVarSize = 706, + MemberGroupIds = 864, + MemberTenantId = 19, + Message = 92, + MessageIdHostname = 698, + MessageIds = 819, + Messages = 145, + Metric = 493, + Metrics = 497, + MetricsCollectionInterval = 207, + MetricsPolicy = 498, + MinHamSamples = 731, + MinRetryWait = 649, + MinSpamSamples = 732, + MinTriggerInterval = 166, + Minute = 191, + Mode = 567, + Model = 28, + ModelId = 764, + ModelType = 30, + MtPriority = 522, + MtaSts = 570, + MtaStsTimeout = 572, + Multiline = 859, + MustMatchSender = 550, + MxHosts = 568, + Name = 25, + Namespace = 414, + NegativeTtl = 156, + NextNotify = 634, + NextRetry = 633, + NextTransitionAt = 223, + NoCapabilityCheck = 700, + NoEcho = 587, + NoSoliciting = 523, + NodeId = 184, + NotValidAfter = 179, + NotValidBefore = 180, + Notify = 513, + NotifyCount = 642, + NotifyDue = 643, + NumFeatures = 390, + NumReplicas = 350, + NumShards = 351, + OnSuccessRenewCertificate = 813, + OpenTelemetry = 495, + Options = 630, + Orcpt = 645, + OrgName = 241, + OrganizationName = 843, + Origin = 301, + OriginalEnvelopeId = 71, + OriginalMailFrom = 72, + OriginalRcptTo = 73, + OtpAuth = 5, + OtpCode = 625, + OtpUrl = 626, + OutboundReportDomain = 653, + OutboundReportSubmitter = 654, + OverrideProxyTrustedNetworks = 590, + OverrideType = 239, + OvhEndpoint = 324, + Parameters = 737, + ParseLimitContact = 433, + ParseLimitEmail = 434, + ParseLimitEvent = 432, + PasswordDefaultExpiry = 113, + PasswordHashAlgorithm = 109, + PasswordMaxLength = 111, + PasswordMinLength = 110, + PasswordMinStrength = 112, + Path = 380, + Period = 646, + Permissions = 48, + PingInterval = 583, + Pipelining = 524, + Policies = 846, + PolicyAdkim = 250, + PolicyAspf = 251, + PolicyDisposition = 252, + PolicyDomain = 248, + PolicyFailureReportingOptions = 255, + PolicyIdentifier = 237, + PolicyIdentifiers = 840, + PolicyOverrideReasons = 262, + PolicyStrings = 848, + PolicySubdomainDisposition = 253, + PolicyTestingMode = 254, + PolicyType = 847, + PolicyVersion = 249, + PollInterval = 489, + PollingInterval = 311, + PoolMaxConnections = 478, + PoolMinConnections = 577, + PoolRecyclingMethod = 631, + PoolTimeoutCreate = 479, + PoolTimeoutRecycle = 480, + PoolTimeoutWait = 481, + PoolWorkers = 657, + Port = 299, + Prefix = 856, + PreserveIntermediates = 306, + Priority = 483, + PrivateKey = 177, + PrivateZone = 319, + PrivateZoneOnly = 332, + Profile = 661, + ProjectId = 317, + Prometheus = 496, + Prompt = 765, + PropagationDelay = 313, + PropagationTimeout = 312, + ProtectedHeaders = 713, + Protocol = 298, + ProtocolVersion = 533, + ProviderInfo = 795, + ProxyTrustedNetworks = 792, + PublicKey = 218, + PublishRecords = 302, + PushAttemptWait = 448, + PushMaxAttempts = 449, + PushRequestTimeout = 452, + PushRetryWait = 450, + PushShardsTotal = 454, + PushThrottle = 451, + PushVerifyTimeout = 453, + QueryEmailAliases = 786, + QueryLogin = 783, + QueryMaxResults = 437, + QueryMemberOf = 785, + QueryRecipient = 784, + QueueId = 514, + QueueName = 644, + Quotas = 394, + Rate = 532, + RateLimit = 410, + RateLimitAnonymous = 397, + RateLimitAuthenticated = 396, + Ratio = 767, + RcptToTimeout = 510, + ReadFromReplicas = 650, + ReadReplicas = 578, + Reason = 45, + ReceivedAt = 63, + ReceivedFromIp = 636, + ReceivedViaPort = 637, + ReceivingIp = 836, + ReceivingMxHelo = 835, + ReceivingMxHostname = 834, + Recipients = 484, + Records = 256, + RecurrenceId = 805, + RedirectUris = 605, + Refresh = 419, + RefreshTokenExpiry = 617, + RefreshTokenRenewal = 618, + Region = 330, + RejectNonFqdn = 563, + RemoteIp = 282, + RenewBefore = 17, + Report = 66, + ReportAddressUri = 349, + ReportId = 244, + ReportedDomains = 74, + ReportedUris = 75, + ReportingMta = 76, + RequestMaxSize = 870, + RequestTlsCertificate = 123, + Require = 551, + RequireAudience = 607, + RequireClientRegistration = 615, + RequireScopes = 608, + RequireTls = 525, + ReservoirCapacity = 733, + ResourceUrl = 51, + ResponseCode = 212, + ResponseEnhanced = 213, + ResponseHeaders = 401, + ResponseHostname = 211, + ResponseMessage = 214, + ResponsePosCategory = 761, + ResponsePosConfidence = 762, + ResponsePosExplanation = 763, + Result = 233, + ResultType = 832, + RetireAfter = 228, + Retry = 420, + RetryCount = 640, + RetryDue = 641, + ReturnPath = 635, + ReverseIpVerify = 692, + Rewrite = 565, + RoleIds = 193, + Roles = 152, + Rotate = 857, + RotateAfter = 227, + Route = 540, + Rua = 236, + SasToken = 119, + SaslMechanisms = 549, + ScanBanPaths = 683, + ScanBanPeriod = 685, + ScanBanRate = 684, + Schedule = 541, + Scheduling = 143, + Scope = 281, + Score = 745, + ScoreDiscard = 771, + ScoreReject = 772, + ScoreSpam = 773, + Script = 553, + SearchStore = 127, + Secret = 3, + SecretAccessKey = 328, + SecretApiKey = 326, + SecretKey = 659, + SecurityToken = 660, + Selector = 222, + SelectorTemplate = 226, + SendFrequency = 230, + SendingMtaIp = 833, + Separator = 97, + ServerHostname = 121, + Servers = 308, + ServiceAccountJson = 316, + Services = 794, + SessionToken = 329, + SetMaxObjects = 440, + ShardIndex = 830, + Sig0Algorithm = 336, + SignatureAlgorithm = 623, + SignatureKey = 624, + SignerName = 335, + Size = 64, + SkipFirst = 423, + SmtpGreeting = 552, + SnippetMaxResults = 441, + SocketBacklog = 591, + SocketNoDelay = 592, + SocketReceiveBufferSize = 593, + SocketReuseAddress = 594, + SocketReusePort = 595, + SocketSendBufferSize = 596, + SocketTosV4 = 597, + SocketTtl = 598, + SourceIp = 77, + SourceIps = 504, + SourcePort = 78, + SpamFilterRulesUrl = 775, + SpfDns = 90, + SpfEhloDomain = 285, + SpfEhloResult = 286, + SpfEhloVerify = 688, + SpfFromVerify = 689, + SpfMailFromDomain = 287, + SpfMailFromResult = 288, + SpfResults = 267, + Stage = 224, + Stages = 529, + StartTime = 56, + StartTls = 571, + Status = 61, + StorageAccount = 116, + Store = 778, + Stores = 694, + Strategy = 816, + SubAddressing = 347, + Subject = 41, + SubjectAlternativeNames = 178, + Subscribe = 368, + Sum = 494, + Summary = 808, + Tag = 748, + Tags = 746, + TaskTypes = 189, + Tasks = 187, + TcpOnError = 307, + TempFailOnError = 528, + Temperature = 27, + Template = 167, + TenantId = 831, + Tenants = 153, + Text = 2, + Then = 377, + ThirdParty = 219, + ThirdPartyHash = 220, + ThreadName = 818, + ThreadPoolSize = 791, + ThreadsPerNode = 574, + Throttle = 862, + TimeZone = 8, + Timeout = 29, + TimeoutAnonymous = 429, + TimeoutAuthenticated = 430, + TimeoutCommand = 534, + TimeoutConnect = 535, + TimeoutConnection = 581, + TimeoutData = 536, + TimeoutIdle = 431, + TimeoutMessage = 461, + TimeoutRequest = 582, + TimeoutSession = 462, + Timestamp = 482, + Title = 55, + Tls = 542, + TlsDisableCipherSuites = 599, + TlsDisableProtocols = 600, + TlsIgnoreClientOrder = 601, + TlsImplicit = 602, + TlsTimeout = 573, + To = 42, + TotalDeadline = 817, + TotalFailedSessions = 850, + TotalSuccessfulSessions = 849, + TraceId = 815, + Tracer = 129, + TrainFrequency = 734, + TransactionRetryDelay = 385, + TransactionRetryLimit = 386, + TransactionTimeout = 387, + TransferLimit = 531, + TrustContacts = 769, + TrustReplies = 774, + TsigAlgorithm = 338, + Ttl = 310, + UnpackDirectory = 54, + UpdateRecords = 812, + UploadQuota = 445, + UploadTtl = 446, + Url = 31, + UrlLimit = 753, + UrlPrefix = 52, + Urls = 647, + UsePermissiveCors = 400, + UseTls = 309, + UseXForwarded = 402, + UsedDiskQuota = 395, + UserAgent = 79, + UserCodeExpiry = 620, + Username = 131, + UsernameDomain = 610, + ValidateDomain = 413, + Value = 492, + VariableName = 675, + Version = 80, + Vrfy = 526, + WaitOnFail = 548, + WebsocketHeartbeat = 455, + WebsocketThrottle = 456, + WebsocketTimeout = 457, + Zone = 749, + ZoneIpV4 = 98, + ZoneIpV6 = 99, +} diff --git a/crates/registry/src/schema/properties_impl.rs b/crates/registry/src/schema/properties_impl.rs new file mode 100644 index 00000000..603f9e6f --- /dev/null +++ b/crates/registry/src/schema/properties_impl.rs @@ -0,0 +1,7599 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +use crate::schema::prelude::*; + +impl EnumImpl for ObjectType { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"Account" => ObjectType::Account, + b"AccountPassword" => ObjectType::AccountPassword, + b"AccountSettings" => ObjectType::AccountSettings, + b"AcmeProvider" => ObjectType::AcmeProvider, + b"Action" => ObjectType::Action, + b"AddressBook" => ObjectType::AddressBook, + b"AiModel" => ObjectType::AiModel, + b"Alert" => ObjectType::Alert, + b"AllowedIp" => ObjectType::AllowedIp, + b"ApiKey" => ObjectType::ApiKey, + b"AppPassword" => ObjectType::AppPassword, + b"Application" => ObjectType::Application, + b"ArchivedItem" => ObjectType::ArchivedItem, + b"ArfExternalReport" => ObjectType::ArfExternalReport, + b"Asn" => ObjectType::Asn, + b"Authentication" => ObjectType::Authentication, + b"BlobStore" => ObjectType::BlobStore, + b"BlockedIp" => ObjectType::BlockedIp, + b"Bootstrap" => ObjectType::Bootstrap, + b"Cache" => ObjectType::Cache, + b"Calendar" => ObjectType::Calendar, + b"CalendarAlarm" => ObjectType::CalendarAlarm, + b"CalendarScheduling" => ObjectType::CalendarScheduling, + b"Certificate" => ObjectType::Certificate, + b"ClusterNode" => ObjectType::ClusterNode, + b"ClusterRole" => ObjectType::ClusterRole, + b"Coordinator" => ObjectType::Coordinator, + b"DataRetention" => ObjectType::DataRetention, + b"DataStore" => ObjectType::DataStore, + b"Directory" => ObjectType::Directory, + b"DkimReportSettings" => ObjectType::DkimReportSettings, + b"DkimSignature" => ObjectType::DkimSignature, + b"DmarcExternalReport" => ObjectType::DmarcExternalReport, + b"DmarcInternalReport" => ObjectType::DmarcInternalReport, + b"DmarcReportSettings" => ObjectType::DmarcReportSettings, + b"DnsResolver" => ObjectType::DnsResolver, + b"DnsServer" => ObjectType::DnsServer, + b"Domain" => ObjectType::Domain, + b"DsnReportSettings" => ObjectType::DsnReportSettings, + b"Email" => ObjectType::Email, + b"Enterprise" => ObjectType::Enterprise, + b"EventTracingLevel" => ObjectType::EventTracingLevel, + b"FileStorage" => ObjectType::FileStorage, + b"Http" => ObjectType::Http, + b"HttpForm" => ObjectType::HttpForm, + b"HttpLookup" => ObjectType::HttpLookup, + b"Imap" => ObjectType::Imap, + b"InMemoryStore" => ObjectType::InMemoryStore, + b"Jmap" => ObjectType::Jmap, + b"Log" => ObjectType::Log, + b"MailingList" => ObjectType::MailingList, + b"MaskedEmail" => ObjectType::MaskedEmail, + b"MemoryLookupKey" => ObjectType::MemoryLookupKey, + b"MemoryLookupKeyValue" => ObjectType::MemoryLookupKeyValue, + b"Metric" => ObjectType::Metric, + b"Metrics" => ObjectType::Metrics, + b"MetricsStore" => ObjectType::MetricsStore, + b"MtaConnectionStrategy" => ObjectType::MtaConnectionStrategy, + b"MtaDeliverySchedule" => ObjectType::MtaDeliverySchedule, + b"MtaExtensions" => ObjectType::MtaExtensions, + b"MtaHook" => ObjectType::MtaHook, + b"MtaInboundSession" => ObjectType::MtaInboundSession, + b"MtaInboundThrottle" => ObjectType::MtaInboundThrottle, + b"MtaMilter" => ObjectType::MtaMilter, + b"MtaOutboundStrategy" => ObjectType::MtaOutboundStrategy, + b"MtaOutboundThrottle" => ObjectType::MtaOutboundThrottle, + b"MtaQueueQuota" => ObjectType::MtaQueueQuota, + b"MtaRoute" => ObjectType::MtaRoute, + b"MtaStageAuth" => ObjectType::MtaStageAuth, + b"MtaStageConnect" => ObjectType::MtaStageConnect, + b"MtaStageData" => ObjectType::MtaStageData, + b"MtaStageEhlo" => ObjectType::MtaStageEhlo, + b"MtaStageMail" => ObjectType::MtaStageMail, + b"MtaStageRcpt" => ObjectType::MtaStageRcpt, + b"MtaSts" => ObjectType::MtaSts, + b"MtaTlsStrategy" => ObjectType::MtaTlsStrategy, + b"MtaVirtualQueue" => ObjectType::MtaVirtualQueue, + b"NetworkListener" => ObjectType::NetworkListener, + b"OAuthClient" => ObjectType::OAuthClient, + b"OidcProvider" => ObjectType::OidcProvider, + b"PublicKey" => ObjectType::PublicKey, + b"QueuedMessage" => ObjectType::QueuedMessage, + b"ReportSettings" => ObjectType::ReportSettings, + b"Role" => ObjectType::Role, + b"Search" => ObjectType::Search, + b"SearchStore" => ObjectType::SearchStore, + b"Security" => ObjectType::Security, + b"SenderAuth" => ObjectType::SenderAuth, + b"Sharing" => ObjectType::Sharing, + b"SieveSystemInterpreter" => ObjectType::SieveSystemInterpreter, + b"SieveSystemScript" => ObjectType::SieveSystemScript, + b"SieveUserInterpreter" => ObjectType::SieveUserInterpreter, + b"SieveUserScript" => ObjectType::SieveUserScript, + b"SpamClassifier" => ObjectType::SpamClassifier, + b"SpamDnsblServer" => ObjectType::SpamDnsblServer, + b"SpamDnsblSettings" => ObjectType::SpamDnsblSettings, + b"SpamFileExtension" => ObjectType::SpamFileExtension, + b"SpamLlm" => ObjectType::SpamLlm, + b"SpamPyzor" => ObjectType::SpamPyzor, + b"SpamRule" => ObjectType::SpamRule, + b"SpamSettings" => ObjectType::SpamSettings, + b"SpamTag" => ObjectType::SpamTag, + b"SpamTrainingSample" => ObjectType::SpamTrainingSample, + b"SpfReportSettings" => ObjectType::SpfReportSettings, + b"StoreLookup" => ObjectType::StoreLookup, + b"SystemSettings" => ObjectType::SystemSettings, + b"Task" => ObjectType::Task, + b"TaskManager" => ObjectType::TaskManager, + b"Tenant" => ObjectType::Tenant, + b"TlsExternalReport" => ObjectType::TlsExternalReport, + b"TlsInternalReport" => ObjectType::TlsInternalReport, + b"TlsReportSettings" => ObjectType::TlsReportSettings, + b"Trace" => ObjectType::Trace, + b"Tracer" => ObjectType::Tracer, + b"TracingStore" => ObjectType::TracingStore, + b"WebDav" => ObjectType::WebDav, + b"WebHook" => ObjectType::WebHook, + } + } + + fn as_str(&self) -> &'static str { + match self { + ObjectType::Account => "Account", + ObjectType::AccountPassword => "AccountPassword", + ObjectType::AccountSettings => "AccountSettings", + ObjectType::AcmeProvider => "AcmeProvider", + ObjectType::Action => "Action", + ObjectType::AddressBook => "AddressBook", + ObjectType::AiModel => "AiModel", + ObjectType::Alert => "Alert", + ObjectType::AllowedIp => "AllowedIp", + ObjectType::ApiKey => "ApiKey", + ObjectType::AppPassword => "AppPassword", + ObjectType::Application => "Application", + ObjectType::ArchivedItem => "ArchivedItem", + ObjectType::ArfExternalReport => "ArfExternalReport", + ObjectType::Asn => "Asn", + ObjectType::Authentication => "Authentication", + ObjectType::BlobStore => "BlobStore", + ObjectType::BlockedIp => "BlockedIp", + ObjectType::Bootstrap => "Bootstrap", + ObjectType::Cache => "Cache", + ObjectType::Calendar => "Calendar", + ObjectType::CalendarAlarm => "CalendarAlarm", + ObjectType::CalendarScheduling => "CalendarScheduling", + ObjectType::Certificate => "Certificate", + ObjectType::ClusterNode => "ClusterNode", + ObjectType::ClusterRole => "ClusterRole", + ObjectType::Coordinator => "Coordinator", + ObjectType::DataRetention => "DataRetention", + ObjectType::DataStore => "DataStore", + ObjectType::Directory => "Directory", + ObjectType::DkimReportSettings => "DkimReportSettings", + ObjectType::DkimSignature => "DkimSignature", + ObjectType::DmarcExternalReport => "DmarcExternalReport", + ObjectType::DmarcInternalReport => "DmarcInternalReport", + ObjectType::DmarcReportSettings => "DmarcReportSettings", + ObjectType::DnsResolver => "DnsResolver", + ObjectType::DnsServer => "DnsServer", + ObjectType::Domain => "Domain", + ObjectType::DsnReportSettings => "DsnReportSettings", + ObjectType::Email => "Email", + ObjectType::Enterprise => "Enterprise", + ObjectType::EventTracingLevel => "EventTracingLevel", + ObjectType::FileStorage => "FileStorage", + ObjectType::Http => "Http", + ObjectType::HttpForm => "HttpForm", + ObjectType::HttpLookup => "HttpLookup", + ObjectType::Imap => "Imap", + ObjectType::InMemoryStore => "InMemoryStore", + ObjectType::Jmap => "Jmap", + ObjectType::Log => "Log", + ObjectType::MailingList => "MailingList", + ObjectType::MaskedEmail => "MaskedEmail", + ObjectType::MemoryLookupKey => "MemoryLookupKey", + ObjectType::MemoryLookupKeyValue => "MemoryLookupKeyValue", + ObjectType::Metric => "Metric", + ObjectType::Metrics => "Metrics", + ObjectType::MetricsStore => "MetricsStore", + ObjectType::MtaConnectionStrategy => "MtaConnectionStrategy", + ObjectType::MtaDeliverySchedule => "MtaDeliverySchedule", + ObjectType::MtaExtensions => "MtaExtensions", + ObjectType::MtaHook => "MtaHook", + ObjectType::MtaInboundSession => "MtaInboundSession", + ObjectType::MtaInboundThrottle => "MtaInboundThrottle", + ObjectType::MtaMilter => "MtaMilter", + ObjectType::MtaOutboundStrategy => "MtaOutboundStrategy", + ObjectType::MtaOutboundThrottle => "MtaOutboundThrottle", + ObjectType::MtaQueueQuota => "MtaQueueQuota", + ObjectType::MtaRoute => "MtaRoute", + ObjectType::MtaStageAuth => "MtaStageAuth", + ObjectType::MtaStageConnect => "MtaStageConnect", + ObjectType::MtaStageData => "MtaStageData", + ObjectType::MtaStageEhlo => "MtaStageEhlo", + ObjectType::MtaStageMail => "MtaStageMail", + ObjectType::MtaStageRcpt => "MtaStageRcpt", + ObjectType::MtaSts => "MtaSts", + ObjectType::MtaTlsStrategy => "MtaTlsStrategy", + ObjectType::MtaVirtualQueue => "MtaVirtualQueue", + ObjectType::NetworkListener => "NetworkListener", + ObjectType::OAuthClient => "OAuthClient", + ObjectType::OidcProvider => "OidcProvider", + ObjectType::PublicKey => "PublicKey", + ObjectType::QueuedMessage => "QueuedMessage", + ObjectType::ReportSettings => "ReportSettings", + ObjectType::Role => "Role", + ObjectType::Search => "Search", + ObjectType::SearchStore => "SearchStore", + ObjectType::Security => "Security", + ObjectType::SenderAuth => "SenderAuth", + ObjectType::Sharing => "Sharing", + ObjectType::SieveSystemInterpreter => "SieveSystemInterpreter", + ObjectType::SieveSystemScript => "SieveSystemScript", + ObjectType::SieveUserInterpreter => "SieveUserInterpreter", + ObjectType::SieveUserScript => "SieveUserScript", + ObjectType::SpamClassifier => "SpamClassifier", + ObjectType::SpamDnsblServer => "SpamDnsblServer", + ObjectType::SpamDnsblSettings => "SpamDnsblSettings", + ObjectType::SpamFileExtension => "SpamFileExtension", + ObjectType::SpamLlm => "SpamLlm", + ObjectType::SpamPyzor => "SpamPyzor", + ObjectType::SpamRule => "SpamRule", + ObjectType::SpamSettings => "SpamSettings", + ObjectType::SpamTag => "SpamTag", + ObjectType::SpamTrainingSample => "SpamTrainingSample", + ObjectType::SpfReportSettings => "SpfReportSettings", + ObjectType::StoreLookup => "StoreLookup", + ObjectType::SystemSettings => "SystemSettings", + ObjectType::Task => "Task", + ObjectType::TaskManager => "TaskManager", + ObjectType::Tenant => "Tenant", + ObjectType::TlsExternalReport => "TlsExternalReport", + ObjectType::TlsInternalReport => "TlsInternalReport", + ObjectType::TlsReportSettings => "TlsReportSettings", + ObjectType::Trace => "Trace", + ObjectType::Tracer => "Tracer", + ObjectType::TracingStore => "TracingStore", + ObjectType::WebDav => "WebDav", + ObjectType::WebHook => "WebHook", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(ObjectType::Account), + 1 => Some(ObjectType::AccountPassword), + 2 => Some(ObjectType::AccountSettings), + 3 => Some(ObjectType::AcmeProvider), + 4 => Some(ObjectType::Action), + 5 => Some(ObjectType::AddressBook), + 6 => Some(ObjectType::AiModel), + 7 => Some(ObjectType::Alert), + 8 => Some(ObjectType::AllowedIp), + 9 => Some(ObjectType::ApiKey), + 10 => Some(ObjectType::AppPassword), + 11 => Some(ObjectType::Application), + 12 => Some(ObjectType::ArchivedItem), + 13 => Some(ObjectType::ArfExternalReport), + 14 => Some(ObjectType::Asn), + 15 => Some(ObjectType::Authentication), + 16 => Some(ObjectType::BlobStore), + 17 => Some(ObjectType::BlockedIp), + 18 => Some(ObjectType::Bootstrap), + 19 => Some(ObjectType::Cache), + 20 => Some(ObjectType::Calendar), + 21 => Some(ObjectType::CalendarAlarm), + 22 => Some(ObjectType::CalendarScheduling), + 23 => Some(ObjectType::Certificate), + 24 => Some(ObjectType::ClusterNode), + 25 => Some(ObjectType::ClusterRole), + 26 => Some(ObjectType::Coordinator), + 27 => Some(ObjectType::DataRetention), + 28 => Some(ObjectType::DataStore), + 29 => Some(ObjectType::Directory), + 30 => Some(ObjectType::DkimReportSettings), + 31 => Some(ObjectType::DkimSignature), + 32 => Some(ObjectType::DmarcExternalReport), + 33 => Some(ObjectType::DmarcInternalReport), + 34 => Some(ObjectType::DmarcReportSettings), + 35 => Some(ObjectType::DnsResolver), + 36 => Some(ObjectType::DnsServer), + 37 => Some(ObjectType::Domain), + 38 => Some(ObjectType::DsnReportSettings), + 39 => Some(ObjectType::Email), + 40 => Some(ObjectType::Enterprise), + 41 => Some(ObjectType::EventTracingLevel), + 42 => Some(ObjectType::FileStorage), + 43 => Some(ObjectType::Http), + 44 => Some(ObjectType::HttpForm), + 45 => Some(ObjectType::HttpLookup), + 46 => Some(ObjectType::Imap), + 47 => Some(ObjectType::InMemoryStore), + 48 => Some(ObjectType::Jmap), + 49 => Some(ObjectType::Log), + 50 => Some(ObjectType::MailingList), + 51 => Some(ObjectType::MaskedEmail), + 52 => Some(ObjectType::MemoryLookupKey), + 53 => Some(ObjectType::MemoryLookupKeyValue), + 54 => Some(ObjectType::Metric), + 55 => Some(ObjectType::Metrics), + 56 => Some(ObjectType::MetricsStore), + 57 => Some(ObjectType::MtaConnectionStrategy), + 58 => Some(ObjectType::MtaDeliverySchedule), + 59 => Some(ObjectType::MtaExtensions), + 60 => Some(ObjectType::MtaHook), + 61 => Some(ObjectType::MtaInboundSession), + 62 => Some(ObjectType::MtaInboundThrottle), + 63 => Some(ObjectType::MtaMilter), + 64 => Some(ObjectType::MtaOutboundStrategy), + 65 => Some(ObjectType::MtaOutboundThrottle), + 66 => Some(ObjectType::MtaQueueQuota), + 67 => Some(ObjectType::MtaRoute), + 68 => Some(ObjectType::MtaStageAuth), + 69 => Some(ObjectType::MtaStageConnect), + 70 => Some(ObjectType::MtaStageData), + 71 => Some(ObjectType::MtaStageEhlo), + 72 => Some(ObjectType::MtaStageMail), + 73 => Some(ObjectType::MtaStageRcpt), + 74 => Some(ObjectType::MtaSts), + 75 => Some(ObjectType::MtaTlsStrategy), + 76 => Some(ObjectType::MtaVirtualQueue), + 77 => Some(ObjectType::NetworkListener), + 78 => Some(ObjectType::OAuthClient), + 79 => Some(ObjectType::OidcProvider), + 80 => Some(ObjectType::PublicKey), + 81 => Some(ObjectType::QueuedMessage), + 82 => Some(ObjectType::ReportSettings), + 83 => Some(ObjectType::Role), + 84 => Some(ObjectType::Search), + 85 => Some(ObjectType::SearchStore), + 86 => Some(ObjectType::Security), + 87 => Some(ObjectType::SenderAuth), + 88 => Some(ObjectType::Sharing), + 89 => Some(ObjectType::SieveSystemInterpreter), + 90 => Some(ObjectType::SieveSystemScript), + 91 => Some(ObjectType::SieveUserInterpreter), + 92 => Some(ObjectType::SieveUserScript), + 93 => Some(ObjectType::SpamClassifier), + 94 => Some(ObjectType::SpamDnsblServer), + 95 => Some(ObjectType::SpamDnsblSettings), + 96 => Some(ObjectType::SpamFileExtension), + 97 => Some(ObjectType::SpamLlm), + 98 => Some(ObjectType::SpamPyzor), + 99 => Some(ObjectType::SpamRule), + 100 => Some(ObjectType::SpamSettings), + 101 => Some(ObjectType::SpamTag), + 102 => Some(ObjectType::SpamTrainingSample), + 103 => Some(ObjectType::SpfReportSettings), + 104 => Some(ObjectType::StoreLookup), + 105 => Some(ObjectType::SystemSettings), + 106 => Some(ObjectType::Task), + 107 => Some(ObjectType::TaskManager), + 108 => Some(ObjectType::Tenant), + 109 => Some(ObjectType::TlsExternalReport), + 110 => Some(ObjectType::TlsInternalReport), + 111 => Some(ObjectType::TlsReportSettings), + 112 => Some(ObjectType::Trace), + 113 => Some(ObjectType::Tracer), + 114 => Some(ObjectType::TracingStore), + 115 => Some(ObjectType::WebDav), + 116 => Some(ObjectType::WebHook), + _ => None, + } + } + + const COUNT: usize = 117; +} + +impl serde::Serialize for ObjectType { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for ObjectType { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl EnumImpl for Property { + fn parse(value: &str) -> Option { + hashify::tiny_map! { + value.as_bytes(), + b"@type" => Property::Type, + b"abuseBanPeriod" => Property::AbuseBanPeriod, + b"abuseBanRate" => Property::AbuseBanRate, + b"accessKey" => Property::AccessKey, + b"accessKeyId" => Property::AccessKeyId, + b"accessTokenExpiry" => Property::AccessTokenExpiry, + b"accessTokens" => Property::AccessTokens, + b"accountDomainId" => Property::AccountDomainId, + b"accountId" => Property::AccountId, + b"accountIdentifier" => Property::AccountIdentifier, + b"accountKey" => Property::AccountKey, + b"accountName" => Property::AccountName, + b"accountType" => Property::AccountType, + b"accountUri" => Property::AccountUri, + b"accounts" => Property::Accounts, + b"acmeProviderId" => Property::AcmeProviderId, + b"addAuthResultsHeader" => Property::AddAuthResultsHeader, + b"addDateHeader" => Property::AddDateHeader, + b"addDeliveredToHeader" => Property::AddDeliveredToHeader, + b"addMessageIdHeader" => Property::AddMessageIdHeader, + b"addReceivedHeader" => Property::AddReceivedHeader, + b"addReceivedSpfHeader" => Property::AddReceivedSpfHeader, + b"addReturnPathHeader" => Property::AddReturnPathHeader, + b"additionalInformation" => Property::AdditionalInformation, + b"address" => Property::Address, + b"addresses" => Property::Addresses, + b"aggregateContactInfo" => Property::AggregateContactInfo, + b"aggregateDkimSignDomain" => Property::AggregateDkimSignDomain, + b"aggregateFromAddress" => Property::AggregateFromAddress, + b"aggregateFromName" => Property::AggregateFromName, + b"aggregateMaxReportSize" => Property::AggregateMaxReportSize, + b"aggregateOrgName" => Property::AggregateOrgName, + b"aggregateSendFrequency" => Property::AggregateSendFrequency, + b"aggregateSubject" => Property::AggregateSubject, + b"alarmId" => Property::AlarmId, + b"algorithms" => Property::Algorithms, + b"aliases" => Property::Aliases, + b"allowCount" => Property::AllowCount, + b"allowDirectoryQueries" => Property::AllowDirectoryQueries, + b"allowExternalRcpts" => Property::AllowExternalRcpts, + b"allowInvalidCerts" => Property::AllowInvalidCerts, + b"allowPlainTextAuth" => Property::AllowPlainTextAuth, + b"allowRelaying" => Property::AllowRelaying, + b"allowSpamTraining" => Property::AllowSpamTraining, + b"allowedEndpoints" => Property::AllowedEndpoints, + b"allowedIps" => Property::AllowedIps, + b"allowedNotifyUris" => Property::AllowedNotifyUris, + b"alpha" => Property::Alpha, + b"anonymousClientRegistration" => Property::AnonymousClientRegistration, + b"ansi" => Property::Ansi, + b"apiKey" => Property::ApiKey, + b"applicationKey" => Property::ApplicationKey, + b"applicationSecret" => Property::ApplicationSecret, + b"arcResult" => Property::ArcResult, + b"arcVerify" => Property::ArcVerify, + b"archiveDeletedAccountsFor" => Property::ArchiveDeletedAccountsFor, + b"archiveDeletedItemsFor" => Property::ArchiveDeletedItemsFor, + b"archivedAt" => Property::ArchivedAt, + b"archivedItemType" => Property::ArchivedItemType, + b"archivedUntil" => Property::ArchivedUntil, + b"arrivalDate" => Property::ArrivalDate, + b"asnUrls" => Property::AsnUrls, + b"attemptNumber" => Property::AttemptNumber, + b"attempts" => Property::Attempts, + b"attrClass" => Property::AttrClass, + b"attrDescription" => Property::AttrDescription, + b"attrEmail" => Property::AttrEmail, + b"attrEmailAlias" => Property::AttrEmailAlias, + b"attrMemberOf" => Property::AttrMemberOf, + b"attrSecret" => Property::AttrSecret, + b"attrSecretChanged" => Property::AttrSecretChanged, + b"auid" => Property::Auid, + b"authBanPeriod" => Property::AuthBanPeriod, + b"authBanRate" => Property::AuthBanRate, + b"authCodeExpiry" => Property::AuthCodeExpiry, + b"authCodeMaxAttempts" => Property::AuthCodeMaxAttempts, + b"authFailure" => Property::AuthFailure, + b"authSecret" => Property::AuthSecret, + b"authToken" => Property::AuthToken, + b"authUsername" => Property::AuthUsername, + b"authenticatedAs" => Property::AuthenticatedAs, + b"authenticationResults" => Property::AuthenticationResults, + b"autoAddInvitations" => Property::AutoAddInvitations, + b"autoUpdateFrequency" => Property::AutoUpdateFrequency, + b"baseDn" => Property::BaseDn, + b"bearerToken" => Property::BearerToken, + b"beta" => Property::Beta, + b"bind" => Property::Bind, + b"bindAuthentication" => Property::BindAuthentication, + b"bindDn" => Property::BindDn, + b"bindSecret" => Property::BindSecret, + b"blobCleanupSchedule" => Property::BlobCleanupSchedule, + b"blobId" => Property::BlobId, + b"blobSize" => Property::BlobSize, + b"blobStore" => Property::BlobStore, + b"blockCount" => Property::BlockCount, + b"body" => Property::Body, + b"brokers" => Property::Brokers, + b"bucket" => Property::Bucket, + b"bufferSize" => Property::BufferSize, + b"buffered" => Property::Buffered, + b"canonicalization" => Property::Canonicalization, + b"capacityClient" => Property::CapacityClient, + b"capacityReadBuffer" => Property::CapacityReadBuffer, + b"capacitySubscription" => Property::CapacitySubscription, + b"catchAllAddress" => Property::CatchAllAddress, + b"categories" => Property::Categories, + b"certificate" => Property::Certificate, + b"certificateManagement" => Property::CertificateManagement, + b"challengeType" => Property::ChallengeType, + b"changesMaxResults" => Property::ChangesMaxResults, + b"chunking" => Property::Chunking, + b"claimGroups" => Property::ClaimGroups, + b"claimName" => Property::ClaimName, + b"claimUsername" => Property::ClaimUsername, + b"cleartext" => Property::Cleartext, + b"clientId" => Property::ClientId, + b"clusterFile" => Property::ClusterFile, + b"columnClass" => Property::ColumnClass, + b"columnDescription" => Property::ColumnDescription, + b"columnEmail" => Property::ColumnEmail, + b"columnSecret" => Property::ColumnSecret, + b"comment" => Property::Comment, + b"compressionAlgorithm" => Property::CompressionAlgorithm, + b"concurrency" => Property::Concurrency, + b"condition" => Property::Condition, + b"confidence" => Property::Confidence, + b"config" => Property::Config, + b"connectTimeout" => Property::ConnectTimeout, + b"connection" => Property::Connection, + b"consumerKey" => Property::ConsumerKey, + b"contact" => Property::Contact, + b"contactInfo" => Property::ContactInfo, + b"contacts" => Property::Contacts, + b"container" => Property::Container, + b"content" => Property::Content, + b"contentTypes" => Property::ContentTypes, + b"contents" => Property::Contents, + b"count" => Property::Count, + b"create" => Property::Create, + b"createdAt" => Property::CreatedAt, + b"createdBy" => Property::CreatedBy, + b"credentialId" => Property::CredentialId, + b"credentials" => Property::Credentials, + b"currentSecret" => Property::CurrentSecret, + b"customEndpoint" => Property::CustomEndpoint, + b"customRegion" => Property::CustomRegion, + b"customRule" => Property::CustomRule, + b"dane" => Property::Dane, + b"dataCleanupSchedule" => Property::DataCleanupSchedule, + b"dataStore" => Property::DataStore, + b"dataTimeout" => Property::DataTimeout, + b"database" => Property::Database, + b"datacenterId" => Property::DatacenterId, + b"dateRangeBegin" => Property::DateRangeBegin, + b"dateRangeEnd" => Property::DateRangeEnd, + b"dateRangeStart" => Property::DateRangeStart, + b"day" => Property::Day, + b"deadPropertyMaxSize" => Property::DeadPropertyMaxSize, + b"defaultAdminRoleIds" => Property::DefaultAdminRoleIds, + b"defaultCertificateId" => Property::DefaultCertificateId, + b"defaultDisplayName" => Property::DefaultDisplayName, + b"defaultDomain" => Property::DefaultDomain, + b"defaultDomainId" => Property::DefaultDomainId, + b"defaultExpiryDuplicate" => Property::DefaultExpiryDuplicate, + b"defaultExpiryVacation" => Property::DefaultExpiryVacation, + b"defaultFolders" => Property::DefaultFolders, + b"defaultFromAddress" => Property::DefaultFromAddress, + b"defaultFromName" => Property::DefaultFromName, + b"defaultGroupRoleIds" => Property::DefaultGroupRoleIds, + b"defaultHostname" => Property::DefaultHostname, + b"defaultHrefName" => Property::DefaultHrefName, + b"defaultLanguage" => Property::DefaultLanguage, + b"defaultName" => Property::DefaultName, + b"defaultReturnPath" => Property::DefaultReturnPath, + b"defaultSubject" => Property::DefaultSubject, + b"defaultSubjectPrefix" => Property::DefaultSubjectPrefix, + b"defaultTenantRoleIds" => Property::DefaultTenantRoleIds, + b"defaultUserRoleIds" => Property::DefaultUserRoleIds, + b"definition" => Property::Definition, + b"delay" => Property::Delay, + b"deleteAfter" => Property::DeleteAfter, + b"deleteAfterUse" => Property::DeleteAfterUse, + b"deliverAt" => Property::DeliverAt, + b"deliverBy" => Property::DeliverBy, + b"deliverTo" => Property::DeliverTo, + b"deliveryResult" => Property::DeliveryResult, + b"depth" => Property::Depth, + b"description" => Property::Description, + b"details" => Property::Details, + b"directory" => Property::Directory, + b"directoryId" => Property::DirectoryId, + b"disableCapabilities" => Property::DisableCapabilities, + b"disableLanguages" => Property::DisableLanguages, + b"disabledPermissions" => Property::DisabledPermissions, + b"discardAfter" => Property::DiscardAfter, + b"disposition" => Property::Disposition, + b"dkimAdspDns" => Property::DkimAdspDns, + b"dkimCanonicalizedBody" => Property::DkimCanonicalizedBody, + b"dkimCanonicalizedHeader" => Property::DkimCanonicalizedHeader, + b"dkimDomain" => Property::DkimDomain, + b"dkimIdentity" => Property::DkimIdentity, + b"dkimManagement" => Property::DkimManagement, + b"dkimPass" => Property::DkimPass, + b"dkimResults" => Property::DkimResults, + b"dkimSelector" => Property::DkimSelector, + b"dkimSelectorDns" => Property::DkimSelectorDns, + b"dkimSignDomain" => Property::DkimSignDomain, + b"dkimSignatures" => Property::DkimSignatures, + b"dkimStrict" => Property::DkimStrict, + b"dkimVerify" => Property::DkimVerify, + b"dmarcPass" => Property::DmarcPass, + b"dmarcPolicy" => Property::DmarcPolicy, + b"dmarcResult" => Property::DmarcResult, + b"dmarcVerify" => Property::DmarcVerify, + b"dnsIpv4" => Property::DnsIpv4, + b"dnsIpv6" => Property::DnsIpv6, + b"dnsManagement" => Property::DnsManagement, + b"dnsMtaSts" => Property::DnsMtaSts, + b"dnsMx" => Property::DnsMx, + b"dnsPtr" => Property::DnsPtr, + b"dnsRbl" => Property::DnsRbl, + b"dnsServer" => Property::DnsServer, + b"dnsServerId" => Property::DnsServerId, + b"dnsTlsa" => Property::DnsTlsa, + b"dnsTxt" => Property::DnsTxt, + b"dnsZoneFile" => Property::DnsZoneFile, + b"documentId" => Property::DocumentId, + b"documentType" => Property::DocumentType, + b"domain" => Property::Domain, + b"domainId" => Property::DomainId, + b"domainLimit" => Property::DomainLimit, + b"domainNames" => Property::DomainNames, + b"domainNamesNegative" => Property::DomainNamesNegative, + b"domains" => Property::Domains, + b"dsn" => Property::Dsn, + b"due" => Property::Due, + b"duplicateExpiry" => Property::DuplicateExpiry, + b"duration" => Property::Duration, + b"eabHmacKey" => Property::EabHmacKey, + b"eabKeyId" => Property::EabKeyId, + b"ehloDomain" => Property::EhloDomain, + b"ehloHostname" => Property::EhloHostname, + b"ehloTimeout" => Property::EhloTimeout, + b"elapsed" => Property::Elapsed, + b"else" => Property::Else, + b"email" => Property::Email, + b"emailAddress" => Property::EmailAddress, + b"emailAddresses" => Property::EmailAddresses, + b"emailAddressesNegative" => Property::EmailAddressesNegative, + b"emailAlert" => Property::EmailAlert, + b"emailDomain" => Property::EmailDomain, + b"emailLimit" => Property::EmailLimit, + b"emailPrefix" => Property::EmailPrefix, + b"emailTemplate" => Property::EmailTemplate, + b"enable" => Property::Enable, + b"enableAssistedDiscovery" => Property::EnableAssistedDiscovery, + b"enableEdns" => Property::EnableEdns, + b"enableHsts" => Property::EnableHsts, + b"enableLogExporter" => Property::EnableLogExporter, + b"enableSpamFilter" => Property::EnableSpamFilter, + b"enableSpanExporter" => Property::EnableSpanExporter, + b"enabled" => Property::Enabled, + b"enabledPermissions" => Property::EnabledPermissions, + b"encryptAtRest" => Property::EncryptAtRest, + b"encryptOnAppend" => Property::EncryptOnAppend, + b"encryptionAtRest" => Property::EncryptionAtRest, + b"encryptionKey" => Property::EncryptionKey, + b"endpoint" => Property::Endpoint, + b"envFrom" => Property::EnvFrom, + b"envFromParameters" => Property::EnvFromParameters, + b"envId" => Property::EnvId, + b"envRcptTo" => Property::EnvRcptTo, + b"envelopeFrom" => Property::EnvelopeFrom, + b"envelopeTo" => Property::EnvelopeTo, + b"errorCommand" => Property::ErrorCommand, + b"errorMessage" => Property::ErrorMessage, + b"errorType" => Property::ErrorType, + b"errors" => Property::Errors, + b"evaluatedDisposition" => Property::EvaluatedDisposition, + b"evaluatedDkim" => Property::EvaluatedDkim, + b"evaluatedSpf" => Property::EvaluatedSpf, + b"event" => Property::Event, + b"eventAlert" => Property::EventAlert, + b"eventEnd" => Property::EventEnd, + b"eventEndTz" => Property::EventEndTz, + b"eventId" => Property::EventId, + b"eventMessage" => Property::EventMessage, + b"eventSourceThrottle" => Property::EventSourceThrottle, + b"eventStart" => Property::EventStart, + b"eventStartTz" => Property::EventStartTz, + b"events" => Property::Events, + b"eventsPolicy" => Property::EventsPolicy, + b"expire" => Property::Expire, + b"expires" => Property::Expires, + b"expiresAt" => Property::ExpiresAt, + b"expiresAttempts" => Property::ExpiresAttempts, + b"expiry" => Property::Expiry, + b"expn" => Property::Expn, + b"expungeSchedule" => Property::ExpungeSchedule, + b"expungeSchedulingInboxAfter" => Property::ExpungeSchedulingInboxAfter, + b"expungeShareNotifyAfter" => Property::ExpungeShareNotifyAfter, + b"expungeSubmissionsAfter" => Property::ExpungeSubmissionsAfter, + b"expungeTrashAfter" => Property::ExpungeTrashAfter, + b"extension" => Property::Extension, + b"extensions" => Property::Extensions, + b"extraContactInfo" => Property::ExtraContactInfo, + b"factor" => Property::Factor, + b"failOnTimeout" => Property::FailOnTimeout, + b"failedAt" => Property::FailedAt, + b"failedAttemptNumber" => Property::FailedAttemptNumber, + b"failedSessionCount" => Property::FailedSessionCount, + b"failureDetails" => Property::FailureDetails, + b"failureDkimSignDomain" => Property::FailureDkimSignDomain, + b"failureFromAddress" => Property::FailureFromAddress, + b"failureFromName" => Property::FailureFromName, + b"failureReason" => Property::FailureReason, + b"failureReasonCode" => Property::FailureReasonCode, + b"failureSendFrequency" => Property::FailureSendFrequency, + b"failureSubject" => Property::FailureSubject, + b"featureL2Normalize" => Property::FeatureL2Normalize, + b"featureLogScale" => Property::FeatureLogScale, + b"feedbackType" => Property::FeedbackType, + b"fieldEmail" => Property::FieldEmail, + b"fieldHoneyPot" => Property::FieldHoneyPot, + b"fieldName" => Property::FieldName, + b"fieldSubject" => Property::FieldSubject, + b"filePath" => Property::FilePath, + b"files" => Property::Files, + b"filterLogin" => Property::FilterLogin, + b"filterMailbox" => Property::FilterMailbox, + b"filterMemberOf" => Property::FilterMemberOf, + b"flags" => Property::Flags, + b"flagsAction" => Property::FlagsAction, + b"flagsProtocol" => Property::FlagsProtocol, + b"forDomain" => Property::ForDomain, + b"format" => Property::Format, + b"from" => Property::From, + b"fromAddress" => Property::FromAddress, + b"fromEmail" => Property::FromEmail, + b"fromName" => Property::FromName, + b"futureRelease" => Property::FutureRelease, + b"generateDkimKeys" => Property::GenerateDkimKeys, + b"geoUrls" => Property::GeoUrls, + b"getMaxResults" => Property::GetMaxResults, + b"greetingTimeout" => Property::GreetingTimeout, + b"greylistFor" => Property::GreylistFor, + b"groupClass" => Property::GroupClass, + b"groupId" => Property::GroupId, + b"headerFrom" => Property::HeaderFrom, + b"headers" => Property::Headers, + b"holdMetricsFor" => Property::HoldMetricsFor, + b"holdMtaReportsFor" => Property::HoldMtaReportsFor, + b"holdSamplesFor" => Property::HoldSamplesFor, + b"holdTracesFor" => Property::HoldTracesFor, + b"host" => Property::Host, + b"hostedZoneId" => Property::HostedZoneId, + b"hostname" => Property::Hostname, + b"hour" => Property::Hour, + b"httpAuth" => Property::HttpAuth, + b"httpHeaders" => Property::HttpHeaders, + b"httpRsvpEnable" => Property::HttpRsvpEnable, + b"httpRsvpLinkExpiry" => Property::HttpRsvpLinkExpiry, + b"httpRsvpTemplate" => Property::HttpRsvpTemplate, + b"httpRsvpUrl" => Property::HttpRsvpUrl, + b"httpRua" => Property::HttpRua, + b"humanResult" => Property::HumanResult, + b"iCalendarData" => Property::ICalendarData, + b"id" => Property::Id, + b"idTokenExpiry" => Property::IdTokenExpiry, + b"identityAlignment" => Property::IdentityAlignment, + b"if" => Property::If, + b"impersonateServiceAccount" => Property::ImpersonateServiceAccount, + b"implicitTls" => Property::ImplicitTls, + b"inMemoryStore" => Property::InMemoryStore, + b"inboundReportAddresses" => Property::InboundReportAddresses, + b"inboundReportForwarding" => Property::InboundReportForwarding, + b"incidents" => Property::Incidents, + b"includeSource" => Property::IncludeSource, + b"indexAsn" => Property::IndexAsn, + b"indexAsnName" => Property::IndexAsnName, + b"indexBatchSize" => Property::IndexBatchSize, + b"indexCalendar" => Property::IndexCalendar, + b"indexCalendarFields" => Property::IndexCalendarFields, + b"indexContactFields" => Property::IndexContactFields, + b"indexContacts" => Property::IndexContacts, + b"indexCountry" => Property::IndexCountry, + b"indexEmail" => Property::IndexEmail, + b"indexEmailFields" => Property::IndexEmailFields, + b"indexKey" => Property::IndexKey, + b"indexTelemetry" => Property::IndexTelemetry, + b"indexTracingFields" => Property::IndexTracingFields, + b"indexValue" => Property::IndexValue, + b"indicatorParameters" => Property::IndicatorParameters, + b"initialDelay" => Property::InitialDelay, + b"interval" => Property::Interval, + b"intervals" => Property::Intervals, + b"ipLimit" => Property::IpLimit, + b"ipLookupStrategy" => Property::IpLookupStrategy, + b"ipRevPtr" => Property::IpRevPtr, + b"ipRevResult" => Property::IpRevResult, + b"isActive" => Property::IsActive, + b"isArchive" => Property::IsArchive, + b"isBad" => Property::IsBad, + b"isEnabled" => Property::IsEnabled, + b"isFromOrganizer" => Property::IsFromOrganizer, + b"isGlobPattern" => Property::IsGlobPattern, + b"isGzipped" => Property::IsGzipped, + b"isNz" => Property::IsNz, + b"isSenderAllowed" => Property::IsSenderAllowed, + b"isSpam" => Property::IsSpam, + b"isTls" => Property::IsTls, + b"issuer" => Property::Issuer, + b"issuerUrl" => Property::IssuerUrl, + b"itipMaxSize" => Property::ItipMaxSize, + b"jitter" => Property::Jitter, + b"key" => Property::Key, + b"keyName" => Property::KeyName, + b"keyPrefix" => Property::KeyPrefix, + b"keyValues" => Property::KeyValues, + b"l1Ratio" => Property::L1Ratio, + b"l2Ratio" => Property::L2Ratio, + b"lastRenewal" => Property::LastRenewal, + b"learnHamFromCard" => Property::LearnHamFromCard, + b"learnHamFromReply" => Property::LearnHamFromReply, + b"learnSpamFromRblHits" => Property::LearnSpamFromRblHits, + b"learnSpamFromTraps" => Property::LearnSpamFromTraps, + b"level" => Property::Level, + b"licenseKey" => Property::LicenseKey, + b"listenerIds" => Property::ListenerIds, + b"listeners" => Property::Listeners, + b"livePropertyMaxSize" => Property::LivePropertyMaxSize, + b"locale" => Property::Locale, + b"logo" => Property::Logo, + b"logoUrl" => Property::LogoUrl, + b"loiterBanPeriod" => Property::LoiterBanPeriod, + b"loiterBanRate" => Property::LoiterBanRate, + b"lossy" => Property::Lossy, + b"machineId" => Property::MachineId, + b"mailExchangers" => Property::MailExchangers, + b"mailFrom" => Property::MailFrom, + b"mailFromTimeout" => Property::MailFromTimeout, + b"mailRua" => Property::MailRua, + b"mailingLists" => Property::MailingLists, + b"maintenanceType" => Property::MaintenanceType, + b"managedZone" => Property::ManagedZone, + b"match" => Property::Match, + b"maxAddressBooks" => Property::MaxAddressBooks, + b"maxAge" => Property::MaxAge, + b"maxAllowedPacket" => Property::MaxAllowedPacket, + b"maxApiKeys" => Property::MaxApiKeys, + b"maxAppPasswords" => Property::MaxAppPasswords, + b"maxAttachmentSize" => Property::MaxAttachmentSize, + b"maxAttempts" => Property::MaxAttempts, + b"maxAttendees" => Property::MaxAttendees, + b"maxAuthFailures" => Property::MaxAuthFailures, + b"maxCalendars" => Property::MaxCalendars, + b"maxChangesHistory" => Property::MaxChangesHistory, + b"maxConcurrent" => Property::MaxConcurrent, + b"maxConcurrentRequests" => Property::MaxConcurrentRequests, + b"maxConcurrentUploads" => Property::MaxConcurrentUploads, + b"maxConnections" => Property::MaxConnections, + b"maxContacts" => Property::MaxContacts, + b"maxCpuCycles" => Property::MaxCpuCycles, + b"maxDelay" => Property::MaxDelay, + b"maxDuration" => Property::MaxDuration, + b"maxEntries" => Property::MaxEntries, + b"maxEntrySize" => Property::MaxEntrySize, + b"maxEventNotifications" => Property::MaxEventNotifications, + b"maxEvents" => Property::MaxEvents, + b"maxFailures" => Property::MaxFailures, + b"maxFiles" => Property::MaxFiles, + b"maxFolders" => Property::MaxFolders, + b"maxHeaderSize" => Property::MaxHeaderSize, + b"maxICalendarSize" => Property::MaxICalendarSize, + b"maxIdentities" => Property::MaxIdentities, + b"maxIncludes" => Property::MaxIncludes, + b"maxLocalVars" => Property::MaxLocalVars, + b"maxLockTimeout" => Property::MaxLockTimeout, + b"maxLocks" => Property::MaxLocks, + b"maxMailboxDepth" => Property::MaxMailboxDepth, + b"maxMailboxNameLength" => Property::MaxMailboxNameLength, + b"maxMailboxes" => Property::MaxMailboxes, + b"maxMaskedAddresses" => Property::MaxMaskedAddresses, + b"maxMatchVars" => Property::MaxMatchVars, + b"maxMessageSize" => Property::MaxMessageSize, + b"maxMessages" => Property::MaxMessages, + b"maxMethodCalls" => Property::MaxMethodCalls, + b"maxMultihomed" => Property::MaxMultihomed, + b"maxMxHosts" => Property::MaxMxHosts, + b"maxNestedBlocks" => Property::MaxNestedBlocks, + b"maxNestedForEvery" => Property::MaxNestedForEvery, + b"maxNestedIncludes" => Property::MaxNestedIncludes, + b"maxNestedTests" => Property::MaxNestedTests, + b"maxOutMessages" => Property::MaxOutMessages, + b"maxParticipantIdentities" => Property::MaxParticipantIdentities, + b"maxPublicKeys" => Property::MaxPublicKeys, + b"maxReceivedHeaders" => Property::MaxReceivedHeaders, + b"maxRecipients" => Property::MaxRecipients, + b"maxReconnects" => Property::MaxReconnects, + b"maxRecurrenceExpansions" => Property::MaxRecurrenceExpansions, + b"maxRedirects" => Property::MaxRedirects, + b"maxReportSize" => Property::MaxReportSize, + b"maxRequestRate" => Property::MaxRequestRate, + b"maxRequestSize" => Property::MaxRequestSize, + b"maxResponseSize" => Property::MaxResponseSize, + b"maxResults" => Property::MaxResults, + b"maxRetries" => Property::MaxRetries, + b"maxRetryWait" => Property::MaxRetryWait, + b"maxScriptNameLength" => Property::MaxScriptNameLength, + b"maxScriptSize" => Property::MaxScriptSize, + b"maxScripts" => Property::MaxScripts, + b"maxShares" => Property::MaxShares, + b"maxSize" => Property::MaxSize, + b"maxStringLength" => Property::MaxStringLength, + b"maxSubmissions" => Property::MaxSubmissions, + b"maxSubscriptions" => Property::MaxSubscriptions, + b"maxUploadCount" => Property::MaxUploadCount, + b"maxUploadSize" => Property::MaxUploadSize, + b"maxVCardSize" => Property::MaxVCardSize, + b"maxVarNameLength" => Property::MaxVarNameLength, + b"maxVarSize" => Property::MaxVarSize, + b"memberGroupIds" => Property::MemberGroupIds, + b"memberTenantId" => Property::MemberTenantId, + b"message" => Property::Message, + b"messageIdHostname" => Property::MessageIdHostname, + b"messageIds" => Property::MessageIds, + b"messages" => Property::Messages, + b"metric" => Property::Metric, + b"metrics" => Property::Metrics, + b"metricsCollectionInterval" => Property::MetricsCollectionInterval, + b"metricsPolicy" => Property::MetricsPolicy, + b"minHamSamples" => Property::MinHamSamples, + b"minRetryWait" => Property::MinRetryWait, + b"minSpamSamples" => Property::MinSpamSamples, + b"minTriggerInterval" => Property::MinTriggerInterval, + b"minute" => Property::Minute, + b"mode" => Property::Mode, + b"model" => Property::Model, + b"modelId" => Property::ModelId, + b"modelType" => Property::ModelType, + b"mtPriority" => Property::MtPriority, + b"mtaSts" => Property::MtaSts, + b"mtaStsTimeout" => Property::MtaStsTimeout, + b"multiline" => Property::Multiline, + b"mustMatchSender" => Property::MustMatchSender, + b"mxHosts" => Property::MxHosts, + b"name" => Property::Name, + b"namespace" => Property::Namespace, + b"negativeTtl" => Property::NegativeTtl, + b"nextNotify" => Property::NextNotify, + b"nextRetry" => Property::NextRetry, + b"nextTransitionAt" => Property::NextTransitionAt, + b"noCapabilityCheck" => Property::NoCapabilityCheck, + b"noEcho" => Property::NoEcho, + b"noSoliciting" => Property::NoSoliciting, + b"nodeId" => Property::NodeId, + b"notValidAfter" => Property::NotValidAfter, + b"notValidBefore" => Property::NotValidBefore, + b"notify" => Property::Notify, + b"notifyCount" => Property::NotifyCount, + b"notifyDue" => Property::NotifyDue, + b"numFeatures" => Property::NumFeatures, + b"numReplicas" => Property::NumReplicas, + b"numShards" => Property::NumShards, + b"onSuccessRenewCertificate" => Property::OnSuccessRenewCertificate, + b"openTelemetry" => Property::OpenTelemetry, + b"options" => Property::Options, + b"orcpt" => Property::Orcpt, + b"orgName" => Property::OrgName, + b"organizationName" => Property::OrganizationName, + b"origin" => Property::Origin, + b"originalEnvelopeId" => Property::OriginalEnvelopeId, + b"originalMailFrom" => Property::OriginalMailFrom, + b"originalRcptTo" => Property::OriginalRcptTo, + b"otpAuth" => Property::OtpAuth, + b"otpCode" => Property::OtpCode, + b"otpUrl" => Property::OtpUrl, + b"outboundReportDomain" => Property::OutboundReportDomain, + b"outboundReportSubmitter" => Property::OutboundReportSubmitter, + b"overrideProxyTrustedNetworks" => Property::OverrideProxyTrustedNetworks, + b"overrideType" => Property::OverrideType, + b"ovhEndpoint" => Property::OvhEndpoint, + b"parameters" => Property::Parameters, + b"parseLimitContact" => Property::ParseLimitContact, + b"parseLimitEmail" => Property::ParseLimitEmail, + b"parseLimitEvent" => Property::ParseLimitEvent, + b"passwordDefaultExpiry" => Property::PasswordDefaultExpiry, + b"passwordHashAlgorithm" => Property::PasswordHashAlgorithm, + b"passwordMaxLength" => Property::PasswordMaxLength, + b"passwordMinLength" => Property::PasswordMinLength, + b"passwordMinStrength" => Property::PasswordMinStrength, + b"path" => Property::Path, + b"period" => Property::Period, + b"permissions" => Property::Permissions, + b"pingInterval" => Property::PingInterval, + b"pipelining" => Property::Pipelining, + b"policies" => Property::Policies, + b"policyAdkim" => Property::PolicyAdkim, + b"policyAspf" => Property::PolicyAspf, + b"policyDisposition" => Property::PolicyDisposition, + b"policyDomain" => Property::PolicyDomain, + b"policyFailureReportingOptions" => Property::PolicyFailureReportingOptions, + b"policyIdentifier" => Property::PolicyIdentifier, + b"policyIdentifiers" => Property::PolicyIdentifiers, + b"policyOverrideReasons" => Property::PolicyOverrideReasons, + b"policyStrings" => Property::PolicyStrings, + b"policySubdomainDisposition" => Property::PolicySubdomainDisposition, + b"policyTestingMode" => Property::PolicyTestingMode, + b"policyType" => Property::PolicyType, + b"policyVersion" => Property::PolicyVersion, + b"pollInterval" => Property::PollInterval, + b"pollingInterval" => Property::PollingInterval, + b"poolMaxConnections" => Property::PoolMaxConnections, + b"poolMinConnections" => Property::PoolMinConnections, + b"poolRecyclingMethod" => Property::PoolRecyclingMethod, + b"poolTimeoutCreate" => Property::PoolTimeoutCreate, + b"poolTimeoutRecycle" => Property::PoolTimeoutRecycle, + b"poolTimeoutWait" => Property::PoolTimeoutWait, + b"poolWorkers" => Property::PoolWorkers, + b"port" => Property::Port, + b"prefix" => Property::Prefix, + b"preserveIntermediates" => Property::PreserveIntermediates, + b"priority" => Property::Priority, + b"privateKey" => Property::PrivateKey, + b"privateZone" => Property::PrivateZone, + b"privateZoneOnly" => Property::PrivateZoneOnly, + b"profile" => Property::Profile, + b"projectId" => Property::ProjectId, + b"prometheus" => Property::Prometheus, + b"prompt" => Property::Prompt, + b"propagationDelay" => Property::PropagationDelay, + b"propagationTimeout" => Property::PropagationTimeout, + b"protectedHeaders" => Property::ProtectedHeaders, + b"protocol" => Property::Protocol, + b"protocolVersion" => Property::ProtocolVersion, + b"providerInfo" => Property::ProviderInfo, + b"proxyTrustedNetworks" => Property::ProxyTrustedNetworks, + b"publicKey" => Property::PublicKey, + b"publishRecords" => Property::PublishRecords, + b"pushAttemptWait" => Property::PushAttemptWait, + b"pushMaxAttempts" => Property::PushMaxAttempts, + b"pushRequestTimeout" => Property::PushRequestTimeout, + b"pushRetryWait" => Property::PushRetryWait, + b"pushShardsTotal" => Property::PushShardsTotal, + b"pushThrottle" => Property::PushThrottle, + b"pushVerifyTimeout" => Property::PushVerifyTimeout, + b"queryEmailAliases" => Property::QueryEmailAliases, + b"queryLogin" => Property::QueryLogin, + b"queryMaxResults" => Property::QueryMaxResults, + b"queryMemberOf" => Property::QueryMemberOf, + b"queryRecipient" => Property::QueryRecipient, + b"queueId" => Property::QueueId, + b"queueName" => Property::QueueName, + b"quotas" => Property::Quotas, + b"rate" => Property::Rate, + b"rateLimit" => Property::RateLimit, + b"rateLimitAnonymous" => Property::RateLimitAnonymous, + b"rateLimitAuthenticated" => Property::RateLimitAuthenticated, + b"ratio" => Property::Ratio, + b"rcptToTimeout" => Property::RcptToTimeout, + b"readFromReplicas" => Property::ReadFromReplicas, + b"readReplicas" => Property::ReadReplicas, + b"reason" => Property::Reason, + b"receivedAt" => Property::ReceivedAt, + b"receivedFromIp" => Property::ReceivedFromIp, + b"receivedViaPort" => Property::ReceivedViaPort, + b"receivingIp" => Property::ReceivingIp, + b"receivingMxHelo" => Property::ReceivingMxHelo, + b"receivingMxHostname" => Property::ReceivingMxHostname, + b"recipients" => Property::Recipients, + b"records" => Property::Records, + b"recurrenceId" => Property::RecurrenceId, + b"redirectUris" => Property::RedirectUris, + b"refresh" => Property::Refresh, + b"refreshTokenExpiry" => Property::RefreshTokenExpiry, + b"refreshTokenRenewal" => Property::RefreshTokenRenewal, + b"region" => Property::Region, + b"rejectNonFqdn" => Property::RejectNonFqdn, + b"remoteIp" => Property::RemoteIp, + b"renewBefore" => Property::RenewBefore, + b"report" => Property::Report, + b"reportAddressUri" => Property::ReportAddressUri, + b"reportId" => Property::ReportId, + b"reportedDomains" => Property::ReportedDomains, + b"reportedUris" => Property::ReportedUris, + b"reportingMta" => Property::ReportingMta, + b"requestMaxSize" => Property::RequestMaxSize, + b"requestTlsCertificate" => Property::RequestTlsCertificate, + b"require" => Property::Require, + b"requireAudience" => Property::RequireAudience, + b"requireClientRegistration" => Property::RequireClientRegistration, + b"requireScopes" => Property::RequireScopes, + b"requireTls" => Property::RequireTls, + b"reservoirCapacity" => Property::ReservoirCapacity, + b"resourceUrl" => Property::ResourceUrl, + b"responseCode" => Property::ResponseCode, + b"responseEnhanced" => Property::ResponseEnhanced, + b"responseHeaders" => Property::ResponseHeaders, + b"responseHostname" => Property::ResponseHostname, + b"responseMessage" => Property::ResponseMessage, + b"responsePosCategory" => Property::ResponsePosCategory, + b"responsePosConfidence" => Property::ResponsePosConfidence, + b"responsePosExplanation" => Property::ResponsePosExplanation, + b"result" => Property::Result, + b"resultType" => Property::ResultType, + b"retireAfter" => Property::RetireAfter, + b"retry" => Property::Retry, + b"retryCount" => Property::RetryCount, + b"retryDue" => Property::RetryDue, + b"returnPath" => Property::ReturnPath, + b"reverseIpVerify" => Property::ReverseIpVerify, + b"rewrite" => Property::Rewrite, + b"roleIds" => Property::RoleIds, + b"roles" => Property::Roles, + b"rotate" => Property::Rotate, + b"rotateAfter" => Property::RotateAfter, + b"route" => Property::Route, + b"rua" => Property::Rua, + b"sasToken" => Property::SasToken, + b"saslMechanisms" => Property::SaslMechanisms, + b"scanBanPaths" => Property::ScanBanPaths, + b"scanBanPeriod" => Property::ScanBanPeriod, + b"scanBanRate" => Property::ScanBanRate, + b"schedule" => Property::Schedule, + b"scheduling" => Property::Scheduling, + b"scope" => Property::Scope, + b"score" => Property::Score, + b"scoreDiscard" => Property::ScoreDiscard, + b"scoreReject" => Property::ScoreReject, + b"scoreSpam" => Property::ScoreSpam, + b"script" => Property::Script, + b"searchStore" => Property::SearchStore, + b"secret" => Property::Secret, + b"secretAccessKey" => Property::SecretAccessKey, + b"secretApiKey" => Property::SecretApiKey, + b"secretKey" => Property::SecretKey, + b"securityToken" => Property::SecurityToken, + b"selector" => Property::Selector, + b"selectorTemplate" => Property::SelectorTemplate, + b"sendFrequency" => Property::SendFrequency, + b"sendingMtaIp" => Property::SendingMtaIp, + b"separator" => Property::Separator, + b"serverHostname" => Property::ServerHostname, + b"servers" => Property::Servers, + b"serviceAccountJson" => Property::ServiceAccountJson, + b"services" => Property::Services, + b"sessionToken" => Property::SessionToken, + b"setMaxObjects" => Property::SetMaxObjects, + b"shardIndex" => Property::ShardIndex, + b"sig0Algorithm" => Property::Sig0Algorithm, + b"signatureAlgorithm" => Property::SignatureAlgorithm, + b"signatureKey" => Property::SignatureKey, + b"signerName" => Property::SignerName, + b"size" => Property::Size, + b"skipFirst" => Property::SkipFirst, + b"smtpGreeting" => Property::SmtpGreeting, + b"snippetMaxResults" => Property::SnippetMaxResults, + b"socketBacklog" => Property::SocketBacklog, + b"socketNoDelay" => Property::SocketNoDelay, + b"socketReceiveBufferSize" => Property::SocketReceiveBufferSize, + b"socketReuseAddress" => Property::SocketReuseAddress, + b"socketReusePort" => Property::SocketReusePort, + b"socketSendBufferSize" => Property::SocketSendBufferSize, + b"socketTosV4" => Property::SocketTosV4, + b"socketTtl" => Property::SocketTtl, + b"sourceIp" => Property::SourceIp, + b"sourceIps" => Property::SourceIps, + b"sourcePort" => Property::SourcePort, + b"spamFilterRulesUrl" => Property::SpamFilterRulesUrl, + b"spfDns" => Property::SpfDns, + b"spfEhloDomain" => Property::SpfEhloDomain, + b"spfEhloResult" => Property::SpfEhloResult, + b"spfEhloVerify" => Property::SpfEhloVerify, + b"spfFromVerify" => Property::SpfFromVerify, + b"spfMailFromDomain" => Property::SpfMailFromDomain, + b"spfMailFromResult" => Property::SpfMailFromResult, + b"spfResults" => Property::SpfResults, + b"stage" => Property::Stage, + b"stages" => Property::Stages, + b"startTime" => Property::StartTime, + b"startTls" => Property::StartTls, + b"status" => Property::Status, + b"storageAccount" => Property::StorageAccount, + b"store" => Property::Store, + b"stores" => Property::Stores, + b"strategy" => Property::Strategy, + b"subAddressing" => Property::SubAddressing, + b"subject" => Property::Subject, + b"subjectAlternativeNames" => Property::SubjectAlternativeNames, + b"subscribe" => Property::Subscribe, + b"sum" => Property::Sum, + b"summary" => Property::Summary, + b"tag" => Property::Tag, + b"tags" => Property::Tags, + b"taskTypes" => Property::TaskTypes, + b"tasks" => Property::Tasks, + b"tcpOnError" => Property::TcpOnError, + b"tempFailOnError" => Property::TempFailOnError, + b"temperature" => Property::Temperature, + b"template" => Property::Template, + b"tenantId" => Property::TenantId, + b"tenants" => Property::Tenants, + b"text" => Property::Text, + b"then" => Property::Then, + b"thirdParty" => Property::ThirdParty, + b"thirdPartyHash" => Property::ThirdPartyHash, + b"threadName" => Property::ThreadName, + b"threadPoolSize" => Property::ThreadPoolSize, + b"threadsPerNode" => Property::ThreadsPerNode, + b"throttle" => Property::Throttle, + b"timeZone" => Property::TimeZone, + b"timeout" => Property::Timeout, + b"timeoutAnonymous" => Property::TimeoutAnonymous, + b"timeoutAuthenticated" => Property::TimeoutAuthenticated, + b"timeoutCommand" => Property::TimeoutCommand, + b"timeoutConnect" => Property::TimeoutConnect, + b"timeoutConnection" => Property::TimeoutConnection, + b"timeoutData" => Property::TimeoutData, + b"timeoutIdle" => Property::TimeoutIdle, + b"timeoutMessage" => Property::TimeoutMessage, + b"timeoutRequest" => Property::TimeoutRequest, + b"timeoutSession" => Property::TimeoutSession, + b"timestamp" => Property::Timestamp, + b"title" => Property::Title, + b"tls" => Property::Tls, + b"tlsDisableCipherSuites" => Property::TlsDisableCipherSuites, + b"tlsDisableProtocols" => Property::TlsDisableProtocols, + b"tlsIgnoreClientOrder" => Property::TlsIgnoreClientOrder, + b"tlsImplicit" => Property::TlsImplicit, + b"tlsTimeout" => Property::TlsTimeout, + b"to" => Property::To, + b"totalDeadline" => Property::TotalDeadline, + b"totalFailedSessions" => Property::TotalFailedSessions, + b"totalSuccessfulSessions" => Property::TotalSuccessfulSessions, + b"traceId" => Property::TraceId, + b"tracer" => Property::Tracer, + b"trainFrequency" => Property::TrainFrequency, + b"transactionRetryDelay" => Property::TransactionRetryDelay, + b"transactionRetryLimit" => Property::TransactionRetryLimit, + b"transactionTimeout" => Property::TransactionTimeout, + b"transferLimit" => Property::TransferLimit, + b"trustContacts" => Property::TrustContacts, + b"trustReplies" => Property::TrustReplies, + b"tsigAlgorithm" => Property::TsigAlgorithm, + b"ttl" => Property::Ttl, + b"unpackDirectory" => Property::UnpackDirectory, + b"updateRecords" => Property::UpdateRecords, + b"uploadQuota" => Property::UploadQuota, + b"uploadTtl" => Property::UploadTtl, + b"url" => Property::Url, + b"urlLimit" => Property::UrlLimit, + b"urlPrefix" => Property::UrlPrefix, + b"urls" => Property::Urls, + b"usePermissiveCors" => Property::UsePermissiveCors, + b"useTls" => Property::UseTls, + b"useXForwarded" => Property::UseXForwarded, + b"usedDiskQuota" => Property::UsedDiskQuota, + b"userAgent" => Property::UserAgent, + b"userCodeExpiry" => Property::UserCodeExpiry, + b"username" => Property::Username, + b"usernameDomain" => Property::UsernameDomain, + b"validateDomain" => Property::ValidateDomain, + b"value" => Property::Value, + b"variableName" => Property::VariableName, + b"version" => Property::Version, + b"vrfy" => Property::Vrfy, + b"waitOnFail" => Property::WaitOnFail, + b"websocketHeartbeat" => Property::WebsocketHeartbeat, + b"websocketThrottle" => Property::WebsocketThrottle, + b"websocketTimeout" => Property::WebsocketTimeout, + b"zone" => Property::Zone, + b"zoneIpV4" => Property::ZoneIpV4, + b"zoneIpV6" => Property::ZoneIpV6, + } + } + + fn as_str(&self) -> &'static str { + match self { + Property::Type => "@type", + Property::AbuseBanPeriod => "abuseBanPeriod", + Property::AbuseBanRate => "abuseBanRate", + Property::AccessKey => "accessKey", + Property::AccessKeyId => "accessKeyId", + Property::AccessTokenExpiry => "accessTokenExpiry", + Property::AccessTokens => "accessTokens", + Property::AccountDomainId => "accountDomainId", + Property::AccountId => "accountId", + Property::AccountIdentifier => "accountIdentifier", + Property::AccountKey => "accountKey", + Property::AccountName => "accountName", + Property::AccountType => "accountType", + Property::AccountUri => "accountUri", + Property::Accounts => "accounts", + Property::AcmeProviderId => "acmeProviderId", + Property::AddAuthResultsHeader => "addAuthResultsHeader", + Property::AddDateHeader => "addDateHeader", + Property::AddDeliveredToHeader => "addDeliveredToHeader", + Property::AddMessageIdHeader => "addMessageIdHeader", + Property::AddReceivedHeader => "addReceivedHeader", + Property::AddReceivedSpfHeader => "addReceivedSpfHeader", + Property::AddReturnPathHeader => "addReturnPathHeader", + Property::AdditionalInformation => "additionalInformation", + Property::Address => "address", + Property::Addresses => "addresses", + Property::AggregateContactInfo => "aggregateContactInfo", + Property::AggregateDkimSignDomain => "aggregateDkimSignDomain", + Property::AggregateFromAddress => "aggregateFromAddress", + Property::AggregateFromName => "aggregateFromName", + Property::AggregateMaxReportSize => "aggregateMaxReportSize", + Property::AggregateOrgName => "aggregateOrgName", + Property::AggregateSendFrequency => "aggregateSendFrequency", + Property::AggregateSubject => "aggregateSubject", + Property::AlarmId => "alarmId", + Property::Algorithms => "algorithms", + Property::Aliases => "aliases", + Property::AllowCount => "allowCount", + Property::AllowDirectoryQueries => "allowDirectoryQueries", + Property::AllowExternalRcpts => "allowExternalRcpts", + Property::AllowInvalidCerts => "allowInvalidCerts", + Property::AllowPlainTextAuth => "allowPlainTextAuth", + Property::AllowRelaying => "allowRelaying", + Property::AllowSpamTraining => "allowSpamTraining", + Property::AllowedEndpoints => "allowedEndpoints", + Property::AllowedIps => "allowedIps", + Property::AllowedNotifyUris => "allowedNotifyUris", + Property::Alpha => "alpha", + Property::AnonymousClientRegistration => "anonymousClientRegistration", + Property::Ansi => "ansi", + Property::ApiKey => "apiKey", + Property::ApplicationKey => "applicationKey", + Property::ApplicationSecret => "applicationSecret", + Property::ArcResult => "arcResult", + Property::ArcVerify => "arcVerify", + Property::ArchiveDeletedAccountsFor => "archiveDeletedAccountsFor", + Property::ArchiveDeletedItemsFor => "archiveDeletedItemsFor", + Property::ArchivedAt => "archivedAt", + Property::ArchivedItemType => "archivedItemType", + Property::ArchivedUntil => "archivedUntil", + Property::ArrivalDate => "arrivalDate", + Property::AsnUrls => "asnUrls", + Property::AttemptNumber => "attemptNumber", + Property::Attempts => "attempts", + Property::AttrClass => "attrClass", + Property::AttrDescription => "attrDescription", + Property::AttrEmail => "attrEmail", + Property::AttrEmailAlias => "attrEmailAlias", + Property::AttrMemberOf => "attrMemberOf", + Property::AttrSecret => "attrSecret", + Property::AttrSecretChanged => "attrSecretChanged", + Property::Auid => "auid", + Property::AuthBanPeriod => "authBanPeriod", + Property::AuthBanRate => "authBanRate", + Property::AuthCodeExpiry => "authCodeExpiry", + Property::AuthCodeMaxAttempts => "authCodeMaxAttempts", + Property::AuthFailure => "authFailure", + Property::AuthSecret => "authSecret", + Property::AuthToken => "authToken", + Property::AuthUsername => "authUsername", + Property::AuthenticatedAs => "authenticatedAs", + Property::AuthenticationResults => "authenticationResults", + Property::AutoAddInvitations => "autoAddInvitations", + Property::AutoUpdateFrequency => "autoUpdateFrequency", + Property::BaseDn => "baseDn", + Property::BearerToken => "bearerToken", + Property::Beta => "beta", + Property::Bind => "bind", + Property::BindAuthentication => "bindAuthentication", + Property::BindDn => "bindDn", + Property::BindSecret => "bindSecret", + Property::BlobCleanupSchedule => "blobCleanupSchedule", + Property::BlobId => "blobId", + Property::BlobSize => "blobSize", + Property::BlobStore => "blobStore", + Property::BlockCount => "blockCount", + Property::Body => "body", + Property::Brokers => "brokers", + Property::Bucket => "bucket", + Property::BufferSize => "bufferSize", + Property::Buffered => "buffered", + Property::Canonicalization => "canonicalization", + Property::CapacityClient => "capacityClient", + Property::CapacityReadBuffer => "capacityReadBuffer", + Property::CapacitySubscription => "capacitySubscription", + Property::CatchAllAddress => "catchAllAddress", + Property::Categories => "categories", + Property::Certificate => "certificate", + Property::CertificateManagement => "certificateManagement", + Property::ChallengeType => "challengeType", + Property::ChangesMaxResults => "changesMaxResults", + Property::Chunking => "chunking", + Property::ClaimGroups => "claimGroups", + Property::ClaimName => "claimName", + Property::ClaimUsername => "claimUsername", + Property::Cleartext => "cleartext", + Property::ClientId => "clientId", + Property::ClusterFile => "clusterFile", + Property::ColumnClass => "columnClass", + Property::ColumnDescription => "columnDescription", + Property::ColumnEmail => "columnEmail", + Property::ColumnSecret => "columnSecret", + Property::Comment => "comment", + Property::CompressionAlgorithm => "compressionAlgorithm", + Property::Concurrency => "concurrency", + Property::Condition => "condition", + Property::Confidence => "confidence", + Property::Config => "config", + Property::ConnectTimeout => "connectTimeout", + Property::Connection => "connection", + Property::ConsumerKey => "consumerKey", + Property::Contact => "contact", + Property::ContactInfo => "contactInfo", + Property::Contacts => "contacts", + Property::Container => "container", + Property::Content => "content", + Property::ContentTypes => "contentTypes", + Property::Contents => "contents", + Property::Count => "count", + Property::Create => "create", + Property::CreatedAt => "createdAt", + Property::CreatedBy => "createdBy", + Property::CredentialId => "credentialId", + Property::Credentials => "credentials", + Property::CurrentSecret => "currentSecret", + Property::CustomEndpoint => "customEndpoint", + Property::CustomRegion => "customRegion", + Property::CustomRule => "customRule", + Property::Dane => "dane", + Property::DataCleanupSchedule => "dataCleanupSchedule", + Property::DataStore => "dataStore", + Property::DataTimeout => "dataTimeout", + Property::Database => "database", + Property::DatacenterId => "datacenterId", + Property::DateRangeBegin => "dateRangeBegin", + Property::DateRangeEnd => "dateRangeEnd", + Property::DateRangeStart => "dateRangeStart", + Property::Day => "day", + Property::DeadPropertyMaxSize => "deadPropertyMaxSize", + Property::DefaultAdminRoleIds => "defaultAdminRoleIds", + Property::DefaultCertificateId => "defaultCertificateId", + Property::DefaultDisplayName => "defaultDisplayName", + Property::DefaultDomain => "defaultDomain", + Property::DefaultDomainId => "defaultDomainId", + Property::DefaultExpiryDuplicate => "defaultExpiryDuplicate", + Property::DefaultExpiryVacation => "defaultExpiryVacation", + Property::DefaultFolders => "defaultFolders", + Property::DefaultFromAddress => "defaultFromAddress", + Property::DefaultFromName => "defaultFromName", + Property::DefaultGroupRoleIds => "defaultGroupRoleIds", + Property::DefaultHostname => "defaultHostname", + Property::DefaultHrefName => "defaultHrefName", + Property::DefaultLanguage => "defaultLanguage", + Property::DefaultName => "defaultName", + Property::DefaultReturnPath => "defaultReturnPath", + Property::DefaultSubject => "defaultSubject", + Property::DefaultSubjectPrefix => "defaultSubjectPrefix", + Property::DefaultTenantRoleIds => "defaultTenantRoleIds", + Property::DefaultUserRoleIds => "defaultUserRoleIds", + Property::Definition => "definition", + Property::Delay => "delay", + Property::DeleteAfter => "deleteAfter", + Property::DeleteAfterUse => "deleteAfterUse", + Property::DeliverAt => "deliverAt", + Property::DeliverBy => "deliverBy", + Property::DeliverTo => "deliverTo", + Property::DeliveryResult => "deliveryResult", + Property::Depth => "depth", + Property::Description => "description", + Property::Details => "details", + Property::Directory => "directory", + Property::DirectoryId => "directoryId", + Property::DisableCapabilities => "disableCapabilities", + Property::DisableLanguages => "disableLanguages", + Property::DisabledPermissions => "disabledPermissions", + Property::DiscardAfter => "discardAfter", + Property::Disposition => "disposition", + Property::DkimAdspDns => "dkimAdspDns", + Property::DkimCanonicalizedBody => "dkimCanonicalizedBody", + Property::DkimCanonicalizedHeader => "dkimCanonicalizedHeader", + Property::DkimDomain => "dkimDomain", + Property::DkimIdentity => "dkimIdentity", + Property::DkimManagement => "dkimManagement", + Property::DkimPass => "dkimPass", + Property::DkimResults => "dkimResults", + Property::DkimSelector => "dkimSelector", + Property::DkimSelectorDns => "dkimSelectorDns", + Property::DkimSignDomain => "dkimSignDomain", + Property::DkimSignatures => "dkimSignatures", + Property::DkimStrict => "dkimStrict", + Property::DkimVerify => "dkimVerify", + Property::DmarcPass => "dmarcPass", + Property::DmarcPolicy => "dmarcPolicy", + Property::DmarcResult => "dmarcResult", + Property::DmarcVerify => "dmarcVerify", + Property::DnsIpv4 => "dnsIpv4", + Property::DnsIpv6 => "dnsIpv6", + Property::DnsManagement => "dnsManagement", + Property::DnsMtaSts => "dnsMtaSts", + Property::DnsMx => "dnsMx", + Property::DnsPtr => "dnsPtr", + Property::DnsRbl => "dnsRbl", + Property::DnsServer => "dnsServer", + Property::DnsServerId => "dnsServerId", + Property::DnsTlsa => "dnsTlsa", + Property::DnsTxt => "dnsTxt", + Property::DnsZoneFile => "dnsZoneFile", + Property::DocumentId => "documentId", + Property::DocumentType => "documentType", + Property::Domain => "domain", + Property::DomainId => "domainId", + Property::DomainLimit => "domainLimit", + Property::DomainNames => "domainNames", + Property::DomainNamesNegative => "domainNamesNegative", + Property::Domains => "domains", + Property::Dsn => "dsn", + Property::Due => "due", + Property::DuplicateExpiry => "duplicateExpiry", + Property::Duration => "duration", + Property::EabHmacKey => "eabHmacKey", + Property::EabKeyId => "eabKeyId", + Property::EhloDomain => "ehloDomain", + Property::EhloHostname => "ehloHostname", + Property::EhloTimeout => "ehloTimeout", + Property::Elapsed => "elapsed", + Property::Else => "else", + Property::Email => "email", + Property::EmailAddress => "emailAddress", + Property::EmailAddresses => "emailAddresses", + Property::EmailAddressesNegative => "emailAddressesNegative", + Property::EmailAlert => "emailAlert", + Property::EmailDomain => "emailDomain", + Property::EmailLimit => "emailLimit", + Property::EmailPrefix => "emailPrefix", + Property::EmailTemplate => "emailTemplate", + Property::Enable => "enable", + Property::EnableAssistedDiscovery => "enableAssistedDiscovery", + Property::EnableEdns => "enableEdns", + Property::EnableHsts => "enableHsts", + Property::EnableLogExporter => "enableLogExporter", + Property::EnableSpamFilter => "enableSpamFilter", + Property::EnableSpanExporter => "enableSpanExporter", + Property::Enabled => "enabled", + Property::EnabledPermissions => "enabledPermissions", + Property::EncryptAtRest => "encryptAtRest", + Property::EncryptOnAppend => "encryptOnAppend", + Property::EncryptionAtRest => "encryptionAtRest", + Property::EncryptionKey => "encryptionKey", + Property::Endpoint => "endpoint", + Property::EnvFrom => "envFrom", + Property::EnvFromParameters => "envFromParameters", + Property::EnvId => "envId", + Property::EnvRcptTo => "envRcptTo", + Property::EnvelopeFrom => "envelopeFrom", + Property::EnvelopeTo => "envelopeTo", + Property::ErrorCommand => "errorCommand", + Property::ErrorMessage => "errorMessage", + Property::ErrorType => "errorType", + Property::Errors => "errors", + Property::EvaluatedDisposition => "evaluatedDisposition", + Property::EvaluatedDkim => "evaluatedDkim", + Property::EvaluatedSpf => "evaluatedSpf", + Property::Event => "event", + Property::EventAlert => "eventAlert", + Property::EventEnd => "eventEnd", + Property::EventEndTz => "eventEndTz", + Property::EventId => "eventId", + Property::EventMessage => "eventMessage", + Property::EventSourceThrottle => "eventSourceThrottle", + Property::EventStart => "eventStart", + Property::EventStartTz => "eventStartTz", + Property::Events => "events", + Property::EventsPolicy => "eventsPolicy", + Property::Expire => "expire", + Property::Expires => "expires", + Property::ExpiresAt => "expiresAt", + Property::ExpiresAttempts => "expiresAttempts", + Property::Expiry => "expiry", + Property::Expn => "expn", + Property::ExpungeSchedule => "expungeSchedule", + Property::ExpungeSchedulingInboxAfter => "expungeSchedulingInboxAfter", + Property::ExpungeShareNotifyAfter => "expungeShareNotifyAfter", + Property::ExpungeSubmissionsAfter => "expungeSubmissionsAfter", + Property::ExpungeTrashAfter => "expungeTrashAfter", + Property::Extension => "extension", + Property::Extensions => "extensions", + Property::ExtraContactInfo => "extraContactInfo", + Property::Factor => "factor", + Property::FailOnTimeout => "failOnTimeout", + Property::FailedAt => "failedAt", + Property::FailedAttemptNumber => "failedAttemptNumber", + Property::FailedSessionCount => "failedSessionCount", + Property::FailureDetails => "failureDetails", + Property::FailureDkimSignDomain => "failureDkimSignDomain", + Property::FailureFromAddress => "failureFromAddress", + Property::FailureFromName => "failureFromName", + Property::FailureReason => "failureReason", + Property::FailureReasonCode => "failureReasonCode", + Property::FailureSendFrequency => "failureSendFrequency", + Property::FailureSubject => "failureSubject", + Property::FeatureL2Normalize => "featureL2Normalize", + Property::FeatureLogScale => "featureLogScale", + Property::FeedbackType => "feedbackType", + Property::FieldEmail => "fieldEmail", + Property::FieldHoneyPot => "fieldHoneyPot", + Property::FieldName => "fieldName", + Property::FieldSubject => "fieldSubject", + Property::FilePath => "filePath", + Property::Files => "files", + Property::FilterLogin => "filterLogin", + Property::FilterMailbox => "filterMailbox", + Property::FilterMemberOf => "filterMemberOf", + Property::Flags => "flags", + Property::FlagsAction => "flagsAction", + Property::FlagsProtocol => "flagsProtocol", + Property::ForDomain => "forDomain", + Property::Format => "format", + Property::From => "from", + Property::FromAddress => "fromAddress", + Property::FromEmail => "fromEmail", + Property::FromName => "fromName", + Property::FutureRelease => "futureRelease", + Property::GenerateDkimKeys => "generateDkimKeys", + Property::GeoUrls => "geoUrls", + Property::GetMaxResults => "getMaxResults", + Property::GreetingTimeout => "greetingTimeout", + Property::GreylistFor => "greylistFor", + Property::GroupClass => "groupClass", + Property::GroupId => "groupId", + Property::HeaderFrom => "headerFrom", + Property::Headers => "headers", + Property::HoldMetricsFor => "holdMetricsFor", + Property::HoldMtaReportsFor => "holdMtaReportsFor", + Property::HoldSamplesFor => "holdSamplesFor", + Property::HoldTracesFor => "holdTracesFor", + Property::Host => "host", + Property::HostedZoneId => "hostedZoneId", + Property::Hostname => "hostname", + Property::Hour => "hour", + Property::HttpAuth => "httpAuth", + Property::HttpHeaders => "httpHeaders", + Property::HttpRsvpEnable => "httpRsvpEnable", + Property::HttpRsvpLinkExpiry => "httpRsvpLinkExpiry", + Property::HttpRsvpTemplate => "httpRsvpTemplate", + Property::HttpRsvpUrl => "httpRsvpUrl", + Property::HttpRua => "httpRua", + Property::HumanResult => "humanResult", + Property::ICalendarData => "iCalendarData", + Property::Id => "id", + Property::IdTokenExpiry => "idTokenExpiry", + Property::IdentityAlignment => "identityAlignment", + Property::If => "if", + Property::ImpersonateServiceAccount => "impersonateServiceAccount", + Property::ImplicitTls => "implicitTls", + Property::InMemoryStore => "inMemoryStore", + Property::InboundReportAddresses => "inboundReportAddresses", + Property::InboundReportForwarding => "inboundReportForwarding", + Property::Incidents => "incidents", + Property::IncludeSource => "includeSource", + Property::IndexAsn => "indexAsn", + Property::IndexAsnName => "indexAsnName", + Property::IndexBatchSize => "indexBatchSize", + Property::IndexCalendar => "indexCalendar", + Property::IndexCalendarFields => "indexCalendarFields", + Property::IndexContactFields => "indexContactFields", + Property::IndexContacts => "indexContacts", + Property::IndexCountry => "indexCountry", + Property::IndexEmail => "indexEmail", + Property::IndexEmailFields => "indexEmailFields", + Property::IndexKey => "indexKey", + Property::IndexTelemetry => "indexTelemetry", + Property::IndexTracingFields => "indexTracingFields", + Property::IndexValue => "indexValue", + Property::IndicatorParameters => "indicatorParameters", + Property::InitialDelay => "initialDelay", + Property::Interval => "interval", + Property::Intervals => "intervals", + Property::IpLimit => "ipLimit", + Property::IpLookupStrategy => "ipLookupStrategy", + Property::IpRevPtr => "ipRevPtr", + Property::IpRevResult => "ipRevResult", + Property::IsActive => "isActive", + Property::IsArchive => "isArchive", + Property::IsBad => "isBad", + Property::IsEnabled => "isEnabled", + Property::IsFromOrganizer => "isFromOrganizer", + Property::IsGlobPattern => "isGlobPattern", + Property::IsGzipped => "isGzipped", + Property::IsNz => "isNz", + Property::IsSenderAllowed => "isSenderAllowed", + Property::IsSpam => "isSpam", + Property::IsTls => "isTls", + Property::Issuer => "issuer", + Property::IssuerUrl => "issuerUrl", + Property::ItipMaxSize => "itipMaxSize", + Property::Jitter => "jitter", + Property::Key => "key", + Property::KeyName => "keyName", + Property::KeyPrefix => "keyPrefix", + Property::KeyValues => "keyValues", + Property::L1Ratio => "l1Ratio", + Property::L2Ratio => "l2Ratio", + Property::LastRenewal => "lastRenewal", + Property::LearnHamFromCard => "learnHamFromCard", + Property::LearnHamFromReply => "learnHamFromReply", + Property::LearnSpamFromRblHits => "learnSpamFromRblHits", + Property::LearnSpamFromTraps => "learnSpamFromTraps", + Property::Level => "level", + Property::LicenseKey => "licenseKey", + Property::ListenerIds => "listenerIds", + Property::Listeners => "listeners", + Property::LivePropertyMaxSize => "livePropertyMaxSize", + Property::Locale => "locale", + Property::Logo => "logo", + Property::LogoUrl => "logoUrl", + Property::LoiterBanPeriod => "loiterBanPeriod", + Property::LoiterBanRate => "loiterBanRate", + Property::Lossy => "lossy", + Property::MachineId => "machineId", + Property::MailExchangers => "mailExchangers", + Property::MailFrom => "mailFrom", + Property::MailFromTimeout => "mailFromTimeout", + Property::MailRua => "mailRua", + Property::MailingLists => "mailingLists", + Property::MaintenanceType => "maintenanceType", + Property::ManagedZone => "managedZone", + Property::Match => "match", + Property::MaxAddressBooks => "maxAddressBooks", + Property::MaxAge => "maxAge", + Property::MaxAllowedPacket => "maxAllowedPacket", + Property::MaxApiKeys => "maxApiKeys", + Property::MaxAppPasswords => "maxAppPasswords", + Property::MaxAttachmentSize => "maxAttachmentSize", + Property::MaxAttempts => "maxAttempts", + Property::MaxAttendees => "maxAttendees", + Property::MaxAuthFailures => "maxAuthFailures", + Property::MaxCalendars => "maxCalendars", + Property::MaxChangesHistory => "maxChangesHistory", + Property::MaxConcurrent => "maxConcurrent", + Property::MaxConcurrentRequests => "maxConcurrentRequests", + Property::MaxConcurrentUploads => "maxConcurrentUploads", + Property::MaxConnections => "maxConnections", + Property::MaxContacts => "maxContacts", + Property::MaxCpuCycles => "maxCpuCycles", + Property::MaxDelay => "maxDelay", + Property::MaxDuration => "maxDuration", + Property::MaxEntries => "maxEntries", + Property::MaxEntrySize => "maxEntrySize", + Property::MaxEventNotifications => "maxEventNotifications", + Property::MaxEvents => "maxEvents", + Property::MaxFailures => "maxFailures", + Property::MaxFiles => "maxFiles", + Property::MaxFolders => "maxFolders", + Property::MaxHeaderSize => "maxHeaderSize", + Property::MaxICalendarSize => "maxICalendarSize", + Property::MaxIdentities => "maxIdentities", + Property::MaxIncludes => "maxIncludes", + Property::MaxLocalVars => "maxLocalVars", + Property::MaxLockTimeout => "maxLockTimeout", + Property::MaxLocks => "maxLocks", + Property::MaxMailboxDepth => "maxMailboxDepth", + Property::MaxMailboxNameLength => "maxMailboxNameLength", + Property::MaxMailboxes => "maxMailboxes", + Property::MaxMaskedAddresses => "maxMaskedAddresses", + Property::MaxMatchVars => "maxMatchVars", + Property::MaxMessageSize => "maxMessageSize", + Property::MaxMessages => "maxMessages", + Property::MaxMethodCalls => "maxMethodCalls", + Property::MaxMultihomed => "maxMultihomed", + Property::MaxMxHosts => "maxMxHosts", + Property::MaxNestedBlocks => "maxNestedBlocks", + Property::MaxNestedForEvery => "maxNestedForEvery", + Property::MaxNestedIncludes => "maxNestedIncludes", + Property::MaxNestedTests => "maxNestedTests", + Property::MaxOutMessages => "maxOutMessages", + Property::MaxParticipantIdentities => "maxParticipantIdentities", + Property::MaxPublicKeys => "maxPublicKeys", + Property::MaxReceivedHeaders => "maxReceivedHeaders", + Property::MaxRecipients => "maxRecipients", + Property::MaxReconnects => "maxReconnects", + Property::MaxRecurrenceExpansions => "maxRecurrenceExpansions", + Property::MaxRedirects => "maxRedirects", + Property::MaxReportSize => "maxReportSize", + Property::MaxRequestRate => "maxRequestRate", + Property::MaxRequestSize => "maxRequestSize", + Property::MaxResponseSize => "maxResponseSize", + Property::MaxResults => "maxResults", + Property::MaxRetries => "maxRetries", + Property::MaxRetryWait => "maxRetryWait", + Property::MaxScriptNameLength => "maxScriptNameLength", + Property::MaxScriptSize => "maxScriptSize", + Property::MaxScripts => "maxScripts", + Property::MaxShares => "maxShares", + Property::MaxSize => "maxSize", + Property::MaxStringLength => "maxStringLength", + Property::MaxSubmissions => "maxSubmissions", + Property::MaxSubscriptions => "maxSubscriptions", + Property::MaxUploadCount => "maxUploadCount", + Property::MaxUploadSize => "maxUploadSize", + Property::MaxVCardSize => "maxVCardSize", + Property::MaxVarNameLength => "maxVarNameLength", + Property::MaxVarSize => "maxVarSize", + Property::MemberGroupIds => "memberGroupIds", + Property::MemberTenantId => "memberTenantId", + Property::Message => "message", + Property::MessageIdHostname => "messageIdHostname", + Property::MessageIds => "messageIds", + Property::Messages => "messages", + Property::Metric => "metric", + Property::Metrics => "metrics", + Property::MetricsCollectionInterval => "metricsCollectionInterval", + Property::MetricsPolicy => "metricsPolicy", + Property::MinHamSamples => "minHamSamples", + Property::MinRetryWait => "minRetryWait", + Property::MinSpamSamples => "minSpamSamples", + Property::MinTriggerInterval => "minTriggerInterval", + Property::Minute => "minute", + Property::Mode => "mode", + Property::Model => "model", + Property::ModelId => "modelId", + Property::ModelType => "modelType", + Property::MtPriority => "mtPriority", + Property::MtaSts => "mtaSts", + Property::MtaStsTimeout => "mtaStsTimeout", + Property::Multiline => "multiline", + Property::MustMatchSender => "mustMatchSender", + Property::MxHosts => "mxHosts", + Property::Name => "name", + Property::Namespace => "namespace", + Property::NegativeTtl => "negativeTtl", + Property::NextNotify => "nextNotify", + Property::NextRetry => "nextRetry", + Property::NextTransitionAt => "nextTransitionAt", + Property::NoCapabilityCheck => "noCapabilityCheck", + Property::NoEcho => "noEcho", + Property::NoSoliciting => "noSoliciting", + Property::NodeId => "nodeId", + Property::NotValidAfter => "notValidAfter", + Property::NotValidBefore => "notValidBefore", + Property::Notify => "notify", + Property::NotifyCount => "notifyCount", + Property::NotifyDue => "notifyDue", + Property::NumFeatures => "numFeatures", + Property::NumReplicas => "numReplicas", + Property::NumShards => "numShards", + Property::OnSuccessRenewCertificate => "onSuccessRenewCertificate", + Property::OpenTelemetry => "openTelemetry", + Property::Options => "options", + Property::Orcpt => "orcpt", + Property::OrgName => "orgName", + Property::OrganizationName => "organizationName", + Property::Origin => "origin", + Property::OriginalEnvelopeId => "originalEnvelopeId", + Property::OriginalMailFrom => "originalMailFrom", + Property::OriginalRcptTo => "originalRcptTo", + Property::OtpAuth => "otpAuth", + Property::OtpCode => "otpCode", + Property::OtpUrl => "otpUrl", + Property::OutboundReportDomain => "outboundReportDomain", + Property::OutboundReportSubmitter => "outboundReportSubmitter", + Property::OverrideProxyTrustedNetworks => "overrideProxyTrustedNetworks", + Property::OverrideType => "overrideType", + Property::OvhEndpoint => "ovhEndpoint", + Property::Parameters => "parameters", + Property::ParseLimitContact => "parseLimitContact", + Property::ParseLimitEmail => "parseLimitEmail", + Property::ParseLimitEvent => "parseLimitEvent", + Property::PasswordDefaultExpiry => "passwordDefaultExpiry", + Property::PasswordHashAlgorithm => "passwordHashAlgorithm", + Property::PasswordMaxLength => "passwordMaxLength", + Property::PasswordMinLength => "passwordMinLength", + Property::PasswordMinStrength => "passwordMinStrength", + Property::Path => "path", + Property::Period => "period", + Property::Permissions => "permissions", + Property::PingInterval => "pingInterval", + Property::Pipelining => "pipelining", + Property::Policies => "policies", + Property::PolicyAdkim => "policyAdkim", + Property::PolicyAspf => "policyAspf", + Property::PolicyDisposition => "policyDisposition", + Property::PolicyDomain => "policyDomain", + Property::PolicyFailureReportingOptions => "policyFailureReportingOptions", + Property::PolicyIdentifier => "policyIdentifier", + Property::PolicyIdentifiers => "policyIdentifiers", + Property::PolicyOverrideReasons => "policyOverrideReasons", + Property::PolicyStrings => "policyStrings", + Property::PolicySubdomainDisposition => "policySubdomainDisposition", + Property::PolicyTestingMode => "policyTestingMode", + Property::PolicyType => "policyType", + Property::PolicyVersion => "policyVersion", + Property::PollInterval => "pollInterval", + Property::PollingInterval => "pollingInterval", + Property::PoolMaxConnections => "poolMaxConnections", + Property::PoolMinConnections => "poolMinConnections", + Property::PoolRecyclingMethod => "poolRecyclingMethod", + Property::PoolTimeoutCreate => "poolTimeoutCreate", + Property::PoolTimeoutRecycle => "poolTimeoutRecycle", + Property::PoolTimeoutWait => "poolTimeoutWait", + Property::PoolWorkers => "poolWorkers", + Property::Port => "port", + Property::Prefix => "prefix", + Property::PreserveIntermediates => "preserveIntermediates", + Property::Priority => "priority", + Property::PrivateKey => "privateKey", + Property::PrivateZone => "privateZone", + Property::PrivateZoneOnly => "privateZoneOnly", + Property::Profile => "profile", + Property::ProjectId => "projectId", + Property::Prometheus => "prometheus", + Property::Prompt => "prompt", + Property::PropagationDelay => "propagationDelay", + Property::PropagationTimeout => "propagationTimeout", + Property::ProtectedHeaders => "protectedHeaders", + Property::Protocol => "protocol", + Property::ProtocolVersion => "protocolVersion", + Property::ProviderInfo => "providerInfo", + Property::ProxyTrustedNetworks => "proxyTrustedNetworks", + Property::PublicKey => "publicKey", + Property::PublishRecords => "publishRecords", + Property::PushAttemptWait => "pushAttemptWait", + Property::PushMaxAttempts => "pushMaxAttempts", + Property::PushRequestTimeout => "pushRequestTimeout", + Property::PushRetryWait => "pushRetryWait", + Property::PushShardsTotal => "pushShardsTotal", + Property::PushThrottle => "pushThrottle", + Property::PushVerifyTimeout => "pushVerifyTimeout", + Property::QueryEmailAliases => "queryEmailAliases", + Property::QueryLogin => "queryLogin", + Property::QueryMaxResults => "queryMaxResults", + Property::QueryMemberOf => "queryMemberOf", + Property::QueryRecipient => "queryRecipient", + Property::QueueId => "queueId", + Property::QueueName => "queueName", + Property::Quotas => "quotas", + Property::Rate => "rate", + Property::RateLimit => "rateLimit", + Property::RateLimitAnonymous => "rateLimitAnonymous", + Property::RateLimitAuthenticated => "rateLimitAuthenticated", + Property::Ratio => "ratio", + Property::RcptToTimeout => "rcptToTimeout", + Property::ReadFromReplicas => "readFromReplicas", + Property::ReadReplicas => "readReplicas", + Property::Reason => "reason", + Property::ReceivedAt => "receivedAt", + Property::ReceivedFromIp => "receivedFromIp", + Property::ReceivedViaPort => "receivedViaPort", + Property::ReceivingIp => "receivingIp", + Property::ReceivingMxHelo => "receivingMxHelo", + Property::ReceivingMxHostname => "receivingMxHostname", + Property::Recipients => "recipients", + Property::Records => "records", + Property::RecurrenceId => "recurrenceId", + Property::RedirectUris => "redirectUris", + Property::Refresh => "refresh", + Property::RefreshTokenExpiry => "refreshTokenExpiry", + Property::RefreshTokenRenewal => "refreshTokenRenewal", + Property::Region => "region", + Property::RejectNonFqdn => "rejectNonFqdn", + Property::RemoteIp => "remoteIp", + Property::RenewBefore => "renewBefore", + Property::Report => "report", + Property::ReportAddressUri => "reportAddressUri", + Property::ReportId => "reportId", + Property::ReportedDomains => "reportedDomains", + Property::ReportedUris => "reportedUris", + Property::ReportingMta => "reportingMta", + Property::RequestMaxSize => "requestMaxSize", + Property::RequestTlsCertificate => "requestTlsCertificate", + Property::Require => "require", + Property::RequireAudience => "requireAudience", + Property::RequireClientRegistration => "requireClientRegistration", + Property::RequireScopes => "requireScopes", + Property::RequireTls => "requireTls", + Property::ReservoirCapacity => "reservoirCapacity", + Property::ResourceUrl => "resourceUrl", + Property::ResponseCode => "responseCode", + Property::ResponseEnhanced => "responseEnhanced", + Property::ResponseHeaders => "responseHeaders", + Property::ResponseHostname => "responseHostname", + Property::ResponseMessage => "responseMessage", + Property::ResponsePosCategory => "responsePosCategory", + Property::ResponsePosConfidence => "responsePosConfidence", + Property::ResponsePosExplanation => "responsePosExplanation", + Property::Result => "result", + Property::ResultType => "resultType", + Property::RetireAfter => "retireAfter", + Property::Retry => "retry", + Property::RetryCount => "retryCount", + Property::RetryDue => "retryDue", + Property::ReturnPath => "returnPath", + Property::ReverseIpVerify => "reverseIpVerify", + Property::Rewrite => "rewrite", + Property::RoleIds => "roleIds", + Property::Roles => "roles", + Property::Rotate => "rotate", + Property::RotateAfter => "rotateAfter", + Property::Route => "route", + Property::Rua => "rua", + Property::SasToken => "sasToken", + Property::SaslMechanisms => "saslMechanisms", + Property::ScanBanPaths => "scanBanPaths", + Property::ScanBanPeriod => "scanBanPeriod", + Property::ScanBanRate => "scanBanRate", + Property::Schedule => "schedule", + Property::Scheduling => "scheduling", + Property::Scope => "scope", + Property::Score => "score", + Property::ScoreDiscard => "scoreDiscard", + Property::ScoreReject => "scoreReject", + Property::ScoreSpam => "scoreSpam", + Property::Script => "script", + Property::SearchStore => "searchStore", + Property::Secret => "secret", + Property::SecretAccessKey => "secretAccessKey", + Property::SecretApiKey => "secretApiKey", + Property::SecretKey => "secretKey", + Property::SecurityToken => "securityToken", + Property::Selector => "selector", + Property::SelectorTemplate => "selectorTemplate", + Property::SendFrequency => "sendFrequency", + Property::SendingMtaIp => "sendingMtaIp", + Property::Separator => "separator", + Property::ServerHostname => "serverHostname", + Property::Servers => "servers", + Property::ServiceAccountJson => "serviceAccountJson", + Property::Services => "services", + Property::SessionToken => "sessionToken", + Property::SetMaxObjects => "setMaxObjects", + Property::ShardIndex => "shardIndex", + Property::Sig0Algorithm => "sig0Algorithm", + Property::SignatureAlgorithm => "signatureAlgorithm", + Property::SignatureKey => "signatureKey", + Property::SignerName => "signerName", + Property::Size => "size", + Property::SkipFirst => "skipFirst", + Property::SmtpGreeting => "smtpGreeting", + Property::SnippetMaxResults => "snippetMaxResults", + Property::SocketBacklog => "socketBacklog", + Property::SocketNoDelay => "socketNoDelay", + Property::SocketReceiveBufferSize => "socketReceiveBufferSize", + Property::SocketReuseAddress => "socketReuseAddress", + Property::SocketReusePort => "socketReusePort", + Property::SocketSendBufferSize => "socketSendBufferSize", + Property::SocketTosV4 => "socketTosV4", + Property::SocketTtl => "socketTtl", + Property::SourceIp => "sourceIp", + Property::SourceIps => "sourceIps", + Property::SourcePort => "sourcePort", + Property::SpamFilterRulesUrl => "spamFilterRulesUrl", + Property::SpfDns => "spfDns", + Property::SpfEhloDomain => "spfEhloDomain", + Property::SpfEhloResult => "spfEhloResult", + Property::SpfEhloVerify => "spfEhloVerify", + Property::SpfFromVerify => "spfFromVerify", + Property::SpfMailFromDomain => "spfMailFromDomain", + Property::SpfMailFromResult => "spfMailFromResult", + Property::SpfResults => "spfResults", + Property::Stage => "stage", + Property::Stages => "stages", + Property::StartTime => "startTime", + Property::StartTls => "startTls", + Property::Status => "status", + Property::StorageAccount => "storageAccount", + Property::Store => "store", + Property::Stores => "stores", + Property::Strategy => "strategy", + Property::SubAddressing => "subAddressing", + Property::Subject => "subject", + Property::SubjectAlternativeNames => "subjectAlternativeNames", + Property::Subscribe => "subscribe", + Property::Sum => "sum", + Property::Summary => "summary", + Property::Tag => "tag", + Property::Tags => "tags", + Property::TaskTypes => "taskTypes", + Property::Tasks => "tasks", + Property::TcpOnError => "tcpOnError", + Property::TempFailOnError => "tempFailOnError", + Property::Temperature => "temperature", + Property::Template => "template", + Property::TenantId => "tenantId", + Property::Tenants => "tenants", + Property::Text => "text", + Property::Then => "then", + Property::ThirdParty => "thirdParty", + Property::ThirdPartyHash => "thirdPartyHash", + Property::ThreadName => "threadName", + Property::ThreadPoolSize => "threadPoolSize", + Property::ThreadsPerNode => "threadsPerNode", + Property::Throttle => "throttle", + Property::TimeZone => "timeZone", + Property::Timeout => "timeout", + Property::TimeoutAnonymous => "timeoutAnonymous", + Property::TimeoutAuthenticated => "timeoutAuthenticated", + Property::TimeoutCommand => "timeoutCommand", + Property::TimeoutConnect => "timeoutConnect", + Property::TimeoutConnection => "timeoutConnection", + Property::TimeoutData => "timeoutData", + Property::TimeoutIdle => "timeoutIdle", + Property::TimeoutMessage => "timeoutMessage", + Property::TimeoutRequest => "timeoutRequest", + Property::TimeoutSession => "timeoutSession", + Property::Timestamp => "timestamp", + Property::Title => "title", + Property::Tls => "tls", + Property::TlsDisableCipherSuites => "tlsDisableCipherSuites", + Property::TlsDisableProtocols => "tlsDisableProtocols", + Property::TlsIgnoreClientOrder => "tlsIgnoreClientOrder", + Property::TlsImplicit => "tlsImplicit", + Property::TlsTimeout => "tlsTimeout", + Property::To => "to", + Property::TotalDeadline => "totalDeadline", + Property::TotalFailedSessions => "totalFailedSessions", + Property::TotalSuccessfulSessions => "totalSuccessfulSessions", + Property::TraceId => "traceId", + Property::Tracer => "tracer", + Property::TrainFrequency => "trainFrequency", + Property::TransactionRetryDelay => "transactionRetryDelay", + Property::TransactionRetryLimit => "transactionRetryLimit", + Property::TransactionTimeout => "transactionTimeout", + Property::TransferLimit => "transferLimit", + Property::TrustContacts => "trustContacts", + Property::TrustReplies => "trustReplies", + Property::TsigAlgorithm => "tsigAlgorithm", + Property::Ttl => "ttl", + Property::UnpackDirectory => "unpackDirectory", + Property::UpdateRecords => "updateRecords", + Property::UploadQuota => "uploadQuota", + Property::UploadTtl => "uploadTtl", + Property::Url => "url", + Property::UrlLimit => "urlLimit", + Property::UrlPrefix => "urlPrefix", + Property::Urls => "urls", + Property::UsePermissiveCors => "usePermissiveCors", + Property::UseTls => "useTls", + Property::UseXForwarded => "useXForwarded", + Property::UsedDiskQuota => "usedDiskQuota", + Property::UserAgent => "userAgent", + Property::UserCodeExpiry => "userCodeExpiry", + Property::Username => "username", + Property::UsernameDomain => "usernameDomain", + Property::ValidateDomain => "validateDomain", + Property::Value => "value", + Property::VariableName => "variableName", + Property::Version => "version", + Property::Vrfy => "vrfy", + Property::WaitOnFail => "waitOnFail", + Property::WebsocketHeartbeat => "websocketHeartbeat", + Property::WebsocketThrottle => "websocketThrottle", + Property::WebsocketTimeout => "websocketTimeout", + Property::Zone => "zone", + Property::ZoneIpV4 => "zoneIpV4", + Property::ZoneIpV6 => "zoneIpV6", + } + } + + fn to_id(&self) -> u16 { + *self as u16 + } + + fn from_id(id: u16) -> Option { + match id { + 0 => Some(Property::Type), + 678 => Some(Property::AbuseBanPeriod), + 677 => Some(Property::AbuseBanRate), + 118 => Some(Property::AccessKey), + 327 => Some(Property::AccessKeyId), + 619 => Some(Property::AccessTokenExpiry), + 132 => Some(Property::AccessTokens), + 810 => Some(Property::AccountDomainId), + 57 => Some(Property::AccountId), + 315 => Some(Property::AccountIdentifier), + 15 => Some(Property::AccountKey), + 809 => Some(Property::AccountName), + 811 => Some(Property::AccountType), + 16 => Some(Property::AccountUri), + 151 => Some(Property::Accounts), + 182 => Some(Property::AcmeProviderId), + 554 => Some(Property::AddAuthResultsHeader), + 555 => Some(Property::AddDateHeader), + 556 => Some(Property::AddDeliveredToHeader), + 557 => Some(Property::AddMessageIdHeader), + 558 => Some(Property::AddReceivedHeader), + 559 => Some(Property::AddReceivedSpfHeader), + 560 => Some(Property::AddReturnPathHeader), + 838 => Some(Property::AdditionalInformation), + 44 => Some(Property::Address), + 579 => Some(Property::Addresses), + 268 => Some(Property::AggregateContactInfo), + 274 => Some(Property::AggregateDkimSignDomain), + 269 => Some(Property::AggregateFromAddress), + 270 => Some(Property::AggregateFromName), + 271 => Some(Property::AggregateMaxReportSize), + 272 => Some(Property::AggregateOrgName), + 273 => Some(Property::AggregateSendFrequency), + 275 => Some(Property::AggregateSubject), + 798 => Some(Property::AlarmId), + 225 => Some(Property::Algorithms), + 339 => Some(Property::Aliases), + 768 => Some(Property::AllowCount), + 695 => Some(Property::AllowDirectoryQueries), + 164 => Some(Property::AllowExternalRcpts), + 26 => Some(Property::AllowInvalidCerts), + 424 => Some(Property::AllowPlainTextAuth), + 348 => Some(Property::AllowRelaying), + 369 => Some(Property::AllowSpamTraining), + 398 => Some(Property::AllowedEndpoints), + 49 => Some(Property::AllowedIps), + 712 => Some(Property::AllowedNotifyUris), + 388 => Some(Property::Alpha), + 614 => Some(Property::AnonymousClientRegistration), + 858 => Some(Property::Ansi), + 325 => Some(Property::ApiKey), + 321 => Some(Property::ApplicationKey), + 322 => Some(Property::ApplicationSecret), + 292 => Some(Property::ArcResult), + 690 => Some(Property::ArcVerify), + 203 => Some(Property::ArchiveDeletedAccountsFor), + 202 => Some(Property::ArchiveDeletedItemsFor), + 58 => Some(Property::ArchivedAt), + 820 => Some(Property::ArchivedItemType), + 59 => Some(Property::ArchivedUntil), + 68 => Some(Property::ArrivalDate), + 102 => Some(Property::AsnUrls), + 829 => Some(Property::AttemptNumber), + 303 => Some(Property::Attempts), + 470 => Some(Property::AttrClass), + 471 => Some(Property::AttrDescription), + 472 => Some(Property::AttrEmail), + 473 => Some(Property::AttrEmailAlias), + 474 => Some(Property::AttrMemberOf), + 475 => Some(Property::AttrSecret), + 476 => Some(Property::AttrSecretChanged), + 215 => Some(Property::Auid), + 680 => Some(Property::AuthBanPeriod), + 679 => Some(Property::AuthBanRate), + 616 => Some(Property::AuthCodeExpiry), + 613 => Some(Property::AuthCodeMaxAttempts), + 81 => Some(Property::AuthFailure), + 501 => Some(Property::AuthSecret), + 314 => Some(Property::AuthToken), + 502 => Some(Property::AuthUsername), + 740 => Some(Property::AuthenticatedAs), + 69 => Some(Property::AuthenticationResults), + 171 => Some(Property::AutoAddInvitations), + 53 => Some(Property::AutoUpdateFrequency), + 463 => Some(Property::BaseDn), + 403 => Some(Property::BearerToken), + 389 => Some(Property::Beta), + 589 => Some(Property::Bind), + 466 => Some(Property::BindAuthentication), + 464 => Some(Property::BindDn), + 465 => Some(Property::BindSecret), + 200 => Some(Property::BlobCleanupSchedule), + 60 => Some(Property::BlobId), + 655 => Some(Property::BlobSize), + 126 => Some(Property::BlobStore), + 766 => Some(Property::BlockCount), + 38 => Some(Property::Body), + 459 => Some(Property::Brokers), + 658 => Some(Property::Bucket), + 656 => Some(Property::BufferSize), + 863 => Some(Property::Buffered), + 216 => Some(Property::Canonicalization), + 584 => Some(Property::CapacityClient), + 585 => Some(Property::CapacityReadBuffer), + 586 => Some(Property::CapacitySubscription), + 346 => Some(Property::CatchAllAddress), + 759 => Some(Property::Categories), + 176 => Some(Property::Certificate), + 342 => Some(Property::CertificateManagement), + 10 => Some(Property::ChallengeType), + 435 => Some(Property::ChangesMaxResults), + 517 => Some(Property::Chunking), + 612 => Some(Property::ClaimGroups), + 611 => Some(Property::ClaimName), + 609 => Some(Property::ClaimUsername), + 693 => Some(Property::Cleartext), + 604 => Some(Property::ClientId), + 382 => Some(Property::ClusterFile), + 781 => Some(Property::ColumnClass), + 782 => Some(Property::ColumnDescription), + 779 => Some(Property::ColumnEmail), + 780 => Some(Property::ColumnSecret), + 240 => Some(Property::Comment), + 359 => Some(Property::CompressionAlgorithm), + 304 => Some(Property::Concurrency), + 34 => Some(Property::Condition), + 760 => Some(Property::Confidence), + 873 => Some(Property::Config), + 505 => Some(Property::ConnectTimeout), + 539 => Some(Property::Connection), + 323 => Some(Property::ConsumerKey), + 11 => Some(Property::Contact), + 844 => Some(Property::ContactInfo), + 133 => Some(Property::Contacts), + 117 => Some(Property::Container), + 65 => Some(Property::Content), + 758 => Some(Property::ContentTypes), + 708 => Some(Property::Contents), + 258 => Some(Property::Count), + 367 => Some(Property::Create), + 46 => Some(Property::CreatedAt), + 486 => Some(Property::CreatedBy), + 627 => Some(Property::CredentialId), + 588 => Some(Property::Credentials), + 4 => Some(Property::CurrentSecret), + 662 => Some(Property::CustomEndpoint), + 663 => Some(Property::CustomRegion), + 787 => Some(Property::CustomRule), + 569 => Some(Property::Dane), + 199 => Some(Property::DataCleanupSchedule), + 125 => Some(Property::DataStore), + 506 => Some(Property::DataTimeout), + 575 => Some(Property::Database), + 383 => Some(Property::DatacenterId), + 245 => Some(Property::DateRangeBegin), + 246 => Some(Property::DateRangeEnd), + 845 => Some(Property::DateRangeStart), + 192 => Some(Property::Day), + 868 => Some(Property::DeadPropertyMaxSize), + 108 => Some(Property::DefaultAdminRoleIds), + 790 => Some(Property::DefaultCertificateId), + 20 => Some(Property::DefaultDisplayName), + 122 => Some(Property::DefaultDomain), + 789 => Some(Property::DefaultDomainId), + 709 => Some(Property::DefaultExpiryDuplicate), + 710 => Some(Property::DefaultExpiryVacation), + 360 => Some(Property::DefaultFolders), + 405 => Some(Property::DefaultFromAddress), + 697 => Some(Property::DefaultFromName), + 106 => Some(Property::DefaultGroupRoleIds), + 788 => Some(Property::DefaultHostname), + 21 => Some(Property::DefaultHrefName), + 665 => Some(Property::DefaultLanguage), + 408 => Some(Property::DefaultName), + 701 => Some(Property::DefaultReturnPath), + 411 => Some(Property::DefaultSubject), + 714 => Some(Property::DefaultSubjectPrefix), + 107 => Some(Property::DefaultTenantRoleIds), + 105 => Some(Property::DefaultUserRoleIds), + 235 => Some(Property::Definition), + 825 => Some(Property::Delay), + 229 => Some(Property::DeleteAfter), + 777 => Some(Property::DeleteAfterUse), + 238 => Some(Property::DeliverAt), + 518 => Some(Property::DeliverBy), + 404 => Some(Property::DeliverTo), + 82 => Some(Property::DeliveryResult), + 381 => Some(Property::Depth), + 6 => Some(Property::Description), + 297 => Some(Property::Details), + 12 => Some(Property::Directory), + 104 => Some(Property::DirectoryId), + 711 => Some(Property::DisableCapabilities), + 666 => Some(Property::DisableLanguages), + 629 => Some(Property::DisabledPermissions), + 872 => Some(Property::DiscardAfter), + 747 => Some(Property::Disposition), + 83 => Some(Property::DkimAdspDns), + 84 => Some(Property::DkimCanonicalizedBody), + 85 => Some(Property::DkimCanonicalizedHeader), + 86 => Some(Property::DkimDomain), + 87 => Some(Property::DkimIdentity), + 343 => Some(Property::DkimManagement), + 291 => Some(Property::DkimPass), + 266 => Some(Property::DkimResults), + 88 => Some(Property::DkimSelector), + 89 => Some(Property::DkimSelectorDns), + 231 => Some(Property::DkimSignDomain), + 155 => Some(Property::DkimSignatures), + 686 => Some(Property::DkimStrict), + 687 => Some(Property::DkimVerify), + 294 => Some(Property::DmarcPass), + 295 => Some(Property::DmarcPolicy), + 293 => Some(Property::DmarcResult), + 691 => Some(Property::DmarcVerify), + 134 => Some(Property::DnsIpv4), + 135 => Some(Property::DnsIpv6), + 344 => Some(Property::DnsManagement), + 136 => Some(Property::DnsMtaSts), + 137 => Some(Property::DnsMx), + 138 => Some(Property::DnsPtr), + 139 => Some(Property::DnsRbl), + 130 => Some(Property::DnsServer), + 300 => Some(Property::DnsServerId), + 140 => Some(Property::DnsTlsa), + 141 => Some(Property::DnsTxt), + 345 => Some(Property::DnsZoneFile), + 804 => Some(Property::DocumentId), + 814 => Some(Property::DocumentType), + 232 => Some(Property::Domain), + 221 => Some(Property::DomainId), + 750 => Some(Property::DomainLimit), + 147 => Some(Property::DomainNames), + 148 => Some(Property::DomainNamesNegative), + 146 => Some(Property::Domains), + 519 => Some(Property::Dsn), + 797 => Some(Property::Due), + 699 => Some(Property::DuplicateExpiry), + 515 => Some(Property::Duration), + 13 => Some(Property::EabHmacKey), + 14 => Some(Property::EabKeyId), + 283 => Some(Property::EhloDomain), + 503 => Some(Property::EhloHostname), + 507 => Some(Property::EhloTimeout), + 296 => Some(Property::Elapsed), + 375 => Some(Property::Else), + 242 => Some(Property::Email), + 393 => Some(Property::EmailAddress), + 149 => Some(Property::EmailAddresses), + 150 => Some(Property::EmailAddressesNegative), + 35 => Some(Property::EmailAlert), + 488 => Some(Property::EmailDomain), + 751 => Some(Property::EmailLimit), + 487 => Some(Property::EmailPrefix), + 174 => Some(Property::EmailTemplate), + 37 => Some(Property::Enable), + 865 => Some(Property::EnableAssistedDiscovery), + 305 => Some(Property::EnableEdns), + 399 => Some(Property::EnableHsts), + 860 => Some(Property::EnableLogExporter), + 562 => Some(Property::EnableSpamFilter), + 861 => Some(Property::EnableSpanExporter), + 50 => Some(Property::Enabled), + 628 => Some(Property::EnabledPermissions), + 358 => Some(Property::EncryptAtRest), + 357 => Some(Property::EncryptOnAppend), + 9 => Some(Property::EncryptionAtRest), + 622 => Some(Property::EncryptionKey), + 499 => Some(Property::Endpoint), + 742 => Some(Property::EnvFrom), + 743 => Some(Property::EnvFromParameters), + 639 => Some(Property::EnvId), + 744 => Some(Property::EnvRcptTo), + 264 => Some(Property::EnvelopeFrom), + 263 => Some(Property::EnvelopeTo), + 210 => Some(Property::ErrorCommand), + 209 => Some(Property::ErrorMessage), + 208 => Some(Property::ErrorType), + 247 => Some(Property::Errors), + 259 => Some(Property::EvaluatedDisposition), + 260 => Some(Property::EvaluatedDkim), + 261 => Some(Property::EvaluatedSpf), + 372 => Some(Property::Event), + 36 => Some(Property::EventAlert), + 801 => Some(Property::EventEnd), + 803 => Some(Property::EventEndTz), + 799 => Some(Property::EventId), + 43 => Some(Property::EventMessage), + 447 => Some(Property::EventSourceThrottle), + 800 => Some(Property::EventStart), + 802 => Some(Property::EventStartTz), + 142 => Some(Property::Events), + 855 => Some(Property::EventsPolicy), + 217 => Some(Property::Expire), + 100 => Some(Property::Expires), + 47 => Some(Property::ExpiresAt), + 632 => Some(Property::ExpiresAttempts), + 512 => Some(Property::Expiry), + 520 => Some(Property::Expn), + 198 => Some(Property::ExpungeSchedule), + 197 => Some(Property::ExpungeSchedulingInboxAfter), + 196 => Some(Property::ExpungeShareNotifyAfter), + 195 => Some(Property::ExpungeSubmissionsAfter), + 194 => Some(Property::ExpungeTrashAfter), + 754 => Some(Property::Extension), + 257 => Some(Property::Extensions), + 243 => Some(Property::ExtraContactInfo), + 821 => Some(Property::Factor), + 490 => Some(Property::FailOnTimeout), + 826 => Some(Property::FailedAt), + 827 => Some(Property::FailedAttemptNumber), + 837 => Some(Property::FailedSessionCount), + 851 => Some(Property::FailureDetails), + 279 => Some(Property::FailureDkimSignDomain), + 276 => Some(Property::FailureFromAddress), + 277 => Some(Property::FailureFromName), + 828 => Some(Property::FailureReason), + 839 => Some(Property::FailureReasonCode), + 278 => Some(Property::FailureSendFrequency), + 280 => Some(Property::FailureSubject), + 738 => Some(Property::FeatureL2Normalize), + 739 => Some(Property::FeatureLogScale), + 67 => Some(Property::FeedbackType), + 406 => Some(Property::FieldEmail), + 407 => Some(Property::FieldHoneyPot), + 409 => Some(Property::FieldName), + 412 => Some(Property::FieldSubject), + 676 => Some(Property::FilePath), + 144 => Some(Property::Files), + 467 => Some(Property::FilterLogin), + 468 => Some(Property::FilterMailbox), + 469 => Some(Property::FilterMemberOf), + 638 => Some(Property::Flags), + 537 => Some(Property::FlagsAction), + 538 => Some(Property::FlagsProtocol), + 485 => Some(Property::ForDomain), + 415 => Some(Property::Format), + 62 => Some(Property::From), + 39 => Some(Property::FromAddress), + 165 => Some(Property::FromEmail), + 40 => Some(Property::FromName), + 521 => Some(Property::FutureRelease), + 124 => Some(Property::GenerateDkimKeys), + 103 => Some(Property::GeoUrls), + 436 => Some(Property::GetMaxResults), + 508 => Some(Property::GreetingTimeout), + 770 => Some(Property::GreylistFor), + 477 => Some(Property::GroupClass), + 460 => Some(Property::GroupId), + 265 => Some(Property::HeaderFrom), + 93 => Some(Property::Headers), + 206 => Some(Property::HoldMetricsFor), + 204 => Some(Property::HoldMtaReportsFor), + 730 => Some(Property::HoldSamplesFor), + 205 => Some(Property::HoldTracesFor), + 333 => Some(Property::Host), + 331 => Some(Property::HostedZoneId), + 185 => Some(Property::Hostname), + 190 => Some(Property::Hour), + 32 => Some(Property::HttpAuth), + 33 => Some(Property::HttpHeaders), + 168 => Some(Property::HttpRsvpEnable), + 169 => Some(Property::HttpRsvpLinkExpiry), + 175 => Some(Property::HttpRsvpTemplate), + 170 => Some(Property::HttpRsvpUrl), + 842 => Some(Property::HttpRua), + 234 => Some(Property::HumanResult), + 807 => Some(Property::ICalendarData), + 1 => Some(Property::Id), + 621 => Some(Property::IdTokenExpiry), + 91 => Some(Property::IdentityAlignment), + 376 => Some(Property::If), + 320 => Some(Property::ImpersonateServiceAccount), + 546 => Some(Property::ImplicitTls), + 128 => Some(Property::InMemoryStore), + 651 => Some(Property::InboundReportAddresses), + 652 => Some(Property::InboundReportForwarding), + 70 => Some(Property::Incidents), + 352 => Some(Property::IncludeSource), + 94 => Some(Property::IndexAsn), + 95 => Some(Property::IndexAsnName), + 664 => Some(Property::IndexBatchSize), + 667 => Some(Property::IndexCalendar), + 668 => Some(Property::IndexCalendarFields), + 670 => Some(Property::IndexContactFields), + 669 => Some(Property::IndexContacts), + 96 => Some(Property::IndexCountry), + 671 => Some(Property::IndexEmail), + 672 => Some(Property::IndexEmailFields), + 421 => Some(Property::IndexKey), + 673 => Some(Property::IndexTelemetry), + 674 => Some(Property::IndexTracingFields), + 422 => Some(Property::IndexValue), + 736 => Some(Property::IndicatorParameters), + 822 => Some(Property::InitialDelay), + 500 => Some(Property::Interval), + 516 => Some(Property::Intervals), + 752 => Some(Property::IpLimit), + 543 => Some(Property::IpLookupStrategy), + 290 => Some(Property::IpRevPtr), + 289 => Some(Property::IpRevResult), + 707 => Some(Property::IsActive), + 755 => Some(Property::IsArchive), + 756 => Some(Property::IsBad), + 340 => Some(Property::IsEnabled), + 806 => Some(Property::IsFromOrganizer), + 491 => Some(Property::IsGlobPattern), + 416 => Some(Property::IsGzipped), + 757 => Some(Property::IsNz), + 564 => Some(Property::IsSenderAllowed), + 776 => Some(Property::IsSpam), + 741 => Some(Property::IsTls), + 181 => Some(Property::Issuer), + 606 => Some(Property::IssuerUrl), + 172 => Some(Property::ItipMaxSize), + 824 => Some(Property::Jitter), + 334 => Some(Property::Key), + 337 => Some(Property::KeyName), + 120 => Some(Property::KeyPrefix), + 853 => Some(Property::KeyValues), + 391 => Some(Property::L1Ratio), + 392 => Some(Property::L2Ratio), + 186 => Some(Property::LastRenewal), + 727 => Some(Property::LearnHamFromCard), + 735 => Some(Property::LearnHamFromReply), + 728 => Some(Property::LearnSpamFromRblHits), + 729 => Some(Property::LearnSpamFromTraps), + 373 => Some(Property::Level), + 370 => Some(Property::LicenseKey), + 183 => Some(Property::ListenerIds), + 188 => Some(Property::Listeners), + 869 => Some(Property::LivePropertyMaxSize), + 7 => Some(Property::Locale), + 341 => Some(Property::Logo), + 371 => Some(Property::LogoUrl), + 682 => Some(Property::LoiterBanPeriod), + 681 => Some(Property::LoiterBanRate), + 854 => Some(Property::Lossy), + 384 => Some(Property::MachineId), + 793 => Some(Property::MailExchangers), + 284 => Some(Property::MailFrom), + 509 => Some(Property::MailFromTimeout), + 841 => Some(Property::MailRua), + 154 => Some(Property::MailingLists), + 796 => Some(Property::MaintenanceType), + 318 => Some(Property::ManagedZone), + 374 => Some(Property::Match), + 23 => Some(Property::MaxAddressBooks), + 566 => Some(Property::MaxAge), + 576 => Some(Property::MaxAllowedPacket), + 115 => Some(Property::MaxApiKeys), + 114 => Some(Property::MaxAppPasswords), + 353 => Some(Property::MaxAttachmentSize), + 511 => Some(Property::MaxAttempts), + 157 => Some(Property::MaxAttendees), + 425 => Some(Property::MaxAuthFailures), + 160 => Some(Property::MaxCalendars), + 201 => Some(Property::MaxChangesHistory), + 426 => Some(Property::MaxConcurrent), + 439 => Some(Property::MaxConcurrentRequests), + 442 => Some(Property::MaxConcurrentUploads), + 603 => Some(Property::MaxConnections), + 24 => Some(Property::MaxContacts), + 702 => Some(Property::MaxCpuCycles), + 823 => Some(Property::MaxDelay), + 530 => Some(Property::MaxDuration), + 417 => Some(Property::MaxEntries), + 418 => Some(Property::MaxEntrySize), + 163 => Some(Property::MaxEventNotifications), + 161 => Some(Property::MaxEvents), + 547 => Some(Property::MaxFailures), + 378 => Some(Property::MaxFiles), + 379 => Some(Property::MaxFolders), + 715 => Some(Property::MaxHeaderSize), + 159 => Some(Property::MaxICalendarSize), + 363 => Some(Property::MaxIdentities), + 716 => Some(Property::MaxIncludes), + 717 => Some(Property::MaxLocalVars), + 866 => Some(Property::MaxLockTimeout), + 867 => Some(Property::MaxLocks), + 355 => Some(Property::MaxMailboxDepth), + 356 => Some(Property::MaxMailboxNameLength), + 364 => Some(Property::MaxMailboxes), + 365 => Some(Property::MaxMaskedAddresses), + 718 => Some(Property::MaxMatchVars), + 354 => Some(Property::MaxMessageSize), + 361 => Some(Property::MaxMessages), + 438 => Some(Property::MaxMethodCalls), + 544 => Some(Property::MaxMultihomed), + 545 => Some(Property::MaxMxHosts), + 720 => Some(Property::MaxNestedBlocks), + 721 => Some(Property::MaxNestedForEvery), + 703 => Some(Property::MaxNestedIncludes), + 722 => Some(Property::MaxNestedTests), + 704 => Some(Property::MaxOutMessages), + 162 => Some(Property::MaxParticipantIdentities), + 366 => Some(Property::MaxPublicKeys), + 561 => Some(Property::MaxReceivedHeaders), + 173 => Some(Property::MaxRecipients), + 580 => Some(Property::MaxReconnects), + 158 => Some(Property::MaxRecurrenceExpansions), + 705 => Some(Property::MaxRedirects), + 852 => Some(Property::MaxReportSize), + 427 => Some(Property::MaxRequestRate), + 428 => Some(Property::MaxRequestSize), + 527 => Some(Property::MaxResponseSize), + 871 => Some(Property::MaxResults), + 18 => Some(Property::MaxRetries), + 648 => Some(Property::MaxRetryWait), + 719 => Some(Property::MaxScriptNameLength), + 723 => Some(Property::MaxScriptSize), + 726 => Some(Property::MaxScripts), + 696 => Some(Property::MaxShares), + 101 => Some(Property::MaxSize), + 724 => Some(Property::MaxStringLength), + 362 => Some(Property::MaxSubmissions), + 458 => Some(Property::MaxSubscriptions), + 444 => Some(Property::MaxUploadCount), + 443 => Some(Property::MaxUploadSize), + 22 => Some(Property::MaxVCardSize), + 725 => Some(Property::MaxVarNameLength), + 706 => Some(Property::MaxVarSize), + 864 => Some(Property::MemberGroupIds), + 19 => Some(Property::MemberTenantId), + 92 => Some(Property::Message), + 698 => Some(Property::MessageIdHostname), + 819 => Some(Property::MessageIds), + 145 => Some(Property::Messages), + 493 => Some(Property::Metric), + 497 => Some(Property::Metrics), + 207 => Some(Property::MetricsCollectionInterval), + 498 => Some(Property::MetricsPolicy), + 731 => Some(Property::MinHamSamples), + 649 => Some(Property::MinRetryWait), + 732 => Some(Property::MinSpamSamples), + 166 => Some(Property::MinTriggerInterval), + 191 => Some(Property::Minute), + 567 => Some(Property::Mode), + 28 => Some(Property::Model), + 764 => Some(Property::ModelId), + 30 => Some(Property::ModelType), + 522 => Some(Property::MtPriority), + 570 => Some(Property::MtaSts), + 572 => Some(Property::MtaStsTimeout), + 859 => Some(Property::Multiline), + 550 => Some(Property::MustMatchSender), + 568 => Some(Property::MxHosts), + 25 => Some(Property::Name), + 414 => Some(Property::Namespace), + 156 => Some(Property::NegativeTtl), + 634 => Some(Property::NextNotify), + 633 => Some(Property::NextRetry), + 223 => Some(Property::NextTransitionAt), + 700 => Some(Property::NoCapabilityCheck), + 587 => Some(Property::NoEcho), + 523 => Some(Property::NoSoliciting), + 184 => Some(Property::NodeId), + 179 => Some(Property::NotValidAfter), + 180 => Some(Property::NotValidBefore), + 513 => Some(Property::Notify), + 642 => Some(Property::NotifyCount), + 643 => Some(Property::NotifyDue), + 390 => Some(Property::NumFeatures), + 350 => Some(Property::NumReplicas), + 351 => Some(Property::NumShards), + 813 => Some(Property::OnSuccessRenewCertificate), + 495 => Some(Property::OpenTelemetry), + 630 => Some(Property::Options), + 645 => Some(Property::Orcpt), + 241 => Some(Property::OrgName), + 843 => Some(Property::OrganizationName), + 301 => Some(Property::Origin), + 71 => Some(Property::OriginalEnvelopeId), + 72 => Some(Property::OriginalMailFrom), + 73 => Some(Property::OriginalRcptTo), + 5 => Some(Property::OtpAuth), + 625 => Some(Property::OtpCode), + 626 => Some(Property::OtpUrl), + 653 => Some(Property::OutboundReportDomain), + 654 => Some(Property::OutboundReportSubmitter), + 590 => Some(Property::OverrideProxyTrustedNetworks), + 239 => Some(Property::OverrideType), + 324 => Some(Property::OvhEndpoint), + 737 => Some(Property::Parameters), + 433 => Some(Property::ParseLimitContact), + 434 => Some(Property::ParseLimitEmail), + 432 => Some(Property::ParseLimitEvent), + 113 => Some(Property::PasswordDefaultExpiry), + 109 => Some(Property::PasswordHashAlgorithm), + 111 => Some(Property::PasswordMaxLength), + 110 => Some(Property::PasswordMinLength), + 112 => Some(Property::PasswordMinStrength), + 380 => Some(Property::Path), + 646 => Some(Property::Period), + 48 => Some(Property::Permissions), + 583 => Some(Property::PingInterval), + 524 => Some(Property::Pipelining), + 846 => Some(Property::Policies), + 250 => Some(Property::PolicyAdkim), + 251 => Some(Property::PolicyAspf), + 252 => Some(Property::PolicyDisposition), + 248 => Some(Property::PolicyDomain), + 255 => Some(Property::PolicyFailureReportingOptions), + 237 => Some(Property::PolicyIdentifier), + 840 => Some(Property::PolicyIdentifiers), + 262 => Some(Property::PolicyOverrideReasons), + 848 => Some(Property::PolicyStrings), + 253 => Some(Property::PolicySubdomainDisposition), + 254 => Some(Property::PolicyTestingMode), + 847 => Some(Property::PolicyType), + 249 => Some(Property::PolicyVersion), + 489 => Some(Property::PollInterval), + 311 => Some(Property::PollingInterval), + 478 => Some(Property::PoolMaxConnections), + 577 => Some(Property::PoolMinConnections), + 631 => Some(Property::PoolRecyclingMethod), + 479 => Some(Property::PoolTimeoutCreate), + 480 => Some(Property::PoolTimeoutRecycle), + 481 => Some(Property::PoolTimeoutWait), + 657 => Some(Property::PoolWorkers), + 299 => Some(Property::Port), + 856 => Some(Property::Prefix), + 306 => Some(Property::PreserveIntermediates), + 483 => Some(Property::Priority), + 177 => Some(Property::PrivateKey), + 319 => Some(Property::PrivateZone), + 332 => Some(Property::PrivateZoneOnly), + 661 => Some(Property::Profile), + 317 => Some(Property::ProjectId), + 496 => Some(Property::Prometheus), + 765 => Some(Property::Prompt), + 313 => Some(Property::PropagationDelay), + 312 => Some(Property::PropagationTimeout), + 713 => Some(Property::ProtectedHeaders), + 298 => Some(Property::Protocol), + 533 => Some(Property::ProtocolVersion), + 795 => Some(Property::ProviderInfo), + 792 => Some(Property::ProxyTrustedNetworks), + 218 => Some(Property::PublicKey), + 302 => Some(Property::PublishRecords), + 448 => Some(Property::PushAttemptWait), + 449 => Some(Property::PushMaxAttempts), + 452 => Some(Property::PushRequestTimeout), + 450 => Some(Property::PushRetryWait), + 454 => Some(Property::PushShardsTotal), + 451 => Some(Property::PushThrottle), + 453 => Some(Property::PushVerifyTimeout), + 786 => Some(Property::QueryEmailAliases), + 783 => Some(Property::QueryLogin), + 437 => Some(Property::QueryMaxResults), + 785 => Some(Property::QueryMemberOf), + 784 => Some(Property::QueryRecipient), + 514 => Some(Property::QueueId), + 644 => Some(Property::QueueName), + 394 => Some(Property::Quotas), + 532 => Some(Property::Rate), + 410 => Some(Property::RateLimit), + 397 => Some(Property::RateLimitAnonymous), + 396 => Some(Property::RateLimitAuthenticated), + 767 => Some(Property::Ratio), + 510 => Some(Property::RcptToTimeout), + 650 => Some(Property::ReadFromReplicas), + 578 => Some(Property::ReadReplicas), + 45 => Some(Property::Reason), + 63 => Some(Property::ReceivedAt), + 636 => Some(Property::ReceivedFromIp), + 637 => Some(Property::ReceivedViaPort), + 836 => Some(Property::ReceivingIp), + 835 => Some(Property::ReceivingMxHelo), + 834 => Some(Property::ReceivingMxHostname), + 484 => Some(Property::Recipients), + 256 => Some(Property::Records), + 805 => Some(Property::RecurrenceId), + 605 => Some(Property::RedirectUris), + 419 => Some(Property::Refresh), + 617 => Some(Property::RefreshTokenExpiry), + 618 => Some(Property::RefreshTokenRenewal), + 330 => Some(Property::Region), + 563 => Some(Property::RejectNonFqdn), + 282 => Some(Property::RemoteIp), + 17 => Some(Property::RenewBefore), + 66 => Some(Property::Report), + 349 => Some(Property::ReportAddressUri), + 244 => Some(Property::ReportId), + 74 => Some(Property::ReportedDomains), + 75 => Some(Property::ReportedUris), + 76 => Some(Property::ReportingMta), + 870 => Some(Property::RequestMaxSize), + 123 => Some(Property::RequestTlsCertificate), + 551 => Some(Property::Require), + 607 => Some(Property::RequireAudience), + 615 => Some(Property::RequireClientRegistration), + 608 => Some(Property::RequireScopes), + 525 => Some(Property::RequireTls), + 733 => Some(Property::ReservoirCapacity), + 51 => Some(Property::ResourceUrl), + 212 => Some(Property::ResponseCode), + 213 => Some(Property::ResponseEnhanced), + 401 => Some(Property::ResponseHeaders), + 211 => Some(Property::ResponseHostname), + 214 => Some(Property::ResponseMessage), + 761 => Some(Property::ResponsePosCategory), + 762 => Some(Property::ResponsePosConfidence), + 763 => Some(Property::ResponsePosExplanation), + 233 => Some(Property::Result), + 832 => Some(Property::ResultType), + 228 => Some(Property::RetireAfter), + 420 => Some(Property::Retry), + 640 => Some(Property::RetryCount), + 641 => Some(Property::RetryDue), + 635 => Some(Property::ReturnPath), + 692 => Some(Property::ReverseIpVerify), + 565 => Some(Property::Rewrite), + 193 => Some(Property::RoleIds), + 152 => Some(Property::Roles), + 857 => Some(Property::Rotate), + 227 => Some(Property::RotateAfter), + 540 => Some(Property::Route), + 236 => Some(Property::Rua), + 119 => Some(Property::SasToken), + 549 => Some(Property::SaslMechanisms), + 683 => Some(Property::ScanBanPaths), + 685 => Some(Property::ScanBanPeriod), + 684 => Some(Property::ScanBanRate), + 541 => Some(Property::Schedule), + 143 => Some(Property::Scheduling), + 281 => Some(Property::Scope), + 745 => Some(Property::Score), + 771 => Some(Property::ScoreDiscard), + 772 => Some(Property::ScoreReject), + 773 => Some(Property::ScoreSpam), + 553 => Some(Property::Script), + 127 => Some(Property::SearchStore), + 3 => Some(Property::Secret), + 328 => Some(Property::SecretAccessKey), + 326 => Some(Property::SecretApiKey), + 659 => Some(Property::SecretKey), + 660 => Some(Property::SecurityToken), + 222 => Some(Property::Selector), + 226 => Some(Property::SelectorTemplate), + 230 => Some(Property::SendFrequency), + 833 => Some(Property::SendingMtaIp), + 97 => Some(Property::Separator), + 121 => Some(Property::ServerHostname), + 308 => Some(Property::Servers), + 316 => Some(Property::ServiceAccountJson), + 794 => Some(Property::Services), + 329 => Some(Property::SessionToken), + 440 => Some(Property::SetMaxObjects), + 830 => Some(Property::ShardIndex), + 336 => Some(Property::Sig0Algorithm), + 623 => Some(Property::SignatureAlgorithm), + 624 => Some(Property::SignatureKey), + 335 => Some(Property::SignerName), + 64 => Some(Property::Size), + 423 => Some(Property::SkipFirst), + 552 => Some(Property::SmtpGreeting), + 441 => Some(Property::SnippetMaxResults), + 591 => Some(Property::SocketBacklog), + 592 => Some(Property::SocketNoDelay), + 593 => Some(Property::SocketReceiveBufferSize), + 594 => Some(Property::SocketReuseAddress), + 595 => Some(Property::SocketReusePort), + 596 => Some(Property::SocketSendBufferSize), + 597 => Some(Property::SocketTosV4), + 598 => Some(Property::SocketTtl), + 77 => Some(Property::SourceIp), + 504 => Some(Property::SourceIps), + 78 => Some(Property::SourcePort), + 775 => Some(Property::SpamFilterRulesUrl), + 90 => Some(Property::SpfDns), + 285 => Some(Property::SpfEhloDomain), + 286 => Some(Property::SpfEhloResult), + 688 => Some(Property::SpfEhloVerify), + 689 => Some(Property::SpfFromVerify), + 287 => Some(Property::SpfMailFromDomain), + 288 => Some(Property::SpfMailFromResult), + 267 => Some(Property::SpfResults), + 224 => Some(Property::Stage), + 529 => Some(Property::Stages), + 56 => Some(Property::StartTime), + 571 => Some(Property::StartTls), + 61 => Some(Property::Status), + 116 => Some(Property::StorageAccount), + 778 => Some(Property::Store), + 694 => Some(Property::Stores), + 816 => Some(Property::Strategy), + 347 => Some(Property::SubAddressing), + 41 => Some(Property::Subject), + 178 => Some(Property::SubjectAlternativeNames), + 368 => Some(Property::Subscribe), + 494 => Some(Property::Sum), + 808 => Some(Property::Summary), + 748 => Some(Property::Tag), + 746 => Some(Property::Tags), + 189 => Some(Property::TaskTypes), + 187 => Some(Property::Tasks), + 307 => Some(Property::TcpOnError), + 528 => Some(Property::TempFailOnError), + 27 => Some(Property::Temperature), + 167 => Some(Property::Template), + 831 => Some(Property::TenantId), + 153 => Some(Property::Tenants), + 2 => Some(Property::Text), + 377 => Some(Property::Then), + 219 => Some(Property::ThirdParty), + 220 => Some(Property::ThirdPartyHash), + 818 => Some(Property::ThreadName), + 791 => Some(Property::ThreadPoolSize), + 574 => Some(Property::ThreadsPerNode), + 862 => Some(Property::Throttle), + 8 => Some(Property::TimeZone), + 29 => Some(Property::Timeout), + 429 => Some(Property::TimeoutAnonymous), + 430 => Some(Property::TimeoutAuthenticated), + 534 => Some(Property::TimeoutCommand), + 535 => Some(Property::TimeoutConnect), + 581 => Some(Property::TimeoutConnection), + 536 => Some(Property::TimeoutData), + 431 => Some(Property::TimeoutIdle), + 461 => Some(Property::TimeoutMessage), + 582 => Some(Property::TimeoutRequest), + 462 => Some(Property::TimeoutSession), + 482 => Some(Property::Timestamp), + 55 => Some(Property::Title), + 542 => Some(Property::Tls), + 599 => Some(Property::TlsDisableCipherSuites), + 600 => Some(Property::TlsDisableProtocols), + 601 => Some(Property::TlsIgnoreClientOrder), + 602 => Some(Property::TlsImplicit), + 573 => Some(Property::TlsTimeout), + 42 => Some(Property::To), + 817 => Some(Property::TotalDeadline), + 850 => Some(Property::TotalFailedSessions), + 849 => Some(Property::TotalSuccessfulSessions), + 815 => Some(Property::TraceId), + 129 => Some(Property::Tracer), + 734 => Some(Property::TrainFrequency), + 385 => Some(Property::TransactionRetryDelay), + 386 => Some(Property::TransactionRetryLimit), + 387 => Some(Property::TransactionTimeout), + 531 => Some(Property::TransferLimit), + 769 => Some(Property::TrustContacts), + 774 => Some(Property::TrustReplies), + 338 => Some(Property::TsigAlgorithm), + 310 => Some(Property::Ttl), + 54 => Some(Property::UnpackDirectory), + 812 => Some(Property::UpdateRecords), + 445 => Some(Property::UploadQuota), + 446 => Some(Property::UploadTtl), + 31 => Some(Property::Url), + 753 => Some(Property::UrlLimit), + 52 => Some(Property::UrlPrefix), + 647 => Some(Property::Urls), + 400 => Some(Property::UsePermissiveCors), + 309 => Some(Property::UseTls), + 402 => Some(Property::UseXForwarded), + 395 => Some(Property::UsedDiskQuota), + 79 => Some(Property::UserAgent), + 620 => Some(Property::UserCodeExpiry), + 131 => Some(Property::Username), + 610 => Some(Property::UsernameDomain), + 413 => Some(Property::ValidateDomain), + 492 => Some(Property::Value), + 675 => Some(Property::VariableName), + 80 => Some(Property::Version), + 526 => Some(Property::Vrfy), + 548 => Some(Property::WaitOnFail), + 455 => Some(Property::WebsocketHeartbeat), + 456 => Some(Property::WebsocketThrottle), + 457 => Some(Property::WebsocketTimeout), + 749 => Some(Property::Zone), + 98 => Some(Property::ZoneIpV4), + 99 => Some(Property::ZoneIpV6), + _ => None, + } + } + + const COUNT: usize = 100; +} + +impl serde::Serialize for Property { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for Property { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = Cow::::deserialize(deserializer)?; + Self::parse(&s).ok_or_else(|| serde::de::Error::unknown_variant(&s, &[])) + } +} + +impl ObjectType { + pub fn flags(&self) -> u64 { + match self { + ObjectType::Account => Account::FLAGS, + ObjectType::AccountPassword => AccountPassword::FLAGS, + ObjectType::AccountSettings => AccountSettings::FLAGS, + ObjectType::AcmeProvider => AcmeProvider::FLAGS, + ObjectType::Action => Action::FLAGS, + ObjectType::AddressBook => AddressBook::FLAGS, + ObjectType::AiModel => AiModel::FLAGS, + ObjectType::Alert => Alert::FLAGS, + ObjectType::AllowedIp => AllowedIp::FLAGS, + ObjectType::ApiKey => ApiKey::FLAGS, + ObjectType::AppPassword => AppPassword::FLAGS, + ObjectType::Application => Application::FLAGS, + ObjectType::ArchivedItem => ArchivedItem::FLAGS, + ObjectType::ArfExternalReport => ArfExternalReport::FLAGS, + ObjectType::Asn => Asn::FLAGS, + ObjectType::Authentication => Authentication::FLAGS, + ObjectType::BlobStore => BlobStore::FLAGS, + ObjectType::BlockedIp => BlockedIp::FLAGS, + ObjectType::Bootstrap => Bootstrap::FLAGS, + ObjectType::Cache => Cache::FLAGS, + ObjectType::Calendar => Calendar::FLAGS, + ObjectType::CalendarAlarm => CalendarAlarm::FLAGS, + ObjectType::CalendarScheduling => CalendarScheduling::FLAGS, + ObjectType::Certificate => Certificate::FLAGS, + ObjectType::ClusterNode => ClusterNode::FLAGS, + ObjectType::ClusterRole => ClusterRole::FLAGS, + ObjectType::Coordinator => Coordinator::FLAGS, + ObjectType::DataRetention => DataRetention::FLAGS, + ObjectType::DataStore => DataStore::FLAGS, + ObjectType::Directory => Directory::FLAGS, + ObjectType::DkimReportSettings => DkimReportSettings::FLAGS, + ObjectType::DkimSignature => DkimSignature::FLAGS, + ObjectType::DmarcExternalReport => DmarcExternalReport::FLAGS, + ObjectType::DmarcInternalReport => DmarcInternalReport::FLAGS, + ObjectType::DmarcReportSettings => DmarcReportSettings::FLAGS, + ObjectType::DnsResolver => DnsResolver::FLAGS, + ObjectType::DnsServer => DnsServer::FLAGS, + ObjectType::Domain => Domain::FLAGS, + ObjectType::DsnReportSettings => DsnReportSettings::FLAGS, + ObjectType::Email => Email::FLAGS, + ObjectType::Enterprise => Enterprise::FLAGS, + ObjectType::EventTracingLevel => EventTracingLevel::FLAGS, + ObjectType::FileStorage => FileStorage::FLAGS, + ObjectType::Http => Http::FLAGS, + ObjectType::HttpForm => HttpForm::FLAGS, + ObjectType::HttpLookup => HttpLookup::FLAGS, + ObjectType::Imap => Imap::FLAGS, + ObjectType::InMemoryStore => InMemoryStore::FLAGS, + ObjectType::Jmap => Jmap::FLAGS, + ObjectType::Log => Log::FLAGS, + ObjectType::MailingList => MailingList::FLAGS, + ObjectType::MaskedEmail => MaskedEmail::FLAGS, + ObjectType::MemoryLookupKey => MemoryLookupKey::FLAGS, + ObjectType::MemoryLookupKeyValue => MemoryLookupKeyValue::FLAGS, + ObjectType::Metric => Metric::FLAGS, + ObjectType::Metrics => Metrics::FLAGS, + ObjectType::MetricsStore => MetricsStore::FLAGS, + ObjectType::MtaConnectionStrategy => MtaConnectionStrategy::FLAGS, + ObjectType::MtaDeliverySchedule => MtaDeliverySchedule::FLAGS, + ObjectType::MtaExtensions => MtaExtensions::FLAGS, + ObjectType::MtaHook => MtaHook::FLAGS, + ObjectType::MtaInboundSession => MtaInboundSession::FLAGS, + ObjectType::MtaInboundThrottle => MtaInboundThrottle::FLAGS, + ObjectType::MtaMilter => MtaMilter::FLAGS, + ObjectType::MtaOutboundStrategy => MtaOutboundStrategy::FLAGS, + ObjectType::MtaOutboundThrottle => MtaOutboundThrottle::FLAGS, + ObjectType::MtaQueueQuota => MtaQueueQuota::FLAGS, + ObjectType::MtaRoute => MtaRoute::FLAGS, + ObjectType::MtaStageAuth => MtaStageAuth::FLAGS, + ObjectType::MtaStageConnect => MtaStageConnect::FLAGS, + ObjectType::MtaStageData => MtaStageData::FLAGS, + ObjectType::MtaStageEhlo => MtaStageEhlo::FLAGS, + ObjectType::MtaStageMail => MtaStageMail::FLAGS, + ObjectType::MtaStageRcpt => MtaStageRcpt::FLAGS, + ObjectType::MtaSts => MtaSts::FLAGS, + ObjectType::MtaTlsStrategy => MtaTlsStrategy::FLAGS, + ObjectType::MtaVirtualQueue => MtaVirtualQueue::FLAGS, + ObjectType::NetworkListener => NetworkListener::FLAGS, + ObjectType::OAuthClient => OAuthClient::FLAGS, + ObjectType::OidcProvider => OidcProvider::FLAGS, + ObjectType::PublicKey => PublicKey::FLAGS, + ObjectType::QueuedMessage => QueuedMessage::FLAGS, + ObjectType::ReportSettings => ReportSettings::FLAGS, + ObjectType::Role => Role::FLAGS, + ObjectType::Search => Search::FLAGS, + ObjectType::SearchStore => SearchStore::FLAGS, + ObjectType::Security => Security::FLAGS, + ObjectType::SenderAuth => SenderAuth::FLAGS, + ObjectType::Sharing => Sharing::FLAGS, + ObjectType::SieveSystemInterpreter => SieveSystemInterpreter::FLAGS, + ObjectType::SieveSystemScript => SieveSystemScript::FLAGS, + ObjectType::SieveUserInterpreter => SieveUserInterpreter::FLAGS, + ObjectType::SieveUserScript => SieveUserScript::FLAGS, + ObjectType::SpamClassifier => SpamClassifier::FLAGS, + ObjectType::SpamDnsblServer => SpamDnsblServer::FLAGS, + ObjectType::SpamDnsblSettings => SpamDnsblSettings::FLAGS, + ObjectType::SpamFileExtension => SpamFileExtension::FLAGS, + ObjectType::SpamLlm => SpamLlm::FLAGS, + ObjectType::SpamPyzor => SpamPyzor::FLAGS, + ObjectType::SpamRule => SpamRule::FLAGS, + ObjectType::SpamSettings => SpamSettings::FLAGS, + ObjectType::SpamTag => SpamTag::FLAGS, + ObjectType::SpamTrainingSample => SpamTrainingSample::FLAGS, + ObjectType::SpfReportSettings => SpfReportSettings::FLAGS, + ObjectType::StoreLookup => StoreLookup::FLAGS, + ObjectType::SystemSettings => SystemSettings::FLAGS, + ObjectType::Task => Task::FLAGS, + ObjectType::TaskManager => TaskManager::FLAGS, + ObjectType::Tenant => Tenant::FLAGS, + ObjectType::TlsExternalReport => TlsExternalReport::FLAGS, + ObjectType::TlsInternalReport => TlsInternalReport::FLAGS, + ObjectType::TlsReportSettings => TlsReportSettings::FLAGS, + ObjectType::Trace => Trace::FLAGS, + ObjectType::Tracer => Tracer::FLAGS, + ObjectType::TracingStore => TracingStore::FLAGS, + ObjectType::WebDav => WebDav::FLAGS, + ObjectType::WebHook => WebHook::FLAGS, + } + } + + pub fn indexes(&self) -> Vec { + match self { + ObjectType::Account => vec![ + IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::Type, + IndexSchemaType::Search, + IndexSchemaValueType::Enum, + ), + IndexSchema::new( + Property::DomainId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + IndexSchema::new( + Property::MemberGroupIds, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + IndexSchema::new( + Property::Name, + IndexSchemaType::Search, + IndexSchemaValueType::Keyword, + ), + ], + ObjectType::AcmeProvider => vec![ + IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + ], + ObjectType::AllowedIp => vec![IndexSchema::new( + Property::Address, + IndexSchemaType::Unique, + IndexSchemaValueType::IpMask, + )], + ObjectType::ArchivedItem => vec![IndexSchema::new( + Property::AccountId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::BlockedIp => vec![IndexSchema::new( + Property::Address, + IndexSchemaType::Unique, + IndexSchemaValueType::IpMask, + )], + ObjectType::Certificate => vec![IndexSchema::new( + Property::SubjectAlternativeNames, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + )], + ObjectType::ClusterRole => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::Directory => vec![IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::DkimSignature => vec![ + IndexSchema::new( + Property::DomainId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + ], + ObjectType::DnsServer => vec![IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::Domain => vec![ + IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + ), + ], + ObjectType::MailingList => vec![ + IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + ], + ObjectType::MaskedEmail => vec![IndexSchema::new( + Property::AccountId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::MemoryLookupKey => vec![IndexSchema::new( + Property::Namespace, + IndexSchemaType::Search, + IndexSchemaValueType::Keyword, + )], + ObjectType::MemoryLookupKeyValue => vec![IndexSchema::new( + Property::Namespace, + IndexSchemaType::Search, + IndexSchemaValueType::Keyword, + )], + ObjectType::MtaConnectionStrategy => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::MtaDeliverySchedule => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::MtaRoute => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::MtaTlsStrategy => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::MtaVirtualQueue => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::NetworkListener => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::OAuthClient => vec![ + IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::ClientId, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + ], + ObjectType::PublicKey => vec![IndexSchema::new( + Property::AccountId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::Role => vec![ + IndexSchema::new( + Property::Description, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + ), + IndexSchema::new( + Property::MemberTenantId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + ), + ], + ObjectType::SieveSystemScript => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SieveUserScript => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SpamDnsblServer => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SpamFileExtension => vec![IndexSchema::new( + Property::Extension, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SpamRule => vec![IndexSchema::new( + Property::Name, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SpamTag => vec![IndexSchema::new( + Property::Tag, + IndexSchemaType::Unique, + IndexSchemaValueType::Keyword, + )], + ObjectType::SpamTrainingSample => vec![IndexSchema::new( + Property::AccountId, + IndexSchemaType::Search, + IndexSchemaValueType::Id, + )], + ObjectType::Tenant => vec![IndexSchema::new( + Property::Text, + IndexSchemaType::Search, + IndexSchemaValueType::Text, + )], + _ => vec![], + } + } + + pub fn get_permission(&self) -> Permission { + match self { + ObjectType::Account => Permission::SysAccountGet, + ObjectType::AccountPassword => Permission::SysAccountPasswordGet, + ObjectType::AccountSettings => Permission::SysAccountSettingsGet, + ObjectType::AcmeProvider => Permission::SysAcmeProviderGet, + ObjectType::Action => Permission::SysActionGet, + ObjectType::AddressBook => Permission::SysAddressBookGet, + ObjectType::AiModel => Permission::SysAiModelGet, + ObjectType::Alert => Permission::SysAlertGet, + ObjectType::AllowedIp => Permission::SysAllowedIpGet, + ObjectType::ApiKey => Permission::SysApiKeyGet, + ObjectType::AppPassword => Permission::SysAppPasswordGet, + ObjectType::Application => Permission::SysApplicationGet, + ObjectType::ArchivedItem => Permission::SysArchivedItemGet, + ObjectType::ArfExternalReport => Permission::SysArfExternalReportGet, + ObjectType::Asn => Permission::SysAsnGet, + ObjectType::Authentication => Permission::SysAuthenticationGet, + ObjectType::BlobStore => Permission::SysBlobStoreGet, + ObjectType::BlockedIp => Permission::SysBlockedIpGet, + ObjectType::Bootstrap => Permission::SysBootstrapGet, + ObjectType::Cache => Permission::SysCacheGet, + ObjectType::Calendar => Permission::SysCalendarGet, + ObjectType::CalendarAlarm => Permission::SysCalendarAlarmGet, + ObjectType::CalendarScheduling => Permission::SysCalendarSchedulingGet, + ObjectType::Certificate => Permission::SysCertificateGet, + ObjectType::ClusterNode => Permission::SysClusterNodeGet, + ObjectType::ClusterRole => Permission::SysClusterRoleGet, + ObjectType::Coordinator => Permission::SysCoordinatorGet, + ObjectType::DataRetention => Permission::SysDataRetentionGet, + ObjectType::DataStore => Permission::SysDataStoreGet, + ObjectType::Directory => Permission::SysDirectoryGet, + ObjectType::DkimReportSettings => Permission::SysDkimReportSettingsGet, + ObjectType::DkimSignature => Permission::SysDkimSignatureGet, + ObjectType::DmarcExternalReport => Permission::SysDmarcExternalReportGet, + ObjectType::DmarcInternalReport => Permission::SysDmarcInternalReportGet, + ObjectType::DmarcReportSettings => Permission::SysDmarcReportSettingsGet, + ObjectType::DnsResolver => Permission::SysDnsResolverGet, + ObjectType::DnsServer => Permission::SysDnsServerGet, + ObjectType::Domain => Permission::SysDomainGet, + ObjectType::DsnReportSettings => Permission::SysDsnReportSettingsGet, + ObjectType::Email => Permission::SysEmailGet, + ObjectType::Enterprise => Permission::SysEnterpriseGet, + ObjectType::EventTracingLevel => Permission::SysEventTracingLevelGet, + ObjectType::FileStorage => Permission::SysFileStorageGet, + ObjectType::Http => Permission::SysHttpGet, + ObjectType::HttpForm => Permission::SysHttpFormGet, + ObjectType::HttpLookup => Permission::SysHttpLookupGet, + ObjectType::Imap => Permission::SysImapGet, + ObjectType::InMemoryStore => Permission::SysInMemoryStoreGet, + ObjectType::Jmap => Permission::SysJmapGet, + ObjectType::Log => Permission::SysLogGet, + ObjectType::MailingList => Permission::SysMailingListGet, + ObjectType::MaskedEmail => Permission::SysMaskedEmailGet, + ObjectType::MemoryLookupKey => Permission::SysMemoryLookupKeyGet, + ObjectType::MemoryLookupKeyValue => Permission::SysMemoryLookupKeyValueGet, + ObjectType::Metric => Permission::SysMetricGet, + ObjectType::Metrics => Permission::SysMetricsGet, + ObjectType::MetricsStore => Permission::SysMetricsStoreGet, + ObjectType::MtaConnectionStrategy => Permission::SysMtaConnectionStrategyGet, + ObjectType::MtaDeliverySchedule => Permission::SysMtaDeliveryScheduleGet, + ObjectType::MtaExtensions => Permission::SysMtaExtensionsGet, + ObjectType::MtaHook => Permission::SysMtaHookGet, + ObjectType::MtaInboundSession => Permission::SysMtaInboundSessionGet, + ObjectType::MtaInboundThrottle => Permission::SysMtaInboundThrottleGet, + ObjectType::MtaMilter => Permission::SysMtaMilterGet, + ObjectType::MtaOutboundStrategy => Permission::SysMtaOutboundStrategyGet, + ObjectType::MtaOutboundThrottle => Permission::SysMtaOutboundThrottleGet, + ObjectType::MtaQueueQuota => Permission::SysMtaQueueQuotaGet, + ObjectType::MtaRoute => Permission::SysMtaRouteGet, + ObjectType::MtaStageAuth => Permission::SysMtaStageAuthGet, + ObjectType::MtaStageConnect => Permission::SysMtaStageConnectGet, + ObjectType::MtaStageData => Permission::SysMtaStageDataGet, + ObjectType::MtaStageEhlo => Permission::SysMtaStageEhloGet, + ObjectType::MtaStageMail => Permission::SysMtaStageMailGet, + ObjectType::MtaStageRcpt => Permission::SysMtaStageRcptGet, + ObjectType::MtaSts => Permission::SysMtaStsGet, + ObjectType::MtaTlsStrategy => Permission::SysMtaTlsStrategyGet, + ObjectType::MtaVirtualQueue => Permission::SysMtaVirtualQueueGet, + ObjectType::NetworkListener => Permission::SysNetworkListenerGet, + ObjectType::OAuthClient => Permission::SysOAuthClientGet, + ObjectType::OidcProvider => Permission::SysOidcProviderGet, + ObjectType::PublicKey => Permission::SysPublicKeyGet, + ObjectType::QueuedMessage => Permission::SysQueuedMessageGet, + ObjectType::ReportSettings => Permission::SysReportSettingsGet, + ObjectType::Role => Permission::SysRoleGet, + ObjectType::Search => Permission::SysSearchGet, + ObjectType::SearchStore => Permission::SysSearchStoreGet, + ObjectType::Security => Permission::SysSecurityGet, + ObjectType::SenderAuth => Permission::SysSenderAuthGet, + ObjectType::Sharing => Permission::SysSharingGet, + ObjectType::SieveSystemInterpreter => Permission::SysSieveSystemInterpreterGet, + ObjectType::SieveSystemScript => Permission::SysSieveSystemScriptGet, + ObjectType::SieveUserInterpreter => Permission::SysSieveUserInterpreterGet, + ObjectType::SieveUserScript => Permission::SysSieveUserScriptGet, + ObjectType::SpamClassifier => Permission::SysSpamClassifierGet, + ObjectType::SpamDnsblServer => Permission::SysSpamDnsblServerGet, + ObjectType::SpamDnsblSettings => Permission::SysSpamDnsblSettingsGet, + ObjectType::SpamFileExtension => Permission::SysSpamFileExtensionGet, + ObjectType::SpamLlm => Permission::SysSpamLlmGet, + ObjectType::SpamPyzor => Permission::SysSpamPyzorGet, + ObjectType::SpamRule => Permission::SysSpamRuleGet, + ObjectType::SpamSettings => Permission::SysSpamSettingsGet, + ObjectType::SpamTag => Permission::SysSpamTagGet, + ObjectType::SpamTrainingSample => Permission::SysSpamTrainingSampleGet, + ObjectType::SpfReportSettings => Permission::SysSpfReportSettingsGet, + ObjectType::StoreLookup => Permission::SysStoreLookupGet, + ObjectType::SystemSettings => Permission::SysSystemSettingsGet, + ObjectType::Task => Permission::SysTaskGet, + ObjectType::TaskManager => Permission::SysTaskManagerGet, + ObjectType::Tenant => Permission::SysTenantGet, + ObjectType::TlsExternalReport => Permission::SysTlsExternalReportGet, + ObjectType::TlsInternalReport => Permission::SysTlsInternalReportGet, + ObjectType::TlsReportSettings => Permission::SysTlsReportSettingsGet, + ObjectType::Trace => Permission::SysTraceGet, + ObjectType::Tracer => Permission::SysTracerGet, + ObjectType::TracingStore => Permission::SysTracingStoreGet, + ObjectType::WebDav => Permission::SysWebDavGet, + ObjectType::WebHook => Permission::SysWebHookGet, + } + } + + pub fn query_permission(&self) -> Permission { + match self { + ObjectType::Account => Permission::SysAccountQuery, + ObjectType::AcmeProvider => Permission::SysAcmeProviderQuery, + ObjectType::Action => Permission::SysActionQuery, + ObjectType::AiModel => Permission::SysAiModelQuery, + ObjectType::Alert => Permission::SysAlertQuery, + ObjectType::AllowedIp => Permission::SysAllowedIpQuery, + ObjectType::ApiKey => Permission::SysApiKeyQuery, + ObjectType::AppPassword => Permission::SysAppPasswordQuery, + ObjectType::Application => Permission::SysApplicationQuery, + ObjectType::ArchivedItem => Permission::SysArchivedItemQuery, + ObjectType::ArfExternalReport => Permission::SysArfExternalReportQuery, + ObjectType::BlockedIp => Permission::SysBlockedIpQuery, + ObjectType::Certificate => Permission::SysCertificateQuery, + ObjectType::ClusterNode => Permission::SysClusterNodeQuery, + ObjectType::ClusterRole => Permission::SysClusterRoleQuery, + ObjectType::Directory => Permission::SysDirectoryQuery, + ObjectType::DkimSignature => Permission::SysDkimSignatureQuery, + ObjectType::DmarcExternalReport => Permission::SysDmarcExternalReportQuery, + ObjectType::DmarcInternalReport => Permission::SysDmarcInternalReportQuery, + ObjectType::DnsServer => Permission::SysDnsServerQuery, + ObjectType::Domain => Permission::SysDomainQuery, + ObjectType::EventTracingLevel => Permission::SysEventTracingLevelQuery, + ObjectType::HttpLookup => Permission::SysHttpLookupQuery, + ObjectType::Log => Permission::SysLogQuery, + ObjectType::MailingList => Permission::SysMailingListQuery, + ObjectType::MaskedEmail => Permission::SysMaskedEmailQuery, + ObjectType::MemoryLookupKey => Permission::SysMemoryLookupKeyQuery, + ObjectType::MemoryLookupKeyValue => Permission::SysMemoryLookupKeyValueQuery, + ObjectType::Metric => Permission::SysMetricQuery, + ObjectType::MtaConnectionStrategy => Permission::SysMtaConnectionStrategyQuery, + ObjectType::MtaDeliverySchedule => Permission::SysMtaDeliveryScheduleQuery, + ObjectType::MtaHook => Permission::SysMtaHookQuery, + ObjectType::MtaInboundThrottle => Permission::SysMtaInboundThrottleQuery, + ObjectType::MtaMilter => Permission::SysMtaMilterQuery, + ObjectType::MtaOutboundThrottle => Permission::SysMtaOutboundThrottleQuery, + ObjectType::MtaQueueQuota => Permission::SysMtaQueueQuotaQuery, + ObjectType::MtaRoute => Permission::SysMtaRouteQuery, + ObjectType::MtaTlsStrategy => Permission::SysMtaTlsStrategyQuery, + ObjectType::MtaVirtualQueue => Permission::SysMtaVirtualQueueQuery, + ObjectType::NetworkListener => Permission::SysNetworkListenerQuery, + ObjectType::OAuthClient => Permission::SysOAuthClientQuery, + ObjectType::PublicKey => Permission::SysPublicKeyQuery, + ObjectType::QueuedMessage => Permission::SysQueuedMessageQuery, + ObjectType::Role => Permission::SysRoleQuery, + ObjectType::SieveSystemScript => Permission::SysSieveSystemScriptQuery, + ObjectType::SieveUserScript => Permission::SysSieveUserScriptQuery, + ObjectType::SpamDnsblServer => Permission::SysSpamDnsblServerQuery, + ObjectType::SpamFileExtension => Permission::SysSpamFileExtensionQuery, + ObjectType::SpamRule => Permission::SysSpamRuleQuery, + ObjectType::SpamTag => Permission::SysSpamTagQuery, + ObjectType::SpamTrainingSample => Permission::SysSpamTrainingSampleQuery, + ObjectType::StoreLookup => Permission::SysStoreLookupQuery, + ObjectType::Task => Permission::SysTaskQuery, + ObjectType::Tenant => Permission::SysTenantQuery, + ObjectType::TlsExternalReport => Permission::SysTlsExternalReportQuery, + ObjectType::TlsInternalReport => Permission::SysTlsInternalReportQuery, + ObjectType::Trace => Permission::SysTraceQuery, + ObjectType::Tracer => Permission::SysTracerQuery, + ObjectType::WebHook => Permission::SysWebHookQuery, + _ => unreachable!(), + } + } + + pub fn set_permission(&self) -> [Permission; 3] { + match self { + ObjectType::Account => [ + Permission::SysAccountCreate, + Permission::SysAccountUpdate, + Permission::SysAccountDestroy, + ], + ObjectType::AccountPassword => [ + Permission::SysAccountPasswordUpdate, + Permission::SysAccountPasswordUpdate, + Permission::SysAccountPasswordUpdate, + ], + ObjectType::AccountSettings => [ + Permission::SysAccountSettingsUpdate, + Permission::SysAccountSettingsUpdate, + Permission::SysAccountSettingsUpdate, + ], + ObjectType::AcmeProvider => [ + Permission::SysAcmeProviderCreate, + Permission::SysAcmeProviderUpdate, + Permission::SysAcmeProviderDestroy, + ], + ObjectType::Action => [ + Permission::SysActionCreate, + Permission::SysActionUpdate, + Permission::SysActionDestroy, + ], + ObjectType::AddressBook => [ + Permission::SysAddressBookUpdate, + Permission::SysAddressBookUpdate, + Permission::SysAddressBookUpdate, + ], + ObjectType::AiModel => [ + Permission::SysAiModelCreate, + Permission::SysAiModelUpdate, + Permission::SysAiModelDestroy, + ], + ObjectType::Alert => [ + Permission::SysAlertCreate, + Permission::SysAlertUpdate, + Permission::SysAlertDestroy, + ], + ObjectType::AllowedIp => [ + Permission::SysAllowedIpCreate, + Permission::SysAllowedIpUpdate, + Permission::SysAllowedIpDestroy, + ], + ObjectType::ApiKey => [ + Permission::SysApiKeyCreate, + Permission::SysApiKeyUpdate, + Permission::SysApiKeyDestroy, + ], + ObjectType::AppPassword => [ + Permission::SysAppPasswordCreate, + Permission::SysAppPasswordUpdate, + Permission::SysAppPasswordDestroy, + ], + ObjectType::Application => [ + Permission::SysApplicationCreate, + Permission::SysApplicationUpdate, + Permission::SysApplicationDestroy, + ], + ObjectType::ArchivedItem => [ + Permission::SysArchivedItemCreate, + Permission::SysArchivedItemUpdate, + Permission::SysArchivedItemDestroy, + ], + ObjectType::ArfExternalReport => [ + Permission::SysArfExternalReportCreate, + Permission::SysArfExternalReportUpdate, + Permission::SysArfExternalReportDestroy, + ], + ObjectType::Asn => [ + Permission::SysAsnUpdate, + Permission::SysAsnUpdate, + Permission::SysAsnUpdate, + ], + ObjectType::Authentication => [ + Permission::SysAuthenticationUpdate, + Permission::SysAuthenticationUpdate, + Permission::SysAuthenticationUpdate, + ], + ObjectType::BlobStore => [ + Permission::SysBlobStoreUpdate, + Permission::SysBlobStoreUpdate, + Permission::SysBlobStoreUpdate, + ], + ObjectType::BlockedIp => [ + Permission::SysBlockedIpCreate, + Permission::SysBlockedIpUpdate, + Permission::SysBlockedIpDestroy, + ], + ObjectType::Bootstrap => [ + Permission::SysBootstrapUpdate, + Permission::SysBootstrapUpdate, + Permission::SysBootstrapUpdate, + ], + ObjectType::Cache => [ + Permission::SysCacheUpdate, + Permission::SysCacheUpdate, + Permission::SysCacheUpdate, + ], + ObjectType::Calendar => [ + Permission::SysCalendarUpdate, + Permission::SysCalendarUpdate, + Permission::SysCalendarUpdate, + ], + ObjectType::CalendarAlarm => [ + Permission::SysCalendarAlarmUpdate, + Permission::SysCalendarAlarmUpdate, + Permission::SysCalendarAlarmUpdate, + ], + ObjectType::CalendarScheduling => [ + Permission::SysCalendarSchedulingUpdate, + Permission::SysCalendarSchedulingUpdate, + Permission::SysCalendarSchedulingUpdate, + ], + ObjectType::Certificate => [ + Permission::SysCertificateCreate, + Permission::SysCertificateUpdate, + Permission::SysCertificateDestroy, + ], + ObjectType::ClusterNode => [ + Permission::SysClusterNodeCreate, + Permission::SysClusterNodeUpdate, + Permission::SysClusterNodeDestroy, + ], + ObjectType::ClusterRole => [ + Permission::SysClusterRoleCreate, + Permission::SysClusterRoleUpdate, + Permission::SysClusterRoleDestroy, + ], + ObjectType::Coordinator => [ + Permission::SysCoordinatorUpdate, + Permission::SysCoordinatorUpdate, + Permission::SysCoordinatorUpdate, + ], + ObjectType::DataRetention => [ + Permission::SysDataRetentionUpdate, + Permission::SysDataRetentionUpdate, + Permission::SysDataRetentionUpdate, + ], + ObjectType::DataStore => [ + Permission::SysDataStoreUpdate, + Permission::SysDataStoreUpdate, + Permission::SysDataStoreUpdate, + ], + ObjectType::Directory => [ + Permission::SysDirectoryCreate, + Permission::SysDirectoryUpdate, + Permission::SysDirectoryDestroy, + ], + ObjectType::DkimReportSettings => [ + Permission::SysDkimReportSettingsUpdate, + Permission::SysDkimReportSettingsUpdate, + Permission::SysDkimReportSettingsUpdate, + ], + ObjectType::DkimSignature => [ + Permission::SysDkimSignatureCreate, + Permission::SysDkimSignatureUpdate, + Permission::SysDkimSignatureDestroy, + ], + ObjectType::DmarcExternalReport => [ + Permission::SysDmarcExternalReportCreate, + Permission::SysDmarcExternalReportUpdate, + Permission::SysDmarcExternalReportDestroy, + ], + ObjectType::DmarcInternalReport => [ + Permission::SysDmarcInternalReportCreate, + Permission::SysDmarcInternalReportUpdate, + Permission::SysDmarcInternalReportDestroy, + ], + ObjectType::DmarcReportSettings => [ + Permission::SysDmarcReportSettingsUpdate, + Permission::SysDmarcReportSettingsUpdate, + Permission::SysDmarcReportSettingsUpdate, + ], + ObjectType::DnsResolver => [ + Permission::SysDnsResolverUpdate, + Permission::SysDnsResolverUpdate, + Permission::SysDnsResolverUpdate, + ], + ObjectType::DnsServer => [ + Permission::SysDnsServerCreate, + Permission::SysDnsServerUpdate, + Permission::SysDnsServerDestroy, + ], + ObjectType::Domain => [ + Permission::SysDomainCreate, + Permission::SysDomainUpdate, + Permission::SysDomainDestroy, + ], + ObjectType::DsnReportSettings => [ + Permission::SysDsnReportSettingsUpdate, + Permission::SysDsnReportSettingsUpdate, + Permission::SysDsnReportSettingsUpdate, + ], + ObjectType::Email => [ + Permission::SysEmailUpdate, + Permission::SysEmailUpdate, + Permission::SysEmailUpdate, + ], + ObjectType::Enterprise => [ + Permission::SysEnterpriseUpdate, + Permission::SysEnterpriseUpdate, + Permission::SysEnterpriseUpdate, + ], + ObjectType::EventTracingLevel => [ + Permission::SysEventTracingLevelCreate, + Permission::SysEventTracingLevelUpdate, + Permission::SysEventTracingLevelDestroy, + ], + ObjectType::FileStorage => [ + Permission::SysFileStorageUpdate, + Permission::SysFileStorageUpdate, + Permission::SysFileStorageUpdate, + ], + ObjectType::Http => [ + Permission::SysHttpUpdate, + Permission::SysHttpUpdate, + Permission::SysHttpUpdate, + ], + ObjectType::HttpForm => [ + Permission::SysHttpFormUpdate, + Permission::SysHttpFormUpdate, + Permission::SysHttpFormUpdate, + ], + ObjectType::HttpLookup => [ + Permission::SysHttpLookupCreate, + Permission::SysHttpLookupUpdate, + Permission::SysHttpLookupDestroy, + ], + ObjectType::Imap => [ + Permission::SysImapUpdate, + Permission::SysImapUpdate, + Permission::SysImapUpdate, + ], + ObjectType::InMemoryStore => [ + Permission::SysInMemoryStoreUpdate, + Permission::SysInMemoryStoreUpdate, + Permission::SysInMemoryStoreUpdate, + ], + ObjectType::Jmap => [ + Permission::SysJmapUpdate, + Permission::SysJmapUpdate, + Permission::SysJmapUpdate, + ], + ObjectType::Log => [ + Permission::SysLogCreate, + Permission::SysLogUpdate, + Permission::SysLogDestroy, + ], + ObjectType::MailingList => [ + Permission::SysMailingListCreate, + Permission::SysMailingListUpdate, + Permission::SysMailingListDestroy, + ], + ObjectType::MaskedEmail => [ + Permission::SysMaskedEmailCreate, + Permission::SysMaskedEmailUpdate, + Permission::SysMaskedEmailDestroy, + ], + ObjectType::MemoryLookupKey => [ + Permission::SysMemoryLookupKeyCreate, + Permission::SysMemoryLookupKeyUpdate, + Permission::SysMemoryLookupKeyDestroy, + ], + ObjectType::MemoryLookupKeyValue => [ + Permission::SysMemoryLookupKeyValueCreate, + Permission::SysMemoryLookupKeyValueUpdate, + Permission::SysMemoryLookupKeyValueDestroy, + ], + ObjectType::Metric => [ + Permission::SysMetricCreate, + Permission::SysMetricUpdate, + Permission::SysMetricDestroy, + ], + ObjectType::Metrics => [ + Permission::SysMetricsUpdate, + Permission::SysMetricsUpdate, + Permission::SysMetricsUpdate, + ], + ObjectType::MetricsStore => [ + Permission::SysMetricsStoreUpdate, + Permission::SysMetricsStoreUpdate, + Permission::SysMetricsStoreUpdate, + ], + ObjectType::MtaConnectionStrategy => [ + Permission::SysMtaConnectionStrategyCreate, + Permission::SysMtaConnectionStrategyUpdate, + Permission::SysMtaConnectionStrategyDestroy, + ], + ObjectType::MtaDeliverySchedule => [ + Permission::SysMtaDeliveryScheduleCreate, + Permission::SysMtaDeliveryScheduleUpdate, + Permission::SysMtaDeliveryScheduleDestroy, + ], + ObjectType::MtaExtensions => [ + Permission::SysMtaExtensionsUpdate, + Permission::SysMtaExtensionsUpdate, + Permission::SysMtaExtensionsUpdate, + ], + ObjectType::MtaHook => [ + Permission::SysMtaHookCreate, + Permission::SysMtaHookUpdate, + Permission::SysMtaHookDestroy, + ], + ObjectType::MtaInboundSession => [ + Permission::SysMtaInboundSessionUpdate, + Permission::SysMtaInboundSessionUpdate, + Permission::SysMtaInboundSessionUpdate, + ], + ObjectType::MtaInboundThrottle => [ + Permission::SysMtaInboundThrottleCreate, + Permission::SysMtaInboundThrottleUpdate, + Permission::SysMtaInboundThrottleDestroy, + ], + ObjectType::MtaMilter => [ + Permission::SysMtaMilterCreate, + Permission::SysMtaMilterUpdate, + Permission::SysMtaMilterDestroy, + ], + ObjectType::MtaOutboundStrategy => [ + Permission::SysMtaOutboundStrategyUpdate, + Permission::SysMtaOutboundStrategyUpdate, + Permission::SysMtaOutboundStrategyUpdate, + ], + ObjectType::MtaOutboundThrottle => [ + Permission::SysMtaOutboundThrottleCreate, + Permission::SysMtaOutboundThrottleUpdate, + Permission::SysMtaOutboundThrottleDestroy, + ], + ObjectType::MtaQueueQuota => [ + Permission::SysMtaQueueQuotaCreate, + Permission::SysMtaQueueQuotaUpdate, + Permission::SysMtaQueueQuotaDestroy, + ], + ObjectType::MtaRoute => [ + Permission::SysMtaRouteCreate, + Permission::SysMtaRouteUpdate, + Permission::SysMtaRouteDestroy, + ], + ObjectType::MtaStageAuth => [ + Permission::SysMtaStageAuthUpdate, + Permission::SysMtaStageAuthUpdate, + Permission::SysMtaStageAuthUpdate, + ], + ObjectType::MtaStageConnect => [ + Permission::SysMtaStageConnectUpdate, + Permission::SysMtaStageConnectUpdate, + Permission::SysMtaStageConnectUpdate, + ], + ObjectType::MtaStageData => [ + Permission::SysMtaStageDataUpdate, + Permission::SysMtaStageDataUpdate, + Permission::SysMtaStageDataUpdate, + ], + ObjectType::MtaStageEhlo => [ + Permission::SysMtaStageEhloUpdate, + Permission::SysMtaStageEhloUpdate, + Permission::SysMtaStageEhloUpdate, + ], + ObjectType::MtaStageMail => [ + Permission::SysMtaStageMailUpdate, + Permission::SysMtaStageMailUpdate, + Permission::SysMtaStageMailUpdate, + ], + ObjectType::MtaStageRcpt => [ + Permission::SysMtaStageRcptUpdate, + Permission::SysMtaStageRcptUpdate, + Permission::SysMtaStageRcptUpdate, + ], + ObjectType::MtaSts => [ + Permission::SysMtaStsUpdate, + Permission::SysMtaStsUpdate, + Permission::SysMtaStsUpdate, + ], + ObjectType::MtaTlsStrategy => [ + Permission::SysMtaTlsStrategyCreate, + Permission::SysMtaTlsStrategyUpdate, + Permission::SysMtaTlsStrategyDestroy, + ], + ObjectType::MtaVirtualQueue => [ + Permission::SysMtaVirtualQueueCreate, + Permission::SysMtaVirtualQueueUpdate, + Permission::SysMtaVirtualQueueDestroy, + ], + ObjectType::NetworkListener => [ + Permission::SysNetworkListenerCreate, + Permission::SysNetworkListenerUpdate, + Permission::SysNetworkListenerDestroy, + ], + ObjectType::OAuthClient => [ + Permission::SysOAuthClientCreate, + Permission::SysOAuthClientUpdate, + Permission::SysOAuthClientDestroy, + ], + ObjectType::OidcProvider => [ + Permission::SysOidcProviderUpdate, + Permission::SysOidcProviderUpdate, + Permission::SysOidcProviderUpdate, + ], + ObjectType::PublicKey => [ + Permission::SysPublicKeyCreate, + Permission::SysPublicKeyUpdate, + Permission::SysPublicKeyDestroy, + ], + ObjectType::QueuedMessage => [ + Permission::SysQueuedMessageCreate, + Permission::SysQueuedMessageUpdate, + Permission::SysQueuedMessageDestroy, + ], + ObjectType::ReportSettings => [ + Permission::SysReportSettingsUpdate, + Permission::SysReportSettingsUpdate, + Permission::SysReportSettingsUpdate, + ], + ObjectType::Role => [ + Permission::SysRoleCreate, + Permission::SysRoleUpdate, + Permission::SysRoleDestroy, + ], + ObjectType::Search => [ + Permission::SysSearchUpdate, + Permission::SysSearchUpdate, + Permission::SysSearchUpdate, + ], + ObjectType::SearchStore => [ + Permission::SysSearchStoreUpdate, + Permission::SysSearchStoreUpdate, + Permission::SysSearchStoreUpdate, + ], + ObjectType::Security => [ + Permission::SysSecurityUpdate, + Permission::SysSecurityUpdate, + Permission::SysSecurityUpdate, + ], + ObjectType::SenderAuth => [ + Permission::SysSenderAuthUpdate, + Permission::SysSenderAuthUpdate, + Permission::SysSenderAuthUpdate, + ], + ObjectType::Sharing => [ + Permission::SysSharingUpdate, + Permission::SysSharingUpdate, + Permission::SysSharingUpdate, + ], + ObjectType::SieveSystemInterpreter => [ + Permission::SysSieveSystemInterpreterUpdate, + Permission::SysSieveSystemInterpreterUpdate, + Permission::SysSieveSystemInterpreterUpdate, + ], + ObjectType::SieveSystemScript => [ + Permission::SysSieveSystemScriptCreate, + Permission::SysSieveSystemScriptUpdate, + Permission::SysSieveSystemScriptDestroy, + ], + ObjectType::SieveUserInterpreter => [ + Permission::SysSieveUserInterpreterUpdate, + Permission::SysSieveUserInterpreterUpdate, + Permission::SysSieveUserInterpreterUpdate, + ], + ObjectType::SieveUserScript => [ + Permission::SysSieveUserScriptCreate, + Permission::SysSieveUserScriptUpdate, + Permission::SysSieveUserScriptDestroy, + ], + ObjectType::SpamClassifier => [ + Permission::SysSpamClassifierUpdate, + Permission::SysSpamClassifierUpdate, + Permission::SysSpamClassifierUpdate, + ], + ObjectType::SpamDnsblServer => [ + Permission::SysSpamDnsblServerCreate, + Permission::SysSpamDnsblServerUpdate, + Permission::SysSpamDnsblServerDestroy, + ], + ObjectType::SpamDnsblSettings => [ + Permission::SysSpamDnsblSettingsUpdate, + Permission::SysSpamDnsblSettingsUpdate, + Permission::SysSpamDnsblSettingsUpdate, + ], + ObjectType::SpamFileExtension => [ + Permission::SysSpamFileExtensionCreate, + Permission::SysSpamFileExtensionUpdate, + Permission::SysSpamFileExtensionDestroy, + ], + ObjectType::SpamLlm => [ + Permission::SysSpamLlmUpdate, + Permission::SysSpamLlmUpdate, + Permission::SysSpamLlmUpdate, + ], + ObjectType::SpamPyzor => [ + Permission::SysSpamPyzorUpdate, + Permission::SysSpamPyzorUpdate, + Permission::SysSpamPyzorUpdate, + ], + ObjectType::SpamRule => [ + Permission::SysSpamRuleCreate, + Permission::SysSpamRuleUpdate, + Permission::SysSpamRuleDestroy, + ], + ObjectType::SpamSettings => [ + Permission::SysSpamSettingsUpdate, + Permission::SysSpamSettingsUpdate, + Permission::SysSpamSettingsUpdate, + ], + ObjectType::SpamTag => [ + Permission::SysSpamTagCreate, + Permission::SysSpamTagUpdate, + Permission::SysSpamTagDestroy, + ], + ObjectType::SpamTrainingSample => [ + Permission::SysSpamTrainingSampleCreate, + Permission::SysSpamTrainingSampleUpdate, + Permission::SysSpamTrainingSampleDestroy, + ], + ObjectType::SpfReportSettings => [ + Permission::SysSpfReportSettingsUpdate, + Permission::SysSpfReportSettingsUpdate, + Permission::SysSpfReportSettingsUpdate, + ], + ObjectType::StoreLookup => [ + Permission::SysStoreLookupCreate, + Permission::SysStoreLookupUpdate, + Permission::SysStoreLookupDestroy, + ], + ObjectType::SystemSettings => [ + Permission::SysSystemSettingsUpdate, + Permission::SysSystemSettingsUpdate, + Permission::SysSystemSettingsUpdate, + ], + ObjectType::Task => [ + Permission::SysTaskCreate, + Permission::SysTaskUpdate, + Permission::SysTaskDestroy, + ], + ObjectType::TaskManager => [ + Permission::SysTaskManagerUpdate, + Permission::SysTaskManagerUpdate, + Permission::SysTaskManagerUpdate, + ], + ObjectType::Tenant => [ + Permission::SysTenantCreate, + Permission::SysTenantUpdate, + Permission::SysTenantDestroy, + ], + ObjectType::TlsExternalReport => [ + Permission::SysTlsExternalReportCreate, + Permission::SysTlsExternalReportUpdate, + Permission::SysTlsExternalReportDestroy, + ], + ObjectType::TlsInternalReport => [ + Permission::SysTlsInternalReportCreate, + Permission::SysTlsInternalReportUpdate, + Permission::SysTlsInternalReportDestroy, + ], + ObjectType::TlsReportSettings => [ + Permission::SysTlsReportSettingsUpdate, + Permission::SysTlsReportSettingsUpdate, + Permission::SysTlsReportSettingsUpdate, + ], + ObjectType::Trace => [ + Permission::SysTraceCreate, + Permission::SysTraceUpdate, + Permission::SysTraceDestroy, + ], + ObjectType::Tracer => [ + Permission::SysTracerCreate, + Permission::SysTracerUpdate, + Permission::SysTracerDestroy, + ], + ObjectType::TracingStore => [ + Permission::SysTracingStoreUpdate, + Permission::SysTracingStoreUpdate, + Permission::SysTracingStoreUpdate, + ], + ObjectType::WebDav => [ + Permission::SysWebDavUpdate, + Permission::SysWebDavUpdate, + Permission::SysWebDavUpdate, + ], + ObjectType::WebHook => [ + Permission::SysWebHookCreate, + Permission::SysWebHookUpdate, + Permission::SysWebHookDestroy, + ], + } + } +} + +impl ObjectInner { + pub fn member_tenant_id(&self) -> Option { + match self { + ObjectInner::Account(Account::User(obj)) => obj.member_tenant_id, + ObjectInner::Account(Account::Group(obj)) => obj.member_tenant_id, + ObjectInner::AcmeProvider(obj) => obj.member_tenant_id, + ObjectInner::ArfExternalReport(obj) => obj.member_tenant_id, + ObjectInner::Directory(Directory::Ldap(obj)) => obj.member_tenant_id, + ObjectInner::Directory(Directory::Sql(obj)) => obj.member_tenant_id, + ObjectInner::Directory(Directory::Oidc(obj)) => obj.member_tenant_id, + ObjectInner::DkimSignature(DkimSignature::Dkim1Ed25519Sha256(obj)) => { + obj.member_tenant_id + } + ObjectInner::DkimSignature(DkimSignature::Dkim1RsaSha256(obj)) => obj.member_tenant_id, + ObjectInner::DmarcExternalReport(obj) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Tsig(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Sig0(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Cloudflare(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::DigitalOcean(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::DeSEC(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Ovh(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Bunny(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Porkbun(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Dnsimple(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Spaceship(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::Route53(obj)) => obj.member_tenant_id, + ObjectInner::DnsServer(DnsServer::GoogleCloudDns(obj)) => obj.member_tenant_id, + ObjectInner::Domain(obj) => obj.member_tenant_id, + ObjectInner::MailingList(obj) => obj.member_tenant_id, + ObjectInner::OAuthClient(obj) => obj.member_tenant_id, + ObjectInner::Role(obj) => obj.member_tenant_id, + ObjectInner::TlsExternalReport(obj) => obj.member_tenant_id, + _ => None, + } + } + + pub fn set_member_tenant_id(&mut self, id: Id) { + match self { + ObjectInner::Account(Account::User(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::Account(Account::Group(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::AcmeProvider(obj) => obj.member_tenant_id = Some(id), + ObjectInner::ArfExternalReport(obj) => obj.member_tenant_id = Some(id), + ObjectInner::Directory(Directory::Ldap(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::Directory(Directory::Sql(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::Directory(Directory::Oidc(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DkimSignature(DkimSignature::Dkim1Ed25519Sha256(obj)) => { + obj.member_tenant_id = Some(id) + } + ObjectInner::DkimSignature(DkimSignature::Dkim1RsaSha256(obj)) => { + obj.member_tenant_id = Some(id) + } + ObjectInner::DmarcExternalReport(obj) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Tsig(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Sig0(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Cloudflare(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::DigitalOcean(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::DeSEC(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Ovh(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Bunny(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Porkbun(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Dnsimple(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Spaceship(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::Route53(obj)) => obj.member_tenant_id = Some(id), + ObjectInner::DnsServer(DnsServer::GoogleCloudDns(obj)) => { + obj.member_tenant_id = Some(id) + } + ObjectInner::Domain(obj) => obj.member_tenant_id = Some(id), + ObjectInner::MailingList(obj) => obj.member_tenant_id = Some(id), + ObjectInner::OAuthClient(obj) => obj.member_tenant_id = Some(id), + ObjectInner::Role(obj) => obj.member_tenant_id = Some(id), + ObjectInner::TlsExternalReport(obj) => obj.member_tenant_id = Some(id), + _ => {} + } + } + + pub fn account_id(&self) -> Option { + match self { + ObjectInner::ArchivedItem(ArchivedItem::Email(obj)) => Some(obj.account_id), + ObjectInner::ArchivedItem(ArchivedItem::FileNode(obj)) => Some(obj.account_id), + ObjectInner::ArchivedItem(ArchivedItem::CalendarEvent(obj)) => Some(obj.account_id), + ObjectInner::ArchivedItem(ArchivedItem::ContactCard(obj)) => Some(obj.account_id), + ObjectInner::ArchivedItem(ArchivedItem::SieveScript(obj)) => Some(obj.account_id), + ObjectInner::MaskedEmail(obj) => Some(obj.account_id), + ObjectInner::PublicKey(obj) => Some(obj.account_id), + ObjectInner::SpamTrainingSample(obj) => obj.account_id, + ObjectInner::Task(Task::IndexDocument(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::UnindexDocument(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::CalendarAlarmEmail(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::CalendarAlarmNotification(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::CalendarItipMessage(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::MergeThreads(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::RestoreArchivedItem(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::DestroyAccount(obj)) => Some(obj.account_id), + ObjectInner::Task(Task::AccountMaintenance(obj)) => Some(obj.account_id), + _ => None, + } + } + + pub fn set_account_id(&mut self, id: Id) { + match self { + ObjectInner::ArchivedItem(ArchivedItem::Email(obj)) => obj.account_id = id, + ObjectInner::ArchivedItem(ArchivedItem::FileNode(obj)) => obj.account_id = id, + ObjectInner::ArchivedItem(ArchivedItem::CalendarEvent(obj)) => obj.account_id = id, + ObjectInner::ArchivedItem(ArchivedItem::ContactCard(obj)) => obj.account_id = id, + ObjectInner::ArchivedItem(ArchivedItem::SieveScript(obj)) => obj.account_id = id, + ObjectInner::MaskedEmail(obj) => obj.account_id = id, + ObjectInner::PublicKey(obj) => obj.account_id = id, + ObjectInner::SpamTrainingSample(obj) => obj.account_id = Some(id), + ObjectInner::Task(Task::IndexDocument(obj)) => obj.account_id = id, + ObjectInner::Task(Task::UnindexDocument(obj)) => obj.account_id = id, + ObjectInner::Task(Task::CalendarAlarmEmail(obj)) => obj.account_id = id, + ObjectInner::Task(Task::CalendarAlarmNotification(obj)) => obj.account_id = id, + ObjectInner::Task(Task::CalendarItipMessage(obj)) => obj.account_id = id, + ObjectInner::Task(Task::MergeThreads(obj)) => obj.account_id = id, + ObjectInner::Task(Task::RestoreArchivedItem(obj)) => obj.account_id = id, + ObjectInner::Task(Task::DestroyAccount(obj)) => obj.account_id = id, + ObjectInner::Task(Task::AccountMaintenance(obj)) => obj.account_id = id, + _ => {} + } + } + + pub fn to_pickled_vec(&self) -> Vec { + match &self { + ObjectInner::Account(obj) => obj.to_pickled_vec(), + ObjectInner::AccountPassword(obj) => obj.to_pickled_vec(), + ObjectInner::AccountSettings(obj) => obj.to_pickled_vec(), + ObjectInner::AcmeProvider(obj) => obj.to_pickled_vec(), + ObjectInner::Action(obj) => obj.to_pickled_vec(), + ObjectInner::AddressBook(obj) => obj.to_pickled_vec(), + ObjectInner::AiModel(obj) => obj.to_pickled_vec(), + ObjectInner::Alert(obj) => obj.to_pickled_vec(), + ObjectInner::AllowedIp(obj) => obj.to_pickled_vec(), + ObjectInner::ApiKey(obj) => obj.to_pickled_vec(), + ObjectInner::AppPassword(obj) => obj.to_pickled_vec(), + ObjectInner::Application(obj) => obj.to_pickled_vec(), + ObjectInner::ArchivedItem(obj) => obj.to_pickled_vec(), + ObjectInner::ArfExternalReport(obj) => obj.to_pickled_vec(), + ObjectInner::Asn(obj) => obj.to_pickled_vec(), + ObjectInner::Authentication(obj) => obj.to_pickled_vec(), + ObjectInner::BlobStore(obj) => obj.to_pickled_vec(), + ObjectInner::BlockedIp(obj) => obj.to_pickled_vec(), + ObjectInner::Bootstrap(obj) => obj.to_pickled_vec(), + ObjectInner::Cache(obj) => obj.to_pickled_vec(), + ObjectInner::Calendar(obj) => obj.to_pickled_vec(), + ObjectInner::CalendarAlarm(obj) => obj.to_pickled_vec(), + ObjectInner::CalendarScheduling(obj) => obj.to_pickled_vec(), + ObjectInner::Certificate(obj) => obj.to_pickled_vec(), + ObjectInner::ClusterNode(obj) => obj.to_pickled_vec(), + ObjectInner::ClusterRole(obj) => obj.to_pickled_vec(), + ObjectInner::Coordinator(obj) => obj.to_pickled_vec(), + ObjectInner::DataRetention(obj) => obj.to_pickled_vec(), + ObjectInner::DataStore(obj) => obj.to_pickled_vec(), + ObjectInner::Directory(obj) => obj.to_pickled_vec(), + ObjectInner::DkimReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::DkimSignature(obj) => obj.to_pickled_vec(), + ObjectInner::DmarcExternalReport(obj) => obj.to_pickled_vec(), + ObjectInner::DmarcInternalReport(obj) => obj.to_pickled_vec(), + ObjectInner::DmarcReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::DnsResolver(obj) => obj.to_pickled_vec(), + ObjectInner::DnsServer(obj) => obj.to_pickled_vec(), + ObjectInner::Domain(obj) => obj.to_pickled_vec(), + ObjectInner::DsnReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::Email(obj) => obj.to_pickled_vec(), + ObjectInner::Enterprise(obj) => obj.to_pickled_vec(), + ObjectInner::EventTracingLevel(obj) => obj.to_pickled_vec(), + ObjectInner::FileStorage(obj) => obj.to_pickled_vec(), + ObjectInner::Http(obj) => obj.to_pickled_vec(), + ObjectInner::HttpForm(obj) => obj.to_pickled_vec(), + ObjectInner::HttpLookup(obj) => obj.to_pickled_vec(), + ObjectInner::Imap(obj) => obj.to_pickled_vec(), + ObjectInner::InMemoryStore(obj) => obj.to_pickled_vec(), + ObjectInner::Jmap(obj) => obj.to_pickled_vec(), + ObjectInner::Log(obj) => obj.to_pickled_vec(), + ObjectInner::MailingList(obj) => obj.to_pickled_vec(), + ObjectInner::MaskedEmail(obj) => obj.to_pickled_vec(), + ObjectInner::MemoryLookupKey(obj) => obj.to_pickled_vec(), + ObjectInner::MemoryLookupKeyValue(obj) => obj.to_pickled_vec(), + ObjectInner::Metric(obj) => obj.to_pickled_vec(), + ObjectInner::Metrics(obj) => obj.to_pickled_vec(), + ObjectInner::MetricsStore(obj) => obj.to_pickled_vec(), + ObjectInner::MtaConnectionStrategy(obj) => obj.to_pickled_vec(), + ObjectInner::MtaDeliverySchedule(obj) => obj.to_pickled_vec(), + ObjectInner::MtaExtensions(obj) => obj.to_pickled_vec(), + ObjectInner::MtaHook(obj) => obj.to_pickled_vec(), + ObjectInner::MtaInboundSession(obj) => obj.to_pickled_vec(), + ObjectInner::MtaInboundThrottle(obj) => obj.to_pickled_vec(), + ObjectInner::MtaMilter(obj) => obj.to_pickled_vec(), + ObjectInner::MtaOutboundStrategy(obj) => obj.to_pickled_vec(), + ObjectInner::MtaOutboundThrottle(obj) => obj.to_pickled_vec(), + ObjectInner::MtaQueueQuota(obj) => obj.to_pickled_vec(), + ObjectInner::MtaRoute(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageAuth(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageConnect(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageData(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageEhlo(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageMail(obj) => obj.to_pickled_vec(), + ObjectInner::MtaStageRcpt(obj) => obj.to_pickled_vec(), + ObjectInner::MtaSts(obj) => obj.to_pickled_vec(), + ObjectInner::MtaTlsStrategy(obj) => obj.to_pickled_vec(), + ObjectInner::MtaVirtualQueue(obj) => obj.to_pickled_vec(), + ObjectInner::NetworkListener(obj) => obj.to_pickled_vec(), + ObjectInner::OAuthClient(obj) => obj.to_pickled_vec(), + ObjectInner::OidcProvider(obj) => obj.to_pickled_vec(), + ObjectInner::PublicKey(obj) => obj.to_pickled_vec(), + ObjectInner::QueuedMessage(obj) => obj.to_pickled_vec(), + ObjectInner::ReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::Role(obj) => obj.to_pickled_vec(), + ObjectInner::Search(obj) => obj.to_pickled_vec(), + ObjectInner::SearchStore(obj) => obj.to_pickled_vec(), + ObjectInner::Security(obj) => obj.to_pickled_vec(), + ObjectInner::SenderAuth(obj) => obj.to_pickled_vec(), + ObjectInner::Sharing(obj) => obj.to_pickled_vec(), + ObjectInner::SieveSystemInterpreter(obj) => obj.to_pickled_vec(), + ObjectInner::SieveSystemScript(obj) => obj.to_pickled_vec(), + ObjectInner::SieveUserInterpreter(obj) => obj.to_pickled_vec(), + ObjectInner::SieveUserScript(obj) => obj.to_pickled_vec(), + ObjectInner::SpamClassifier(obj) => obj.to_pickled_vec(), + ObjectInner::SpamDnsblServer(obj) => obj.to_pickled_vec(), + ObjectInner::SpamDnsblSettings(obj) => obj.to_pickled_vec(), + ObjectInner::SpamFileExtension(obj) => obj.to_pickled_vec(), + ObjectInner::SpamLlm(obj) => obj.to_pickled_vec(), + ObjectInner::SpamPyzor(obj) => obj.to_pickled_vec(), + ObjectInner::SpamRule(obj) => obj.to_pickled_vec(), + ObjectInner::SpamSettings(obj) => obj.to_pickled_vec(), + ObjectInner::SpamTag(obj) => obj.to_pickled_vec(), + ObjectInner::SpamTrainingSample(obj) => obj.to_pickled_vec(), + ObjectInner::SpfReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::StoreLookup(obj) => obj.to_pickled_vec(), + ObjectInner::SystemSettings(obj) => obj.to_pickled_vec(), + ObjectInner::Task(obj) => obj.to_pickled_vec(), + ObjectInner::TaskManager(obj) => obj.to_pickled_vec(), + ObjectInner::Tenant(obj) => obj.to_pickled_vec(), + ObjectInner::TlsExternalReport(obj) => obj.to_pickled_vec(), + ObjectInner::TlsInternalReport(obj) => obj.to_pickled_vec(), + ObjectInner::TlsReportSettings(obj) => obj.to_pickled_vec(), + ObjectInner::Trace(obj) => obj.to_pickled_vec(), + ObjectInner::Tracer(obj) => obj.to_pickled_vec(), + ObjectInner::TracingStore(obj) => obj.to_pickled_vec(), + ObjectInner::WebDav(obj) => obj.to_pickled_vec(), + ObjectInner::WebHook(obj) => obj.to_pickled_vec(), + } + } + + pub fn unpickle( + object: ObjectType, + stream: &mut crate::pickle::PickledStream<'_>, + ) -> Option { + match object { + ObjectType::Account => Pickle::unpickle(stream).map(ObjectInner::Account), + ObjectType::AccountPassword => { + Pickle::unpickle(stream).map(ObjectInner::AccountPassword) + } + ObjectType::AccountSettings => { + Pickle::unpickle(stream).map(ObjectInner::AccountSettings) + } + ObjectType::AcmeProvider => Pickle::unpickle(stream).map(ObjectInner::AcmeProvider), + ObjectType::Action => Pickle::unpickle(stream).map(ObjectInner::Action), + ObjectType::AddressBook => Pickle::unpickle(stream).map(ObjectInner::AddressBook), + ObjectType::AiModel => Pickle::unpickle(stream).map(ObjectInner::AiModel), + ObjectType::Alert => Pickle::unpickle(stream).map(ObjectInner::Alert), + ObjectType::AllowedIp => Pickle::unpickle(stream).map(ObjectInner::AllowedIp), + ObjectType::ApiKey => Pickle::unpickle(stream).map(ObjectInner::ApiKey), + ObjectType::AppPassword => Pickle::unpickle(stream).map(ObjectInner::AppPassword), + ObjectType::Application => Pickle::unpickle(stream).map(ObjectInner::Application), + ObjectType::ArchivedItem => Pickle::unpickle(stream).map(ObjectInner::ArchivedItem), + ObjectType::ArfExternalReport => { + Pickle::unpickle(stream).map(ObjectInner::ArfExternalReport) + } + ObjectType::Asn => Pickle::unpickle(stream).map(ObjectInner::Asn), + ObjectType::Authentication => Pickle::unpickle(stream).map(ObjectInner::Authentication), + ObjectType::BlobStore => Pickle::unpickle(stream).map(ObjectInner::BlobStore), + ObjectType::BlockedIp => Pickle::unpickle(stream).map(ObjectInner::BlockedIp), + ObjectType::Bootstrap => Pickle::unpickle(stream).map(ObjectInner::Bootstrap), + ObjectType::Cache => Pickle::unpickle(stream).map(ObjectInner::Cache), + ObjectType::Calendar => Pickle::unpickle(stream).map(ObjectInner::Calendar), + ObjectType::CalendarAlarm => Pickle::unpickle(stream).map(ObjectInner::CalendarAlarm), + ObjectType::CalendarScheduling => { + Pickle::unpickle(stream).map(ObjectInner::CalendarScheduling) + } + ObjectType::Certificate => Pickle::unpickle(stream).map(ObjectInner::Certificate), + ObjectType::ClusterNode => Pickle::unpickle(stream).map(ObjectInner::ClusterNode), + ObjectType::ClusterRole => Pickle::unpickle(stream).map(ObjectInner::ClusterRole), + ObjectType::Coordinator => Pickle::unpickle(stream).map(ObjectInner::Coordinator), + ObjectType::DataRetention => Pickle::unpickle(stream).map(ObjectInner::DataRetention), + ObjectType::DataStore => Pickle::unpickle(stream).map(ObjectInner::DataStore), + ObjectType::Directory => Pickle::unpickle(stream).map(ObjectInner::Directory), + ObjectType::DkimReportSettings => { + Pickle::unpickle(stream).map(ObjectInner::DkimReportSettings) + } + ObjectType::DkimSignature => Pickle::unpickle(stream).map(ObjectInner::DkimSignature), + ObjectType::DmarcExternalReport => { + Pickle::unpickle(stream).map(ObjectInner::DmarcExternalReport) + } + ObjectType::DmarcInternalReport => { + Pickle::unpickle(stream).map(ObjectInner::DmarcInternalReport) + } + ObjectType::DmarcReportSettings => { + Pickle::unpickle(stream).map(ObjectInner::DmarcReportSettings) + } + ObjectType::DnsResolver => Pickle::unpickle(stream).map(ObjectInner::DnsResolver), + ObjectType::DnsServer => Pickle::unpickle(stream).map(ObjectInner::DnsServer), + ObjectType::Domain => Pickle::unpickle(stream).map(ObjectInner::Domain), + ObjectType::DsnReportSettings => { + Pickle::unpickle(stream).map(ObjectInner::DsnReportSettings) + } + ObjectType::Email => Pickle::unpickle(stream).map(ObjectInner::Email), + ObjectType::Enterprise => Pickle::unpickle(stream).map(ObjectInner::Enterprise), + ObjectType::EventTracingLevel => { + Pickle::unpickle(stream).map(ObjectInner::EventTracingLevel) + } + ObjectType::FileStorage => Pickle::unpickle(stream).map(ObjectInner::FileStorage), + ObjectType::Http => Pickle::unpickle(stream).map(ObjectInner::Http), + ObjectType::HttpForm => Pickle::unpickle(stream).map(ObjectInner::HttpForm), + ObjectType::HttpLookup => Pickle::unpickle(stream).map(ObjectInner::HttpLookup), + ObjectType::Imap => Pickle::unpickle(stream).map(ObjectInner::Imap), + ObjectType::InMemoryStore => Pickle::unpickle(stream).map(ObjectInner::InMemoryStore), + ObjectType::Jmap => Pickle::unpickle(stream).map(ObjectInner::Jmap), + ObjectType::Log => Pickle::unpickle(stream).map(ObjectInner::Log), + ObjectType::MailingList => Pickle::unpickle(stream).map(ObjectInner::MailingList), + ObjectType::MaskedEmail => Pickle::unpickle(stream).map(ObjectInner::MaskedEmail), + ObjectType::MemoryLookupKey => { + Pickle::unpickle(stream).map(ObjectInner::MemoryLookupKey) + } + ObjectType::MemoryLookupKeyValue => { + Pickle::unpickle(stream).map(ObjectInner::MemoryLookupKeyValue) + } + ObjectType::Metric => Pickle::unpickle(stream).map(ObjectInner::Metric), + ObjectType::Metrics => Pickle::unpickle(stream).map(ObjectInner::Metrics), + ObjectType::MetricsStore => Pickle::unpickle(stream).map(ObjectInner::MetricsStore), + ObjectType::MtaConnectionStrategy => { + Pickle::unpickle(stream).map(ObjectInner::MtaConnectionStrategy) + } + ObjectType::MtaDeliverySchedule => { + Pickle::unpickle(stream).map(ObjectInner::MtaDeliverySchedule) + } + ObjectType::MtaExtensions => Pickle::unpickle(stream).map(ObjectInner::MtaExtensions), + ObjectType::MtaHook => Pickle::unpickle(stream).map(ObjectInner::MtaHook), + ObjectType::MtaInboundSession => { + Pickle::unpickle(stream).map(ObjectInner::MtaInboundSession) + } + ObjectType::MtaInboundThrottle => { + Pickle::unpickle(stream).map(ObjectInner::MtaInboundThrottle) + } + ObjectType::MtaMilter => Pickle::unpickle(stream).map(ObjectInner::MtaMilter), + ObjectType::MtaOutboundStrategy => { + Pickle::unpickle(stream).map(ObjectInner::MtaOutboundStrategy) + } + ObjectType::MtaOutboundThrottle => { + Pickle::unpickle(stream).map(ObjectInner::MtaOutboundThrottle) + } + ObjectType::MtaQueueQuota => Pickle::unpickle(stream).map(ObjectInner::MtaQueueQuota), + ObjectType::MtaRoute => Pickle::unpickle(stream).map(ObjectInner::MtaRoute), + ObjectType::MtaStageAuth => Pickle::unpickle(stream).map(ObjectInner::MtaStageAuth), + ObjectType::MtaStageConnect => { + Pickle::unpickle(stream).map(ObjectInner::MtaStageConnect) + } + ObjectType::MtaStageData => Pickle::unpickle(stream).map(ObjectInner::MtaStageData), + ObjectType::MtaStageEhlo => Pickle::unpickle(stream).map(ObjectInner::MtaStageEhlo), + ObjectType::MtaStageMail => Pickle::unpickle(stream).map(ObjectInner::MtaStageMail), + ObjectType::MtaStageRcpt => Pickle::unpickle(stream).map(ObjectInner::MtaStageRcpt), + ObjectType::MtaSts => Pickle::unpickle(stream).map(ObjectInner::MtaSts), + ObjectType::MtaTlsStrategy => Pickle::unpickle(stream).map(ObjectInner::MtaTlsStrategy), + ObjectType::MtaVirtualQueue => { + Pickle::unpickle(stream).map(ObjectInner::MtaVirtualQueue) + } + ObjectType::NetworkListener => { + Pickle::unpickle(stream).map(ObjectInner::NetworkListener) + } + ObjectType::OAuthClient => Pickle::unpickle(stream).map(ObjectInner::OAuthClient), + ObjectType::OidcProvider => Pickle::unpickle(stream).map(ObjectInner::OidcProvider), + ObjectType::PublicKey => Pickle::unpickle(stream).map(ObjectInner::PublicKey), + ObjectType::QueuedMessage => Pickle::unpickle(stream).map(ObjectInner::QueuedMessage), + ObjectType::ReportSettings => Pickle::unpickle(stream).map(ObjectInner::ReportSettings), + ObjectType::Role => Pickle::unpickle(stream).map(ObjectInner::Role), + ObjectType::Search => Pickle::unpickle(stream).map(ObjectInner::Search), + ObjectType::SearchStore => Pickle::unpickle(stream).map(ObjectInner::SearchStore), + ObjectType::Security => Pickle::unpickle(stream).map(ObjectInner::Security), + ObjectType::SenderAuth => Pickle::unpickle(stream).map(ObjectInner::SenderAuth), + ObjectType::Sharing => Pickle::unpickle(stream).map(ObjectInner::Sharing), + ObjectType::SieveSystemInterpreter => { + Pickle::unpickle(stream).map(ObjectInner::SieveSystemInterpreter) + } + ObjectType::SieveSystemScript => { + Pickle::unpickle(stream).map(ObjectInner::SieveSystemScript) + } + ObjectType::SieveUserInterpreter => { + Pickle::unpickle(stream).map(ObjectInner::SieveUserInterpreter) + } + ObjectType::SieveUserScript => { + Pickle::unpickle(stream).map(ObjectInner::SieveUserScript) + } + ObjectType::SpamClassifier => Pickle::unpickle(stream).map(ObjectInner::SpamClassifier), + ObjectType::SpamDnsblServer => { + Pickle::unpickle(stream).map(ObjectInner::SpamDnsblServer) + } + ObjectType::SpamDnsblSettings => { + Pickle::unpickle(stream).map(ObjectInner::SpamDnsblSettings) + } + ObjectType::SpamFileExtension => { + Pickle::unpickle(stream).map(ObjectInner::SpamFileExtension) + } + ObjectType::SpamLlm => Pickle::unpickle(stream).map(ObjectInner::SpamLlm), + ObjectType::SpamPyzor => Pickle::unpickle(stream).map(ObjectInner::SpamPyzor), + ObjectType::SpamRule => Pickle::unpickle(stream).map(ObjectInner::SpamRule), + ObjectType::SpamSettings => Pickle::unpickle(stream).map(ObjectInner::SpamSettings), + ObjectType::SpamTag => Pickle::unpickle(stream).map(ObjectInner::SpamTag), + ObjectType::SpamTrainingSample => { + Pickle::unpickle(stream).map(ObjectInner::SpamTrainingSample) + } + ObjectType::SpfReportSettings => { + Pickle::unpickle(stream).map(ObjectInner::SpfReportSettings) + } + ObjectType::StoreLookup => Pickle::unpickle(stream).map(ObjectInner::StoreLookup), + ObjectType::SystemSettings => Pickle::unpickle(stream).map(ObjectInner::SystemSettings), + ObjectType::Task => Pickle::unpickle(stream).map(ObjectInner::Task), + ObjectType::TaskManager => Pickle::unpickle(stream).map(ObjectInner::TaskManager), + ObjectType::Tenant => Pickle::unpickle(stream).map(ObjectInner::Tenant), + ObjectType::TlsExternalReport => { + Pickle::unpickle(stream).map(ObjectInner::TlsExternalReport) + } + ObjectType::TlsInternalReport => { + Pickle::unpickle(stream).map(ObjectInner::TlsInternalReport) + } + ObjectType::TlsReportSettings => { + Pickle::unpickle(stream).map(ObjectInner::TlsReportSettings) + } + ObjectType::Trace => Pickle::unpickle(stream).map(ObjectInner::Trace), + ObjectType::Tracer => Pickle::unpickle(stream).map(ObjectInner::Tracer), + ObjectType::TracingStore => Pickle::unpickle(stream).map(ObjectInner::TracingStore), + ObjectType::WebDav => Pickle::unpickle(stream).map(ObjectInner::WebDav), + ObjectType::WebHook => Pickle::unpickle(stream).map(ObjectInner::WebHook), + } + } + + pub fn deserialize<'de, D>(object: ObjectType, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + match object { + ObjectType::Account => Account::deserialize(deserializer).map(ObjectInner::Account), + ObjectType::AccountPassword => { + AccountPassword::deserialize(deserializer).map(ObjectInner::AccountPassword) + } + ObjectType::AccountSettings => { + AccountSettings::deserialize(deserializer).map(ObjectInner::AccountSettings) + } + ObjectType::AcmeProvider => { + AcmeProvider::deserialize(deserializer).map(ObjectInner::AcmeProvider) + } + ObjectType::Action => Action::deserialize(deserializer).map(ObjectInner::Action), + ObjectType::AddressBook => { + AddressBook::deserialize(deserializer).map(ObjectInner::AddressBook) + } + ObjectType::AiModel => AiModel::deserialize(deserializer).map(ObjectInner::AiModel), + ObjectType::Alert => Alert::deserialize(deserializer).map(ObjectInner::Alert), + ObjectType::AllowedIp => { + AllowedIp::deserialize(deserializer).map(ObjectInner::AllowedIp) + } + ObjectType::ApiKey => ApiKey::deserialize(deserializer).map(ObjectInner::ApiKey), + ObjectType::AppPassword => { + AppPassword::deserialize(deserializer).map(ObjectInner::AppPassword) + } + ObjectType::Application => { + Application::deserialize(deserializer).map(ObjectInner::Application) + } + ObjectType::ArchivedItem => { + ArchivedItem::deserialize(deserializer).map(ObjectInner::ArchivedItem) + } + ObjectType::ArfExternalReport => { + ArfExternalReport::deserialize(deserializer).map(ObjectInner::ArfExternalReport) + } + ObjectType::Asn => Asn::deserialize(deserializer).map(ObjectInner::Asn), + ObjectType::Authentication => { + Authentication::deserialize(deserializer).map(ObjectInner::Authentication) + } + ObjectType::BlobStore => { + BlobStore::deserialize(deserializer).map(ObjectInner::BlobStore) + } + ObjectType::BlockedIp => { + BlockedIp::deserialize(deserializer).map(ObjectInner::BlockedIp) + } + ObjectType::Bootstrap => { + Bootstrap::deserialize(deserializer).map(ObjectInner::Bootstrap) + } + ObjectType::Cache => Cache::deserialize(deserializer).map(ObjectInner::Cache), + ObjectType::Calendar => Calendar::deserialize(deserializer).map(ObjectInner::Calendar), + ObjectType::CalendarAlarm => { + CalendarAlarm::deserialize(deserializer).map(ObjectInner::CalendarAlarm) + } + ObjectType::CalendarScheduling => { + CalendarScheduling::deserialize(deserializer).map(ObjectInner::CalendarScheduling) + } + ObjectType::Certificate => { + Certificate::deserialize(deserializer).map(ObjectInner::Certificate) + } + ObjectType::ClusterNode => { + ClusterNode::deserialize(deserializer).map(ObjectInner::ClusterNode) + } + ObjectType::ClusterRole => { + ClusterRole::deserialize(deserializer).map(ObjectInner::ClusterRole) + } + ObjectType::Coordinator => { + Coordinator::deserialize(deserializer).map(ObjectInner::Coordinator) + } + ObjectType::DataRetention => { + DataRetention::deserialize(deserializer).map(ObjectInner::DataRetention) + } + ObjectType::DataStore => { + DataStore::deserialize(deserializer).map(ObjectInner::DataStore) + } + ObjectType::Directory => { + Directory::deserialize(deserializer).map(ObjectInner::Directory) + } + ObjectType::DkimReportSettings => { + DkimReportSettings::deserialize(deserializer).map(ObjectInner::DkimReportSettings) + } + ObjectType::DkimSignature => { + DkimSignature::deserialize(deserializer).map(ObjectInner::DkimSignature) + } + ObjectType::DmarcExternalReport => { + DmarcExternalReport::deserialize(deserializer).map(ObjectInner::DmarcExternalReport) + } + ObjectType::DmarcInternalReport => { + DmarcInternalReport::deserialize(deserializer).map(ObjectInner::DmarcInternalReport) + } + ObjectType::DmarcReportSettings => { + DmarcReportSettings::deserialize(deserializer).map(ObjectInner::DmarcReportSettings) + } + ObjectType::DnsResolver => { + DnsResolver::deserialize(deserializer).map(ObjectInner::DnsResolver) + } + ObjectType::DnsServer => { + DnsServer::deserialize(deserializer).map(ObjectInner::DnsServer) + } + ObjectType::Domain => Domain::deserialize(deserializer).map(ObjectInner::Domain), + ObjectType::DsnReportSettings => { + DsnReportSettings::deserialize(deserializer).map(ObjectInner::DsnReportSettings) + } + ObjectType::Email => Email::deserialize(deserializer).map(ObjectInner::Email), + ObjectType::Enterprise => { + Enterprise::deserialize(deserializer).map(ObjectInner::Enterprise) + } + ObjectType::EventTracingLevel => { + EventTracingLevel::deserialize(deserializer).map(ObjectInner::EventTracingLevel) + } + ObjectType::FileStorage => { + FileStorage::deserialize(deserializer).map(ObjectInner::FileStorage) + } + ObjectType::Http => Http::deserialize(deserializer).map(ObjectInner::Http), + ObjectType::HttpForm => HttpForm::deserialize(deserializer).map(ObjectInner::HttpForm), + ObjectType::HttpLookup => { + HttpLookup::deserialize(deserializer).map(ObjectInner::HttpLookup) + } + ObjectType::Imap => Imap::deserialize(deserializer).map(ObjectInner::Imap), + ObjectType::InMemoryStore => { + InMemoryStore::deserialize(deserializer).map(ObjectInner::InMemoryStore) + } + ObjectType::Jmap => Jmap::deserialize(deserializer).map(ObjectInner::Jmap), + ObjectType::Log => Log::deserialize(deserializer).map(ObjectInner::Log), + ObjectType::MailingList => { + MailingList::deserialize(deserializer).map(ObjectInner::MailingList) + } + ObjectType::MaskedEmail => { + MaskedEmail::deserialize(deserializer).map(ObjectInner::MaskedEmail) + } + ObjectType::MemoryLookupKey => { + MemoryLookupKey::deserialize(deserializer).map(ObjectInner::MemoryLookupKey) + } + ObjectType::MemoryLookupKeyValue => MemoryLookupKeyValue::deserialize(deserializer) + .map(ObjectInner::MemoryLookupKeyValue), + ObjectType::Metric => Metric::deserialize(deserializer).map(ObjectInner::Metric), + ObjectType::Metrics => Metrics::deserialize(deserializer).map(ObjectInner::Metrics), + ObjectType::MetricsStore => { + MetricsStore::deserialize(deserializer).map(ObjectInner::MetricsStore) + } + ObjectType::MtaConnectionStrategy => MtaConnectionStrategy::deserialize(deserializer) + .map(ObjectInner::MtaConnectionStrategy), + ObjectType::MtaDeliverySchedule => { + MtaDeliverySchedule::deserialize(deserializer).map(ObjectInner::MtaDeliverySchedule) + } + ObjectType::MtaExtensions => { + MtaExtensions::deserialize(deserializer).map(ObjectInner::MtaExtensions) + } + ObjectType::MtaHook => MtaHook::deserialize(deserializer).map(ObjectInner::MtaHook), + ObjectType::MtaInboundSession => { + MtaInboundSession::deserialize(deserializer).map(ObjectInner::MtaInboundSession) + } + ObjectType::MtaInboundThrottle => { + MtaInboundThrottle::deserialize(deserializer).map(ObjectInner::MtaInboundThrottle) + } + ObjectType::MtaMilter => { + MtaMilter::deserialize(deserializer).map(ObjectInner::MtaMilter) + } + ObjectType::MtaOutboundStrategy => { + MtaOutboundStrategy::deserialize(deserializer).map(ObjectInner::MtaOutboundStrategy) + } + ObjectType::MtaOutboundThrottle => { + MtaOutboundThrottle::deserialize(deserializer).map(ObjectInner::MtaOutboundThrottle) + } + ObjectType::MtaQueueQuota => { + MtaQueueQuota::deserialize(deserializer).map(ObjectInner::MtaQueueQuota) + } + ObjectType::MtaRoute => MtaRoute::deserialize(deserializer).map(ObjectInner::MtaRoute), + ObjectType::MtaStageAuth => { + MtaStageAuth::deserialize(deserializer).map(ObjectInner::MtaStageAuth) + } + ObjectType::MtaStageConnect => { + MtaStageConnect::deserialize(deserializer).map(ObjectInner::MtaStageConnect) + } + ObjectType::MtaStageData => { + MtaStageData::deserialize(deserializer).map(ObjectInner::MtaStageData) + } + ObjectType::MtaStageEhlo => { + MtaStageEhlo::deserialize(deserializer).map(ObjectInner::MtaStageEhlo) + } + ObjectType::MtaStageMail => { + MtaStageMail::deserialize(deserializer).map(ObjectInner::MtaStageMail) + } + ObjectType::MtaStageRcpt => { + MtaStageRcpt::deserialize(deserializer).map(ObjectInner::MtaStageRcpt) + } + ObjectType::MtaSts => MtaSts::deserialize(deserializer).map(ObjectInner::MtaSts), + ObjectType::MtaTlsStrategy => { + MtaTlsStrategy::deserialize(deserializer).map(ObjectInner::MtaTlsStrategy) + } + ObjectType::MtaVirtualQueue => { + MtaVirtualQueue::deserialize(deserializer).map(ObjectInner::MtaVirtualQueue) + } + ObjectType::NetworkListener => { + NetworkListener::deserialize(deserializer).map(ObjectInner::NetworkListener) + } + ObjectType::OAuthClient => { + OAuthClient::deserialize(deserializer).map(ObjectInner::OAuthClient) + } + ObjectType::OidcProvider => { + OidcProvider::deserialize(deserializer).map(ObjectInner::OidcProvider) + } + ObjectType::PublicKey => { + PublicKey::deserialize(deserializer).map(ObjectInner::PublicKey) + } + ObjectType::QueuedMessage => { + QueuedMessage::deserialize(deserializer).map(ObjectInner::QueuedMessage) + } + ObjectType::ReportSettings => { + ReportSettings::deserialize(deserializer).map(ObjectInner::ReportSettings) + } + ObjectType::Role => Role::deserialize(deserializer).map(ObjectInner::Role), + ObjectType::Search => Search::deserialize(deserializer).map(ObjectInner::Search), + ObjectType::SearchStore => { + SearchStore::deserialize(deserializer).map(ObjectInner::SearchStore) + } + ObjectType::Security => Security::deserialize(deserializer).map(ObjectInner::Security), + ObjectType::SenderAuth => { + SenderAuth::deserialize(deserializer).map(ObjectInner::SenderAuth) + } + ObjectType::Sharing => Sharing::deserialize(deserializer).map(ObjectInner::Sharing), + ObjectType::SieveSystemInterpreter => SieveSystemInterpreter::deserialize(deserializer) + .map(ObjectInner::SieveSystemInterpreter), + ObjectType::SieveSystemScript => { + SieveSystemScript::deserialize(deserializer).map(ObjectInner::SieveSystemScript) + } + ObjectType::SieveUserInterpreter => SieveUserInterpreter::deserialize(deserializer) + .map(ObjectInner::SieveUserInterpreter), + ObjectType::SieveUserScript => { + SieveUserScript::deserialize(deserializer).map(ObjectInner::SieveUserScript) + } + ObjectType::SpamClassifier => { + SpamClassifier::deserialize(deserializer).map(ObjectInner::SpamClassifier) + } + ObjectType::SpamDnsblServer => { + SpamDnsblServer::deserialize(deserializer).map(ObjectInner::SpamDnsblServer) + } + ObjectType::SpamDnsblSettings => { + SpamDnsblSettings::deserialize(deserializer).map(ObjectInner::SpamDnsblSettings) + } + ObjectType::SpamFileExtension => { + SpamFileExtension::deserialize(deserializer).map(ObjectInner::SpamFileExtension) + } + ObjectType::SpamLlm => SpamLlm::deserialize(deserializer).map(ObjectInner::SpamLlm), + ObjectType::SpamPyzor => { + SpamPyzor::deserialize(deserializer).map(ObjectInner::SpamPyzor) + } + ObjectType::SpamRule => SpamRule::deserialize(deserializer).map(ObjectInner::SpamRule), + ObjectType::SpamSettings => { + SpamSettings::deserialize(deserializer).map(ObjectInner::SpamSettings) + } + ObjectType::SpamTag => SpamTag::deserialize(deserializer).map(ObjectInner::SpamTag), + ObjectType::SpamTrainingSample => { + SpamTrainingSample::deserialize(deserializer).map(ObjectInner::SpamTrainingSample) + } + ObjectType::SpfReportSettings => { + SpfReportSettings::deserialize(deserializer).map(ObjectInner::SpfReportSettings) + } + ObjectType::StoreLookup => { + StoreLookup::deserialize(deserializer).map(ObjectInner::StoreLookup) + } + ObjectType::SystemSettings => { + SystemSettings::deserialize(deserializer).map(ObjectInner::SystemSettings) + } + ObjectType::Task => Task::deserialize(deserializer).map(ObjectInner::Task), + ObjectType::TaskManager => { + TaskManager::deserialize(deserializer).map(ObjectInner::TaskManager) + } + ObjectType::Tenant => Tenant::deserialize(deserializer).map(ObjectInner::Tenant), + ObjectType::TlsExternalReport => { + TlsExternalReport::deserialize(deserializer).map(ObjectInner::TlsExternalReport) + } + ObjectType::TlsInternalReport => { + TlsInternalReport::deserialize(deserializer).map(ObjectInner::TlsInternalReport) + } + ObjectType::TlsReportSettings => { + TlsReportSettings::deserialize(deserializer).map(ObjectInner::TlsReportSettings) + } + ObjectType::Trace => Trace::deserialize(deserializer).map(ObjectInner::Trace), + ObjectType::Tracer => Tracer::deserialize(deserializer).map(ObjectInner::Tracer), + ObjectType::TracingStore => { + TracingStore::deserialize(deserializer).map(ObjectInner::TracingStore) + } + ObjectType::WebDav => WebDav::deserialize(deserializer).map(ObjectInner::WebDav), + ObjectType::WebHook => WebHook::deserialize(deserializer).map(ObjectInner::WebHook), + } + } + + pub fn expression_ctxs(&self) -> Option>> { + match &self { + ObjectInner::Alert(obj) => Some(obj.expression_ctxs()), + ObjectInner::DkimReportSettings(obj) => Some(obj.expression_ctxs()), + ObjectInner::DmarcReportSettings(obj) => Some(obj.expression_ctxs()), + ObjectInner::DsnReportSettings(obj) => Some(obj.expression_ctxs()), + ObjectInner::Http(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaExtensions(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaHook(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaInboundSession(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaInboundThrottle(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaMilter(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaOutboundStrategy(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaOutboundThrottle(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaQueueQuota(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageAuth(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageConnect(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageData(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageEhlo(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageMail(obj) => Some(obj.expression_ctxs()), + ObjectInner::MtaStageRcpt(obj) => Some(obj.expression_ctxs()), + ObjectInner::ReportSettings(obj) => Some(obj.expression_ctxs()), + ObjectInner::SenderAuth(obj) => Some(obj.expression_ctxs()), + ObjectInner::SieveSystemInterpreter(obj) => Some(obj.expression_ctxs()), + ObjectInner::SpamDnsblServer(obj) => Some(obj.expression_ctxs()), + ObjectInner::SpamRule(obj) => Some(obj.expression_ctxs()), + ObjectInner::SpfReportSettings(obj) => Some(obj.expression_ctxs()), + ObjectInner::TlsReportSettings(obj) => Some(obj.expression_ctxs()), + _ => None, + } + } +} + +impl Object { + pub fn flags(&self) -> u64 { + match &self.inner { + ObjectInner::Account(_) => Account::FLAGS, + ObjectInner::AccountPassword(_) => AccountPassword::FLAGS, + ObjectInner::AccountSettings(_) => AccountSettings::FLAGS, + ObjectInner::AcmeProvider(_) => AcmeProvider::FLAGS, + ObjectInner::Action(_) => Action::FLAGS, + ObjectInner::AddressBook(_) => AddressBook::FLAGS, + ObjectInner::AiModel(_) => AiModel::FLAGS, + ObjectInner::Alert(_) => Alert::FLAGS, + ObjectInner::AllowedIp(_) => AllowedIp::FLAGS, + ObjectInner::ApiKey(_) => ApiKey::FLAGS, + ObjectInner::AppPassword(_) => AppPassword::FLAGS, + ObjectInner::Application(_) => Application::FLAGS, + ObjectInner::ArchivedItem(_) => ArchivedItem::FLAGS, + ObjectInner::ArfExternalReport(_) => ArfExternalReport::FLAGS, + ObjectInner::Asn(_) => Asn::FLAGS, + ObjectInner::Authentication(_) => Authentication::FLAGS, + ObjectInner::BlobStore(_) => BlobStore::FLAGS, + ObjectInner::BlockedIp(_) => BlockedIp::FLAGS, + ObjectInner::Bootstrap(_) => Bootstrap::FLAGS, + ObjectInner::Cache(_) => Cache::FLAGS, + ObjectInner::Calendar(_) => Calendar::FLAGS, + ObjectInner::CalendarAlarm(_) => CalendarAlarm::FLAGS, + ObjectInner::CalendarScheduling(_) => CalendarScheduling::FLAGS, + ObjectInner::Certificate(_) => Certificate::FLAGS, + ObjectInner::ClusterNode(_) => ClusterNode::FLAGS, + ObjectInner::ClusterRole(_) => ClusterRole::FLAGS, + ObjectInner::Coordinator(_) => Coordinator::FLAGS, + ObjectInner::DataRetention(_) => DataRetention::FLAGS, + ObjectInner::DataStore(_) => DataStore::FLAGS, + ObjectInner::Directory(_) => Directory::FLAGS, + ObjectInner::DkimReportSettings(_) => DkimReportSettings::FLAGS, + ObjectInner::DkimSignature(_) => DkimSignature::FLAGS, + ObjectInner::DmarcExternalReport(_) => DmarcExternalReport::FLAGS, + ObjectInner::DmarcInternalReport(_) => DmarcInternalReport::FLAGS, + ObjectInner::DmarcReportSettings(_) => DmarcReportSettings::FLAGS, + ObjectInner::DnsResolver(_) => DnsResolver::FLAGS, + ObjectInner::DnsServer(_) => DnsServer::FLAGS, + ObjectInner::Domain(_) => Domain::FLAGS, + ObjectInner::DsnReportSettings(_) => DsnReportSettings::FLAGS, + ObjectInner::Email(_) => Email::FLAGS, + ObjectInner::Enterprise(_) => Enterprise::FLAGS, + ObjectInner::EventTracingLevel(_) => EventTracingLevel::FLAGS, + ObjectInner::FileStorage(_) => FileStorage::FLAGS, + ObjectInner::Http(_) => Http::FLAGS, + ObjectInner::HttpForm(_) => HttpForm::FLAGS, + ObjectInner::HttpLookup(_) => HttpLookup::FLAGS, + ObjectInner::Imap(_) => Imap::FLAGS, + ObjectInner::InMemoryStore(_) => InMemoryStore::FLAGS, + ObjectInner::Jmap(_) => Jmap::FLAGS, + ObjectInner::Log(_) => Log::FLAGS, + ObjectInner::MailingList(_) => MailingList::FLAGS, + ObjectInner::MaskedEmail(_) => MaskedEmail::FLAGS, + ObjectInner::MemoryLookupKey(_) => MemoryLookupKey::FLAGS, + ObjectInner::MemoryLookupKeyValue(_) => MemoryLookupKeyValue::FLAGS, + ObjectInner::Metric(_) => Metric::FLAGS, + ObjectInner::Metrics(_) => Metrics::FLAGS, + ObjectInner::MetricsStore(_) => MetricsStore::FLAGS, + ObjectInner::MtaConnectionStrategy(_) => MtaConnectionStrategy::FLAGS, + ObjectInner::MtaDeliverySchedule(_) => MtaDeliverySchedule::FLAGS, + ObjectInner::MtaExtensions(_) => MtaExtensions::FLAGS, + ObjectInner::MtaHook(_) => MtaHook::FLAGS, + ObjectInner::MtaInboundSession(_) => MtaInboundSession::FLAGS, + ObjectInner::MtaInboundThrottle(_) => MtaInboundThrottle::FLAGS, + ObjectInner::MtaMilter(_) => MtaMilter::FLAGS, + ObjectInner::MtaOutboundStrategy(_) => MtaOutboundStrategy::FLAGS, + ObjectInner::MtaOutboundThrottle(_) => MtaOutboundThrottle::FLAGS, + ObjectInner::MtaQueueQuota(_) => MtaQueueQuota::FLAGS, + ObjectInner::MtaRoute(_) => MtaRoute::FLAGS, + ObjectInner::MtaStageAuth(_) => MtaStageAuth::FLAGS, + ObjectInner::MtaStageConnect(_) => MtaStageConnect::FLAGS, + ObjectInner::MtaStageData(_) => MtaStageData::FLAGS, + ObjectInner::MtaStageEhlo(_) => MtaStageEhlo::FLAGS, + ObjectInner::MtaStageMail(_) => MtaStageMail::FLAGS, + ObjectInner::MtaStageRcpt(_) => MtaStageRcpt::FLAGS, + ObjectInner::MtaSts(_) => MtaSts::FLAGS, + ObjectInner::MtaTlsStrategy(_) => MtaTlsStrategy::FLAGS, + ObjectInner::MtaVirtualQueue(_) => MtaVirtualQueue::FLAGS, + ObjectInner::NetworkListener(_) => NetworkListener::FLAGS, + ObjectInner::OAuthClient(_) => OAuthClient::FLAGS, + ObjectInner::OidcProvider(_) => OidcProvider::FLAGS, + ObjectInner::PublicKey(_) => PublicKey::FLAGS, + ObjectInner::QueuedMessage(_) => QueuedMessage::FLAGS, + ObjectInner::ReportSettings(_) => ReportSettings::FLAGS, + ObjectInner::Role(_) => Role::FLAGS, + ObjectInner::Search(_) => Search::FLAGS, + ObjectInner::SearchStore(_) => SearchStore::FLAGS, + ObjectInner::Security(_) => Security::FLAGS, + ObjectInner::SenderAuth(_) => SenderAuth::FLAGS, + ObjectInner::Sharing(_) => Sharing::FLAGS, + ObjectInner::SieveSystemInterpreter(_) => SieveSystemInterpreter::FLAGS, + ObjectInner::SieveSystemScript(_) => SieveSystemScript::FLAGS, + ObjectInner::SieveUserInterpreter(_) => SieveUserInterpreter::FLAGS, + ObjectInner::SieveUserScript(_) => SieveUserScript::FLAGS, + ObjectInner::SpamClassifier(_) => SpamClassifier::FLAGS, + ObjectInner::SpamDnsblServer(_) => SpamDnsblServer::FLAGS, + ObjectInner::SpamDnsblSettings(_) => SpamDnsblSettings::FLAGS, + ObjectInner::SpamFileExtension(_) => SpamFileExtension::FLAGS, + ObjectInner::SpamLlm(_) => SpamLlm::FLAGS, + ObjectInner::SpamPyzor(_) => SpamPyzor::FLAGS, + ObjectInner::SpamRule(_) => SpamRule::FLAGS, + ObjectInner::SpamSettings(_) => SpamSettings::FLAGS, + ObjectInner::SpamTag(_) => SpamTag::FLAGS, + ObjectInner::SpamTrainingSample(_) => SpamTrainingSample::FLAGS, + ObjectInner::SpfReportSettings(_) => SpfReportSettings::FLAGS, + ObjectInner::StoreLookup(_) => StoreLookup::FLAGS, + ObjectInner::SystemSettings(_) => SystemSettings::FLAGS, + ObjectInner::Task(_) => Task::FLAGS, + ObjectInner::TaskManager(_) => TaskManager::FLAGS, + ObjectInner::Tenant(_) => Tenant::FLAGS, + ObjectInner::TlsExternalReport(_) => TlsExternalReport::FLAGS, + ObjectInner::TlsInternalReport(_) => TlsInternalReport::FLAGS, + ObjectInner::TlsReportSettings(_) => TlsReportSettings::FLAGS, + ObjectInner::Trace(_) => Trace::FLAGS, + ObjectInner::Tracer(_) => Tracer::FLAGS, + ObjectInner::TracingStore(_) => TracingStore::FLAGS, + ObjectInner::WebDav(_) => WebDav::FLAGS, + ObjectInner::WebHook(_) => WebHook::FLAGS, + } + } + + pub fn object_type(&self) -> ObjectType { + match &self.inner { + ObjectInner::Account(_) => ObjectType::Account, + ObjectInner::AccountPassword(_) => ObjectType::AccountPassword, + ObjectInner::AccountSettings(_) => ObjectType::AccountSettings, + ObjectInner::AcmeProvider(_) => ObjectType::AcmeProvider, + ObjectInner::Action(_) => ObjectType::Action, + ObjectInner::AddressBook(_) => ObjectType::AddressBook, + ObjectInner::AiModel(_) => ObjectType::AiModel, + ObjectInner::Alert(_) => ObjectType::Alert, + ObjectInner::AllowedIp(_) => ObjectType::AllowedIp, + ObjectInner::ApiKey(_) => ObjectType::ApiKey, + ObjectInner::AppPassword(_) => ObjectType::AppPassword, + ObjectInner::Application(_) => ObjectType::Application, + ObjectInner::ArchivedItem(_) => ObjectType::ArchivedItem, + ObjectInner::ArfExternalReport(_) => ObjectType::ArfExternalReport, + ObjectInner::Asn(_) => ObjectType::Asn, + ObjectInner::Authentication(_) => ObjectType::Authentication, + ObjectInner::BlobStore(_) => ObjectType::BlobStore, + ObjectInner::BlockedIp(_) => ObjectType::BlockedIp, + ObjectInner::Bootstrap(_) => ObjectType::Bootstrap, + ObjectInner::Cache(_) => ObjectType::Cache, + ObjectInner::Calendar(_) => ObjectType::Calendar, + ObjectInner::CalendarAlarm(_) => ObjectType::CalendarAlarm, + ObjectInner::CalendarScheduling(_) => ObjectType::CalendarScheduling, + ObjectInner::Certificate(_) => ObjectType::Certificate, + ObjectInner::ClusterNode(_) => ObjectType::ClusterNode, + ObjectInner::ClusterRole(_) => ObjectType::ClusterRole, + ObjectInner::Coordinator(_) => ObjectType::Coordinator, + ObjectInner::DataRetention(_) => ObjectType::DataRetention, + ObjectInner::DataStore(_) => ObjectType::DataStore, + ObjectInner::Directory(_) => ObjectType::Directory, + ObjectInner::DkimReportSettings(_) => ObjectType::DkimReportSettings, + ObjectInner::DkimSignature(_) => ObjectType::DkimSignature, + ObjectInner::DmarcExternalReport(_) => ObjectType::DmarcExternalReport, + ObjectInner::DmarcInternalReport(_) => ObjectType::DmarcInternalReport, + ObjectInner::DmarcReportSettings(_) => ObjectType::DmarcReportSettings, + ObjectInner::DnsResolver(_) => ObjectType::DnsResolver, + ObjectInner::DnsServer(_) => ObjectType::DnsServer, + ObjectInner::Domain(_) => ObjectType::Domain, + ObjectInner::DsnReportSettings(_) => ObjectType::DsnReportSettings, + ObjectInner::Email(_) => ObjectType::Email, + ObjectInner::Enterprise(_) => ObjectType::Enterprise, + ObjectInner::EventTracingLevel(_) => ObjectType::EventTracingLevel, + ObjectInner::FileStorage(_) => ObjectType::FileStorage, + ObjectInner::Http(_) => ObjectType::Http, + ObjectInner::HttpForm(_) => ObjectType::HttpForm, + ObjectInner::HttpLookup(_) => ObjectType::HttpLookup, + ObjectInner::Imap(_) => ObjectType::Imap, + ObjectInner::InMemoryStore(_) => ObjectType::InMemoryStore, + ObjectInner::Jmap(_) => ObjectType::Jmap, + ObjectInner::Log(_) => ObjectType::Log, + ObjectInner::MailingList(_) => ObjectType::MailingList, + ObjectInner::MaskedEmail(_) => ObjectType::MaskedEmail, + ObjectInner::MemoryLookupKey(_) => ObjectType::MemoryLookupKey, + ObjectInner::MemoryLookupKeyValue(_) => ObjectType::MemoryLookupKeyValue, + ObjectInner::Metric(_) => ObjectType::Metric, + ObjectInner::Metrics(_) => ObjectType::Metrics, + ObjectInner::MetricsStore(_) => ObjectType::MetricsStore, + ObjectInner::MtaConnectionStrategy(_) => ObjectType::MtaConnectionStrategy, + ObjectInner::MtaDeliverySchedule(_) => ObjectType::MtaDeliverySchedule, + ObjectInner::MtaExtensions(_) => ObjectType::MtaExtensions, + ObjectInner::MtaHook(_) => ObjectType::MtaHook, + ObjectInner::MtaInboundSession(_) => ObjectType::MtaInboundSession, + ObjectInner::MtaInboundThrottle(_) => ObjectType::MtaInboundThrottle, + ObjectInner::MtaMilter(_) => ObjectType::MtaMilter, + ObjectInner::MtaOutboundStrategy(_) => ObjectType::MtaOutboundStrategy, + ObjectInner::MtaOutboundThrottle(_) => ObjectType::MtaOutboundThrottle, + ObjectInner::MtaQueueQuota(_) => ObjectType::MtaQueueQuota, + ObjectInner::MtaRoute(_) => ObjectType::MtaRoute, + ObjectInner::MtaStageAuth(_) => ObjectType::MtaStageAuth, + ObjectInner::MtaStageConnect(_) => ObjectType::MtaStageConnect, + ObjectInner::MtaStageData(_) => ObjectType::MtaStageData, + ObjectInner::MtaStageEhlo(_) => ObjectType::MtaStageEhlo, + ObjectInner::MtaStageMail(_) => ObjectType::MtaStageMail, + ObjectInner::MtaStageRcpt(_) => ObjectType::MtaStageRcpt, + ObjectInner::MtaSts(_) => ObjectType::MtaSts, + ObjectInner::MtaTlsStrategy(_) => ObjectType::MtaTlsStrategy, + ObjectInner::MtaVirtualQueue(_) => ObjectType::MtaVirtualQueue, + ObjectInner::NetworkListener(_) => ObjectType::NetworkListener, + ObjectInner::OAuthClient(_) => ObjectType::OAuthClient, + ObjectInner::OidcProvider(_) => ObjectType::OidcProvider, + ObjectInner::PublicKey(_) => ObjectType::PublicKey, + ObjectInner::QueuedMessage(_) => ObjectType::QueuedMessage, + ObjectInner::ReportSettings(_) => ObjectType::ReportSettings, + ObjectInner::Role(_) => ObjectType::Role, + ObjectInner::Search(_) => ObjectType::Search, + ObjectInner::SearchStore(_) => ObjectType::SearchStore, + ObjectInner::Security(_) => ObjectType::Security, + ObjectInner::SenderAuth(_) => ObjectType::SenderAuth, + ObjectInner::Sharing(_) => ObjectType::Sharing, + ObjectInner::SieveSystemInterpreter(_) => ObjectType::SieveSystemInterpreter, + ObjectInner::SieveSystemScript(_) => ObjectType::SieveSystemScript, + ObjectInner::SieveUserInterpreter(_) => ObjectType::SieveUserInterpreter, + ObjectInner::SieveUserScript(_) => ObjectType::SieveUserScript, + ObjectInner::SpamClassifier(_) => ObjectType::SpamClassifier, + ObjectInner::SpamDnsblServer(_) => ObjectType::SpamDnsblServer, + ObjectInner::SpamDnsblSettings(_) => ObjectType::SpamDnsblSettings, + ObjectInner::SpamFileExtension(_) => ObjectType::SpamFileExtension, + ObjectInner::SpamLlm(_) => ObjectType::SpamLlm, + ObjectInner::SpamPyzor(_) => ObjectType::SpamPyzor, + ObjectInner::SpamRule(_) => ObjectType::SpamRule, + ObjectInner::SpamSettings(_) => ObjectType::SpamSettings, + ObjectInner::SpamTag(_) => ObjectType::SpamTag, + ObjectInner::SpamTrainingSample(_) => ObjectType::SpamTrainingSample, + ObjectInner::SpfReportSettings(_) => ObjectType::SpfReportSettings, + ObjectInner::StoreLookup(_) => ObjectType::StoreLookup, + ObjectInner::SystemSettings(_) => ObjectType::SystemSettings, + ObjectInner::Task(_) => ObjectType::Task, + ObjectInner::TaskManager(_) => ObjectType::TaskManager, + ObjectInner::Tenant(_) => ObjectType::Tenant, + ObjectInner::TlsExternalReport(_) => ObjectType::TlsExternalReport, + ObjectInner::TlsInternalReport(_) => ObjectType::TlsInternalReport, + ObjectInner::TlsReportSettings(_) => ObjectType::TlsReportSettings, + ObjectInner::Trace(_) => ObjectType::Trace, + ObjectInner::Tracer(_) => ObjectType::Tracer, + ObjectInner::TracingStore(_) => ObjectType::TracingStore, + ObjectInner::WebDav(_) => ObjectType::WebDav, + ObjectInner::WebHook(_) => ObjectType::WebHook, + } + } + + pub fn validate(&self, errors: &mut Vec) -> bool { + match &self.inner { + ObjectInner::Account(obj) => obj.validate(errors), + ObjectInner::AccountPassword(obj) => obj.validate(errors), + ObjectInner::AccountSettings(obj) => obj.validate(errors), + ObjectInner::AcmeProvider(obj) => obj.validate(errors), + ObjectInner::Action(obj) => obj.validate(errors), + ObjectInner::AddressBook(obj) => obj.validate(errors), + ObjectInner::AiModel(obj) => obj.validate(errors), + ObjectInner::Alert(obj) => obj.validate(errors), + ObjectInner::AllowedIp(obj) => obj.validate(errors), + ObjectInner::ApiKey(obj) => obj.validate(errors), + ObjectInner::AppPassword(obj) => obj.validate(errors), + ObjectInner::Application(obj) => obj.validate(errors), + ObjectInner::ArchivedItem(obj) => obj.validate(errors), + ObjectInner::ArfExternalReport(obj) => obj.validate(errors), + ObjectInner::Asn(obj) => obj.validate(errors), + ObjectInner::Authentication(obj) => obj.validate(errors), + ObjectInner::BlobStore(obj) => obj.validate(errors), + ObjectInner::BlockedIp(obj) => obj.validate(errors), + ObjectInner::Bootstrap(obj) => obj.validate(errors), + ObjectInner::Cache(obj) => obj.validate(errors), + ObjectInner::Calendar(obj) => obj.validate(errors), + ObjectInner::CalendarAlarm(obj) => obj.validate(errors), + ObjectInner::CalendarScheduling(obj) => obj.validate(errors), + ObjectInner::Certificate(obj) => obj.validate(errors), + ObjectInner::ClusterNode(obj) => obj.validate(errors), + ObjectInner::ClusterRole(obj) => obj.validate(errors), + ObjectInner::Coordinator(obj) => obj.validate(errors), + ObjectInner::DataRetention(obj) => obj.validate(errors), + ObjectInner::DataStore(obj) => obj.validate(errors), + ObjectInner::Directory(obj) => obj.validate(errors), + ObjectInner::DkimReportSettings(obj) => obj.validate(errors), + ObjectInner::DkimSignature(obj) => obj.validate(errors), + ObjectInner::DmarcExternalReport(obj) => obj.validate(errors), + ObjectInner::DmarcInternalReport(obj) => obj.validate(errors), + ObjectInner::DmarcReportSettings(obj) => obj.validate(errors), + ObjectInner::DnsResolver(obj) => obj.validate(errors), + ObjectInner::DnsServer(obj) => obj.validate(errors), + ObjectInner::Domain(obj) => obj.validate(errors), + ObjectInner::DsnReportSettings(obj) => obj.validate(errors), + ObjectInner::Email(obj) => obj.validate(errors), + ObjectInner::Enterprise(obj) => obj.validate(errors), + ObjectInner::EventTracingLevel(obj) => obj.validate(errors), + ObjectInner::FileStorage(obj) => obj.validate(errors), + ObjectInner::Http(obj) => obj.validate(errors), + ObjectInner::HttpForm(obj) => obj.validate(errors), + ObjectInner::HttpLookup(obj) => obj.validate(errors), + ObjectInner::Imap(obj) => obj.validate(errors), + ObjectInner::InMemoryStore(obj) => obj.validate(errors), + ObjectInner::Jmap(obj) => obj.validate(errors), + ObjectInner::Log(obj) => obj.validate(errors), + ObjectInner::MailingList(obj) => obj.validate(errors), + ObjectInner::MaskedEmail(obj) => obj.validate(errors), + ObjectInner::MemoryLookupKey(obj) => obj.validate(errors), + ObjectInner::MemoryLookupKeyValue(obj) => obj.validate(errors), + ObjectInner::Metric(obj) => obj.validate(errors), + ObjectInner::Metrics(obj) => obj.validate(errors), + ObjectInner::MetricsStore(obj) => obj.validate(errors), + ObjectInner::MtaConnectionStrategy(obj) => obj.validate(errors), + ObjectInner::MtaDeliverySchedule(obj) => obj.validate(errors), + ObjectInner::MtaExtensions(obj) => obj.validate(errors), + ObjectInner::MtaHook(obj) => obj.validate(errors), + ObjectInner::MtaInboundSession(obj) => obj.validate(errors), + ObjectInner::MtaInboundThrottle(obj) => obj.validate(errors), + ObjectInner::MtaMilter(obj) => obj.validate(errors), + ObjectInner::MtaOutboundStrategy(obj) => obj.validate(errors), + ObjectInner::MtaOutboundThrottle(obj) => obj.validate(errors), + ObjectInner::MtaQueueQuota(obj) => obj.validate(errors), + ObjectInner::MtaRoute(obj) => obj.validate(errors), + ObjectInner::MtaStageAuth(obj) => obj.validate(errors), + ObjectInner::MtaStageConnect(obj) => obj.validate(errors), + ObjectInner::MtaStageData(obj) => obj.validate(errors), + ObjectInner::MtaStageEhlo(obj) => obj.validate(errors), + ObjectInner::MtaStageMail(obj) => obj.validate(errors), + ObjectInner::MtaStageRcpt(obj) => obj.validate(errors), + ObjectInner::MtaSts(obj) => obj.validate(errors), + ObjectInner::MtaTlsStrategy(obj) => obj.validate(errors), + ObjectInner::MtaVirtualQueue(obj) => obj.validate(errors), + ObjectInner::NetworkListener(obj) => obj.validate(errors), + ObjectInner::OAuthClient(obj) => obj.validate(errors), + ObjectInner::OidcProvider(obj) => obj.validate(errors), + ObjectInner::PublicKey(obj) => obj.validate(errors), + ObjectInner::QueuedMessage(obj) => obj.validate(errors), + ObjectInner::ReportSettings(obj) => obj.validate(errors), + ObjectInner::Role(obj) => obj.validate(errors), + ObjectInner::Search(obj) => obj.validate(errors), + ObjectInner::SearchStore(obj) => obj.validate(errors), + ObjectInner::Security(obj) => obj.validate(errors), + ObjectInner::SenderAuth(obj) => obj.validate(errors), + ObjectInner::Sharing(obj) => obj.validate(errors), + ObjectInner::SieveSystemInterpreter(obj) => obj.validate(errors), + ObjectInner::SieveSystemScript(obj) => obj.validate(errors), + ObjectInner::SieveUserInterpreter(obj) => obj.validate(errors), + ObjectInner::SieveUserScript(obj) => obj.validate(errors), + ObjectInner::SpamClassifier(obj) => obj.validate(errors), + ObjectInner::SpamDnsblServer(obj) => obj.validate(errors), + ObjectInner::SpamDnsblSettings(obj) => obj.validate(errors), + ObjectInner::SpamFileExtension(obj) => obj.validate(errors), + ObjectInner::SpamLlm(obj) => obj.validate(errors), + ObjectInner::SpamPyzor(obj) => obj.validate(errors), + ObjectInner::SpamRule(obj) => obj.validate(errors), + ObjectInner::SpamSettings(obj) => obj.validate(errors), + ObjectInner::SpamTag(obj) => obj.validate(errors), + ObjectInner::SpamTrainingSample(obj) => obj.validate(errors), + ObjectInner::SpfReportSettings(obj) => obj.validate(errors), + ObjectInner::StoreLookup(obj) => obj.validate(errors), + ObjectInner::SystemSettings(obj) => obj.validate(errors), + ObjectInner::Task(obj) => obj.validate(errors), + ObjectInner::TaskManager(obj) => obj.validate(errors), + ObjectInner::Tenant(obj) => obj.validate(errors), + ObjectInner::TlsExternalReport(obj) => obj.validate(errors), + ObjectInner::TlsInternalReport(obj) => obj.validate(errors), + ObjectInner::TlsReportSettings(obj) => obj.validate(errors), + ObjectInner::Trace(obj) => obj.validate(errors), + ObjectInner::Tracer(obj) => obj.validate(errors), + ObjectInner::TracingStore(obj) => obj.validate(errors), + ObjectInner::WebDav(obj) => obj.validate(errors), + ObjectInner::WebHook(obj) => obj.validate(errors), + } + } + + pub fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match &self.inner { + ObjectInner::Account(obj) => obj.index(i), + ObjectInner::AccountPassword(obj) => obj.index(i), + ObjectInner::AccountSettings(obj) => obj.index(i), + ObjectInner::AcmeProvider(obj) => obj.index(i), + ObjectInner::Action(obj) => obj.index(i), + ObjectInner::AddressBook(obj) => obj.index(i), + ObjectInner::AiModel(obj) => obj.index(i), + ObjectInner::Alert(obj) => obj.index(i), + ObjectInner::AllowedIp(obj) => obj.index(i), + ObjectInner::ApiKey(obj) => obj.index(i), + ObjectInner::AppPassword(obj) => obj.index(i), + ObjectInner::Application(obj) => obj.index(i), + ObjectInner::ArchivedItem(obj) => obj.index(i), + ObjectInner::ArfExternalReport(obj) => obj.index(i), + ObjectInner::Asn(obj) => obj.index(i), + ObjectInner::Authentication(obj) => obj.index(i), + ObjectInner::BlobStore(obj) => obj.index(i), + ObjectInner::BlockedIp(obj) => obj.index(i), + ObjectInner::Bootstrap(obj) => obj.index(i), + ObjectInner::Cache(obj) => obj.index(i), + ObjectInner::Calendar(obj) => obj.index(i), + ObjectInner::CalendarAlarm(obj) => obj.index(i), + ObjectInner::CalendarScheduling(obj) => obj.index(i), + ObjectInner::Certificate(obj) => obj.index(i), + ObjectInner::ClusterNode(obj) => obj.index(i), + ObjectInner::ClusterRole(obj) => obj.index(i), + ObjectInner::Coordinator(obj) => obj.index(i), + ObjectInner::DataRetention(obj) => obj.index(i), + ObjectInner::DataStore(obj) => obj.index(i), + ObjectInner::Directory(obj) => obj.index(i), + ObjectInner::DkimReportSettings(obj) => obj.index(i), + ObjectInner::DkimSignature(obj) => obj.index(i), + ObjectInner::DmarcExternalReport(obj) => obj.index(i), + ObjectInner::DmarcInternalReport(obj) => obj.index(i), + ObjectInner::DmarcReportSettings(obj) => obj.index(i), + ObjectInner::DnsResolver(obj) => obj.index(i), + ObjectInner::DnsServer(obj) => obj.index(i), + ObjectInner::Domain(obj) => obj.index(i), + ObjectInner::DsnReportSettings(obj) => obj.index(i), + ObjectInner::Email(obj) => obj.index(i), + ObjectInner::Enterprise(obj) => obj.index(i), + ObjectInner::EventTracingLevel(obj) => obj.index(i), + ObjectInner::FileStorage(obj) => obj.index(i), + ObjectInner::Http(obj) => obj.index(i), + ObjectInner::HttpForm(obj) => obj.index(i), + ObjectInner::HttpLookup(obj) => obj.index(i), + ObjectInner::Imap(obj) => obj.index(i), + ObjectInner::InMemoryStore(obj) => obj.index(i), + ObjectInner::Jmap(obj) => obj.index(i), + ObjectInner::Log(obj) => obj.index(i), + ObjectInner::MailingList(obj) => obj.index(i), + ObjectInner::MaskedEmail(obj) => obj.index(i), + ObjectInner::MemoryLookupKey(obj) => obj.index(i), + ObjectInner::MemoryLookupKeyValue(obj) => obj.index(i), + ObjectInner::Metric(obj) => obj.index(i), + ObjectInner::Metrics(obj) => obj.index(i), + ObjectInner::MetricsStore(obj) => obj.index(i), + ObjectInner::MtaConnectionStrategy(obj) => obj.index(i), + ObjectInner::MtaDeliverySchedule(obj) => obj.index(i), + ObjectInner::MtaExtensions(obj) => obj.index(i), + ObjectInner::MtaHook(obj) => obj.index(i), + ObjectInner::MtaInboundSession(obj) => obj.index(i), + ObjectInner::MtaInboundThrottle(obj) => obj.index(i), + ObjectInner::MtaMilter(obj) => obj.index(i), + ObjectInner::MtaOutboundStrategy(obj) => obj.index(i), + ObjectInner::MtaOutboundThrottle(obj) => obj.index(i), + ObjectInner::MtaQueueQuota(obj) => obj.index(i), + ObjectInner::MtaRoute(obj) => obj.index(i), + ObjectInner::MtaStageAuth(obj) => obj.index(i), + ObjectInner::MtaStageConnect(obj) => obj.index(i), + ObjectInner::MtaStageData(obj) => obj.index(i), + ObjectInner::MtaStageEhlo(obj) => obj.index(i), + ObjectInner::MtaStageMail(obj) => obj.index(i), + ObjectInner::MtaStageRcpt(obj) => obj.index(i), + ObjectInner::MtaSts(obj) => obj.index(i), + ObjectInner::MtaTlsStrategy(obj) => obj.index(i), + ObjectInner::MtaVirtualQueue(obj) => obj.index(i), + ObjectInner::NetworkListener(obj) => obj.index(i), + ObjectInner::OAuthClient(obj) => obj.index(i), + ObjectInner::OidcProvider(obj) => obj.index(i), + ObjectInner::PublicKey(obj) => obj.index(i), + ObjectInner::QueuedMessage(obj) => obj.index(i), + ObjectInner::ReportSettings(obj) => obj.index(i), + ObjectInner::Role(obj) => obj.index(i), + ObjectInner::Search(obj) => obj.index(i), + ObjectInner::SearchStore(obj) => obj.index(i), + ObjectInner::Security(obj) => obj.index(i), + ObjectInner::SenderAuth(obj) => obj.index(i), + ObjectInner::Sharing(obj) => obj.index(i), + ObjectInner::SieveSystemInterpreter(obj) => obj.index(i), + ObjectInner::SieveSystemScript(obj) => obj.index(i), + ObjectInner::SieveUserInterpreter(obj) => obj.index(i), + ObjectInner::SieveUserScript(obj) => obj.index(i), + ObjectInner::SpamClassifier(obj) => obj.index(i), + ObjectInner::SpamDnsblServer(obj) => obj.index(i), + ObjectInner::SpamDnsblSettings(obj) => obj.index(i), + ObjectInner::SpamFileExtension(obj) => obj.index(i), + ObjectInner::SpamLlm(obj) => obj.index(i), + ObjectInner::SpamPyzor(obj) => obj.index(i), + ObjectInner::SpamRule(obj) => obj.index(i), + ObjectInner::SpamSettings(obj) => obj.index(i), + ObjectInner::SpamTag(obj) => obj.index(i), + ObjectInner::SpamTrainingSample(obj) => obj.index(i), + ObjectInner::SpfReportSettings(obj) => obj.index(i), + ObjectInner::StoreLookup(obj) => obj.index(i), + ObjectInner::SystemSettings(obj) => obj.index(i), + ObjectInner::Task(obj) => obj.index(i), + ObjectInner::TaskManager(obj) => obj.index(i), + ObjectInner::Tenant(obj) => obj.index(i), + ObjectInner::TlsExternalReport(obj) => obj.index(i), + ObjectInner::TlsInternalReport(obj) => obj.index(i), + ObjectInner::TlsReportSettings(obj) => obj.index(i), + ObjectInner::Trace(obj) => obj.index(i), + ObjectInner::Tracer(obj) => obj.index(i), + ObjectInner::TracingStore(obj) => obj.index(i), + ObjectInner::WebDav(obj) => obj.index(i), + ObjectInner::WebHook(obj) => obj.index(i), + } + } + + pub fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match &mut self.inner { + ObjectInner::Account(obj) => obj.patch(pointer, value), + ObjectInner::AccountPassword(obj) => obj.patch(pointer, value), + ObjectInner::AccountSettings(obj) => obj.patch(pointer, value), + ObjectInner::AcmeProvider(obj) => obj.patch(pointer, value), + ObjectInner::Action(obj) => obj.patch(pointer, value), + ObjectInner::AddressBook(obj) => obj.patch(pointer, value), + ObjectInner::AiModel(obj) => obj.patch(pointer, value), + ObjectInner::Alert(obj) => obj.patch(pointer, value), + ObjectInner::AllowedIp(obj) => obj.patch(pointer, value), + ObjectInner::ApiKey(obj) => obj.patch(pointer, value), + ObjectInner::AppPassword(obj) => obj.patch(pointer, value), + ObjectInner::Application(obj) => obj.patch(pointer, value), + ObjectInner::ArchivedItem(obj) => obj.patch(pointer, value), + ObjectInner::ArfExternalReport(obj) => obj.patch(pointer, value), + ObjectInner::Asn(obj) => obj.patch(pointer, value), + ObjectInner::Authentication(obj) => obj.patch(pointer, value), + ObjectInner::BlobStore(obj) => obj.patch(pointer, value), + ObjectInner::BlockedIp(obj) => obj.patch(pointer, value), + ObjectInner::Bootstrap(obj) => obj.patch(pointer, value), + ObjectInner::Cache(obj) => obj.patch(pointer, value), + ObjectInner::Calendar(obj) => obj.patch(pointer, value), + ObjectInner::CalendarAlarm(obj) => obj.patch(pointer, value), + ObjectInner::CalendarScheduling(obj) => obj.patch(pointer, value), + ObjectInner::Certificate(obj) => obj.patch(pointer, value), + ObjectInner::ClusterNode(obj) => obj.patch(pointer, value), + ObjectInner::ClusterRole(obj) => obj.patch(pointer, value), + ObjectInner::Coordinator(obj) => obj.patch(pointer, value), + ObjectInner::DataRetention(obj) => obj.patch(pointer, value), + ObjectInner::DataStore(obj) => obj.patch(pointer, value), + ObjectInner::Directory(obj) => obj.patch(pointer, value), + ObjectInner::DkimReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::DkimSignature(obj) => obj.patch(pointer, value), + ObjectInner::DmarcExternalReport(obj) => obj.patch(pointer, value), + ObjectInner::DmarcInternalReport(obj) => obj.patch(pointer, value), + ObjectInner::DmarcReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::DnsResolver(obj) => obj.patch(pointer, value), + ObjectInner::DnsServer(obj) => obj.patch(pointer, value), + ObjectInner::Domain(obj) => obj.patch(pointer, value), + ObjectInner::DsnReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::Email(obj) => obj.patch(pointer, value), + ObjectInner::Enterprise(obj) => obj.patch(pointer, value), + ObjectInner::EventTracingLevel(obj) => obj.patch(pointer, value), + ObjectInner::FileStorage(obj) => obj.patch(pointer, value), + ObjectInner::Http(obj) => obj.patch(pointer, value), + ObjectInner::HttpForm(obj) => obj.patch(pointer, value), + ObjectInner::HttpLookup(obj) => obj.patch(pointer, value), + ObjectInner::Imap(obj) => obj.patch(pointer, value), + ObjectInner::InMemoryStore(obj) => obj.patch(pointer, value), + ObjectInner::Jmap(obj) => obj.patch(pointer, value), + ObjectInner::Log(obj) => obj.patch(pointer, value), + ObjectInner::MailingList(obj) => obj.patch(pointer, value), + ObjectInner::MaskedEmail(obj) => obj.patch(pointer, value), + ObjectInner::MemoryLookupKey(obj) => obj.patch(pointer, value), + ObjectInner::MemoryLookupKeyValue(obj) => obj.patch(pointer, value), + ObjectInner::Metric(obj) => obj.patch(pointer, value), + ObjectInner::Metrics(obj) => obj.patch(pointer, value), + ObjectInner::MetricsStore(obj) => obj.patch(pointer, value), + ObjectInner::MtaConnectionStrategy(obj) => obj.patch(pointer, value), + ObjectInner::MtaDeliverySchedule(obj) => obj.patch(pointer, value), + ObjectInner::MtaExtensions(obj) => obj.patch(pointer, value), + ObjectInner::MtaHook(obj) => obj.patch(pointer, value), + ObjectInner::MtaInboundSession(obj) => obj.patch(pointer, value), + ObjectInner::MtaInboundThrottle(obj) => obj.patch(pointer, value), + ObjectInner::MtaMilter(obj) => obj.patch(pointer, value), + ObjectInner::MtaOutboundStrategy(obj) => obj.patch(pointer, value), + ObjectInner::MtaOutboundThrottle(obj) => obj.patch(pointer, value), + ObjectInner::MtaQueueQuota(obj) => obj.patch(pointer, value), + ObjectInner::MtaRoute(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageAuth(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageConnect(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageData(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageEhlo(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageMail(obj) => obj.patch(pointer, value), + ObjectInner::MtaStageRcpt(obj) => obj.patch(pointer, value), + ObjectInner::MtaSts(obj) => obj.patch(pointer, value), + ObjectInner::MtaTlsStrategy(obj) => obj.patch(pointer, value), + ObjectInner::MtaVirtualQueue(obj) => obj.patch(pointer, value), + ObjectInner::NetworkListener(obj) => obj.patch(pointer, value), + ObjectInner::OAuthClient(obj) => obj.patch(pointer, value), + ObjectInner::OidcProvider(obj) => obj.patch(pointer, value), + ObjectInner::PublicKey(obj) => obj.patch(pointer, value), + ObjectInner::QueuedMessage(obj) => obj.patch(pointer, value), + ObjectInner::ReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::Role(obj) => obj.patch(pointer, value), + ObjectInner::Search(obj) => obj.patch(pointer, value), + ObjectInner::SearchStore(obj) => obj.patch(pointer, value), + ObjectInner::Security(obj) => obj.patch(pointer, value), + ObjectInner::SenderAuth(obj) => obj.patch(pointer, value), + ObjectInner::Sharing(obj) => obj.patch(pointer, value), + ObjectInner::SieveSystemInterpreter(obj) => obj.patch(pointer, value), + ObjectInner::SieveSystemScript(obj) => obj.patch(pointer, value), + ObjectInner::SieveUserInterpreter(obj) => obj.patch(pointer, value), + ObjectInner::SieveUserScript(obj) => obj.patch(pointer, value), + ObjectInner::SpamClassifier(obj) => obj.patch(pointer, value), + ObjectInner::SpamDnsblServer(obj) => obj.patch(pointer, value), + ObjectInner::SpamDnsblSettings(obj) => obj.patch(pointer, value), + ObjectInner::SpamFileExtension(obj) => obj.patch(pointer, value), + ObjectInner::SpamLlm(obj) => obj.patch(pointer, value), + ObjectInner::SpamPyzor(obj) => obj.patch(pointer, value), + ObjectInner::SpamRule(obj) => obj.patch(pointer, value), + ObjectInner::SpamSettings(obj) => obj.patch(pointer, value), + ObjectInner::SpamTag(obj) => obj.patch(pointer, value), + ObjectInner::SpamTrainingSample(obj) => obj.patch(pointer, value), + ObjectInner::SpfReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::StoreLookup(obj) => obj.patch(pointer, value), + ObjectInner::SystemSettings(obj) => obj.patch(pointer, value), + ObjectInner::Task(obj) => obj.patch(pointer, value), + ObjectInner::TaskManager(obj) => obj.patch(pointer, value), + ObjectInner::Tenant(obj) => obj.patch(pointer, value), + ObjectInner::TlsExternalReport(obj) => obj.patch(pointer, value), + ObjectInner::TlsInternalReport(obj) => obj.patch(pointer, value), + ObjectInner::TlsReportSettings(obj) => obj.patch(pointer, value), + ObjectInner::Trace(obj) => obj.patch(pointer, value), + ObjectInner::Tracer(obj) => obj.patch(pointer, value), + ObjectInner::TracingStore(obj) => obj.patch(pointer, value), + ObjectInner::WebDav(obj) => obj.patch(pointer, value), + ObjectInner::WebHook(obj) => obj.patch(pointer, value), + } + } +} + +impl IntoValue for Object { + fn into_value(self) -> JmapValue<'static> { + match self.inner { + ObjectInner::Account(obj) => obj.into_value(), + ObjectInner::AccountPassword(obj) => obj.into_value(), + ObjectInner::AccountSettings(obj) => obj.into_value(), + ObjectInner::AcmeProvider(obj) => obj.into_value(), + ObjectInner::Action(obj) => obj.into_value(), + ObjectInner::AddressBook(obj) => obj.into_value(), + ObjectInner::AiModel(obj) => obj.into_value(), + ObjectInner::Alert(obj) => obj.into_value(), + ObjectInner::AllowedIp(obj) => obj.into_value(), + ObjectInner::ApiKey(obj) => obj.into_value(), + ObjectInner::AppPassword(obj) => obj.into_value(), + ObjectInner::Application(obj) => obj.into_value(), + ObjectInner::ArchivedItem(obj) => obj.into_value(), + ObjectInner::ArfExternalReport(obj) => obj.into_value(), + ObjectInner::Asn(obj) => obj.into_value(), + ObjectInner::Authentication(obj) => obj.into_value(), + ObjectInner::BlobStore(obj) => obj.into_value(), + ObjectInner::BlockedIp(obj) => obj.into_value(), + ObjectInner::Bootstrap(obj) => obj.into_value(), + ObjectInner::Cache(obj) => obj.into_value(), + ObjectInner::Calendar(obj) => obj.into_value(), + ObjectInner::CalendarAlarm(obj) => obj.into_value(), + ObjectInner::CalendarScheduling(obj) => obj.into_value(), + ObjectInner::Certificate(obj) => obj.into_value(), + ObjectInner::ClusterNode(obj) => obj.into_value(), + ObjectInner::ClusterRole(obj) => obj.into_value(), + ObjectInner::Coordinator(obj) => obj.into_value(), + ObjectInner::DataRetention(obj) => obj.into_value(), + ObjectInner::DataStore(obj) => obj.into_value(), + ObjectInner::Directory(obj) => obj.into_value(), + ObjectInner::DkimReportSettings(obj) => obj.into_value(), + ObjectInner::DkimSignature(obj) => obj.into_value(), + ObjectInner::DmarcExternalReport(obj) => obj.into_value(), + ObjectInner::DmarcInternalReport(obj) => obj.into_value(), + ObjectInner::DmarcReportSettings(obj) => obj.into_value(), + ObjectInner::DnsResolver(obj) => obj.into_value(), + ObjectInner::DnsServer(obj) => obj.into_value(), + ObjectInner::Domain(obj) => obj.into_value(), + ObjectInner::DsnReportSettings(obj) => obj.into_value(), + ObjectInner::Email(obj) => obj.into_value(), + ObjectInner::Enterprise(obj) => obj.into_value(), + ObjectInner::EventTracingLevel(obj) => obj.into_value(), + ObjectInner::FileStorage(obj) => obj.into_value(), + ObjectInner::Http(obj) => obj.into_value(), + ObjectInner::HttpForm(obj) => obj.into_value(), + ObjectInner::HttpLookup(obj) => obj.into_value(), + ObjectInner::Imap(obj) => obj.into_value(), + ObjectInner::InMemoryStore(obj) => obj.into_value(), + ObjectInner::Jmap(obj) => obj.into_value(), + ObjectInner::Log(obj) => obj.into_value(), + ObjectInner::MailingList(obj) => obj.into_value(), + ObjectInner::MaskedEmail(obj) => obj.into_value(), + ObjectInner::MemoryLookupKey(obj) => obj.into_value(), + ObjectInner::MemoryLookupKeyValue(obj) => obj.into_value(), + ObjectInner::Metric(obj) => obj.into_value(), + ObjectInner::Metrics(obj) => obj.into_value(), + ObjectInner::MetricsStore(obj) => obj.into_value(), + ObjectInner::MtaConnectionStrategy(obj) => obj.into_value(), + ObjectInner::MtaDeliverySchedule(obj) => obj.into_value(), + ObjectInner::MtaExtensions(obj) => obj.into_value(), + ObjectInner::MtaHook(obj) => obj.into_value(), + ObjectInner::MtaInboundSession(obj) => obj.into_value(), + ObjectInner::MtaInboundThrottle(obj) => obj.into_value(), + ObjectInner::MtaMilter(obj) => obj.into_value(), + ObjectInner::MtaOutboundStrategy(obj) => obj.into_value(), + ObjectInner::MtaOutboundThrottle(obj) => obj.into_value(), + ObjectInner::MtaQueueQuota(obj) => obj.into_value(), + ObjectInner::MtaRoute(obj) => obj.into_value(), + ObjectInner::MtaStageAuth(obj) => obj.into_value(), + ObjectInner::MtaStageConnect(obj) => obj.into_value(), + ObjectInner::MtaStageData(obj) => obj.into_value(), + ObjectInner::MtaStageEhlo(obj) => obj.into_value(), + ObjectInner::MtaStageMail(obj) => obj.into_value(), + ObjectInner::MtaStageRcpt(obj) => obj.into_value(), + ObjectInner::MtaSts(obj) => obj.into_value(), + ObjectInner::MtaTlsStrategy(obj) => obj.into_value(), + ObjectInner::MtaVirtualQueue(obj) => obj.into_value(), + ObjectInner::NetworkListener(obj) => obj.into_value(), + ObjectInner::OAuthClient(obj) => obj.into_value(), + ObjectInner::OidcProvider(obj) => obj.into_value(), + ObjectInner::PublicKey(obj) => obj.into_value(), + ObjectInner::QueuedMessage(obj) => obj.into_value(), + ObjectInner::ReportSettings(obj) => obj.into_value(), + ObjectInner::Role(obj) => obj.into_value(), + ObjectInner::Search(obj) => obj.into_value(), + ObjectInner::SearchStore(obj) => obj.into_value(), + ObjectInner::Security(obj) => obj.into_value(), + ObjectInner::SenderAuth(obj) => obj.into_value(), + ObjectInner::Sharing(obj) => obj.into_value(), + ObjectInner::SieveSystemInterpreter(obj) => obj.into_value(), + ObjectInner::SieveSystemScript(obj) => obj.into_value(), + ObjectInner::SieveUserInterpreter(obj) => obj.into_value(), + ObjectInner::SieveUserScript(obj) => obj.into_value(), + ObjectInner::SpamClassifier(obj) => obj.into_value(), + ObjectInner::SpamDnsblServer(obj) => obj.into_value(), + ObjectInner::SpamDnsblSettings(obj) => obj.into_value(), + ObjectInner::SpamFileExtension(obj) => obj.into_value(), + ObjectInner::SpamLlm(obj) => obj.into_value(), + ObjectInner::SpamPyzor(obj) => obj.into_value(), + ObjectInner::SpamRule(obj) => obj.into_value(), + ObjectInner::SpamSettings(obj) => obj.into_value(), + ObjectInner::SpamTag(obj) => obj.into_value(), + ObjectInner::SpamTrainingSample(obj) => obj.into_value(), + ObjectInner::SpfReportSettings(obj) => obj.into_value(), + ObjectInner::StoreLookup(obj) => obj.into_value(), + ObjectInner::SystemSettings(obj) => obj.into_value(), + ObjectInner::Task(obj) => obj.into_value(), + ObjectInner::TaskManager(obj) => obj.into_value(), + ObjectInner::Tenant(obj) => obj.into_value(), + ObjectInner::TlsExternalReport(obj) => obj.into_value(), + ObjectInner::TlsInternalReport(obj) => obj.into_value(), + ObjectInner::TlsReportSettings(obj) => obj.into_value(), + ObjectInner::Trace(obj) => obj.into_value(), + ObjectInner::Tracer(obj) => obj.into_value(), + ObjectInner::TracingStore(obj) => obj.into_value(), + ObjectInner::WebDav(obj) => obj.into_value(), + ObjectInner::WebHook(obj) => obj.into_value(), + } + } +} + +impl From for ObjectInner { + fn from(obj: ObjectType) -> Self { + match obj { + ObjectType::Account => ObjectInner::Account(Default::default()), + ObjectType::AccountPassword => ObjectInner::AccountPassword(Default::default()), + ObjectType::AccountSettings => ObjectInner::AccountSettings(Default::default()), + ObjectType::AcmeProvider => ObjectInner::AcmeProvider(Default::default()), + ObjectType::Action => ObjectInner::Action(Default::default()), + ObjectType::AddressBook => ObjectInner::AddressBook(Default::default()), + ObjectType::AiModel => ObjectInner::AiModel(Default::default()), + ObjectType::Alert => ObjectInner::Alert(Default::default()), + ObjectType::AllowedIp => ObjectInner::AllowedIp(Default::default()), + ObjectType::ApiKey => ObjectInner::ApiKey(Default::default()), + ObjectType::AppPassword => ObjectInner::AppPassword(Default::default()), + ObjectType::Application => ObjectInner::Application(Default::default()), + ObjectType::ArchivedItem => ObjectInner::ArchivedItem(Default::default()), + ObjectType::ArfExternalReport => ObjectInner::ArfExternalReport(Default::default()), + ObjectType::Asn => ObjectInner::Asn(Default::default()), + ObjectType::Authentication => ObjectInner::Authentication(Default::default()), + ObjectType::BlobStore => ObjectInner::BlobStore(Default::default()), + ObjectType::BlockedIp => ObjectInner::BlockedIp(Default::default()), + ObjectType::Bootstrap => ObjectInner::Bootstrap(Default::default()), + ObjectType::Cache => ObjectInner::Cache(Default::default()), + ObjectType::Calendar => ObjectInner::Calendar(Default::default()), + ObjectType::CalendarAlarm => ObjectInner::CalendarAlarm(Default::default()), + ObjectType::CalendarScheduling => ObjectInner::CalendarScheduling(Default::default()), + ObjectType::Certificate => ObjectInner::Certificate(Default::default()), + ObjectType::ClusterNode => ObjectInner::ClusterNode(Default::default()), + ObjectType::ClusterRole => ObjectInner::ClusterRole(Default::default()), + ObjectType::Coordinator => ObjectInner::Coordinator(Default::default()), + ObjectType::DataRetention => ObjectInner::DataRetention(Default::default()), + ObjectType::DataStore => ObjectInner::DataStore(Default::default()), + ObjectType::Directory => ObjectInner::Directory(Default::default()), + ObjectType::DkimReportSettings => ObjectInner::DkimReportSettings(Default::default()), + ObjectType::DkimSignature => ObjectInner::DkimSignature(Default::default()), + ObjectType::DmarcExternalReport => ObjectInner::DmarcExternalReport(Default::default()), + ObjectType::DmarcInternalReport => ObjectInner::DmarcInternalReport(Default::default()), + ObjectType::DmarcReportSettings => ObjectInner::DmarcReportSettings(Default::default()), + ObjectType::DnsResolver => ObjectInner::DnsResolver(Default::default()), + ObjectType::DnsServer => ObjectInner::DnsServer(Default::default()), + ObjectType::Domain => ObjectInner::Domain(Default::default()), + ObjectType::DsnReportSettings => ObjectInner::DsnReportSettings(Default::default()), + ObjectType::Email => ObjectInner::Email(Default::default()), + ObjectType::Enterprise => ObjectInner::Enterprise(Default::default()), + ObjectType::EventTracingLevel => ObjectInner::EventTracingLevel(Default::default()), + ObjectType::FileStorage => ObjectInner::FileStorage(Default::default()), + ObjectType::Http => ObjectInner::Http(Default::default()), + ObjectType::HttpForm => ObjectInner::HttpForm(Default::default()), + ObjectType::HttpLookup => ObjectInner::HttpLookup(Default::default()), + ObjectType::Imap => ObjectInner::Imap(Default::default()), + ObjectType::InMemoryStore => ObjectInner::InMemoryStore(Default::default()), + ObjectType::Jmap => ObjectInner::Jmap(Default::default()), + ObjectType::Log => ObjectInner::Log(Default::default()), + ObjectType::MailingList => ObjectInner::MailingList(Default::default()), + ObjectType::MaskedEmail => ObjectInner::MaskedEmail(Default::default()), + ObjectType::MemoryLookupKey => ObjectInner::MemoryLookupKey(Default::default()), + ObjectType::MemoryLookupKeyValue => { + ObjectInner::MemoryLookupKeyValue(Default::default()) + } + ObjectType::Metric => ObjectInner::Metric(Default::default()), + ObjectType::Metrics => ObjectInner::Metrics(Default::default()), + ObjectType::MetricsStore => ObjectInner::MetricsStore(Default::default()), + ObjectType::MtaConnectionStrategy => { + ObjectInner::MtaConnectionStrategy(Default::default()) + } + ObjectType::MtaDeliverySchedule => ObjectInner::MtaDeliverySchedule(Default::default()), + ObjectType::MtaExtensions => ObjectInner::MtaExtensions(Default::default()), + ObjectType::MtaHook => ObjectInner::MtaHook(Default::default()), + ObjectType::MtaInboundSession => ObjectInner::MtaInboundSession(Default::default()), + ObjectType::MtaInboundThrottle => ObjectInner::MtaInboundThrottle(Default::default()), + ObjectType::MtaMilter => ObjectInner::MtaMilter(Default::default()), + ObjectType::MtaOutboundStrategy => ObjectInner::MtaOutboundStrategy(Default::default()), + ObjectType::MtaOutboundThrottle => ObjectInner::MtaOutboundThrottle(Default::default()), + ObjectType::MtaQueueQuota => ObjectInner::MtaQueueQuota(Default::default()), + ObjectType::MtaRoute => ObjectInner::MtaRoute(Default::default()), + ObjectType::MtaStageAuth => ObjectInner::MtaStageAuth(Default::default()), + ObjectType::MtaStageConnect => ObjectInner::MtaStageConnect(Default::default()), + ObjectType::MtaStageData => ObjectInner::MtaStageData(Default::default()), + ObjectType::MtaStageEhlo => ObjectInner::MtaStageEhlo(Default::default()), + ObjectType::MtaStageMail => ObjectInner::MtaStageMail(Default::default()), + ObjectType::MtaStageRcpt => ObjectInner::MtaStageRcpt(Default::default()), + ObjectType::MtaSts => ObjectInner::MtaSts(Default::default()), + ObjectType::MtaTlsStrategy => ObjectInner::MtaTlsStrategy(Default::default()), + ObjectType::MtaVirtualQueue => ObjectInner::MtaVirtualQueue(Default::default()), + ObjectType::NetworkListener => ObjectInner::NetworkListener(Default::default()), + ObjectType::OAuthClient => ObjectInner::OAuthClient(Default::default()), + ObjectType::OidcProvider => ObjectInner::OidcProvider(Default::default()), + ObjectType::PublicKey => ObjectInner::PublicKey(Default::default()), + ObjectType::QueuedMessage => ObjectInner::QueuedMessage(Default::default()), + ObjectType::ReportSettings => ObjectInner::ReportSettings(Default::default()), + ObjectType::Role => ObjectInner::Role(Default::default()), + ObjectType::Search => ObjectInner::Search(Default::default()), + ObjectType::SearchStore => ObjectInner::SearchStore(Default::default()), + ObjectType::Security => ObjectInner::Security(Default::default()), + ObjectType::SenderAuth => ObjectInner::SenderAuth(Default::default()), + ObjectType::Sharing => ObjectInner::Sharing(Default::default()), + ObjectType::SieveSystemInterpreter => { + ObjectInner::SieveSystemInterpreter(Default::default()) + } + ObjectType::SieveSystemScript => ObjectInner::SieveSystemScript(Default::default()), + ObjectType::SieveUserInterpreter => { + ObjectInner::SieveUserInterpreter(Default::default()) + } + ObjectType::SieveUserScript => ObjectInner::SieveUserScript(Default::default()), + ObjectType::SpamClassifier => ObjectInner::SpamClassifier(Default::default()), + ObjectType::SpamDnsblServer => ObjectInner::SpamDnsblServer(Default::default()), + ObjectType::SpamDnsblSettings => ObjectInner::SpamDnsblSettings(Default::default()), + ObjectType::SpamFileExtension => ObjectInner::SpamFileExtension(Default::default()), + ObjectType::SpamLlm => ObjectInner::SpamLlm(Default::default()), + ObjectType::SpamPyzor => ObjectInner::SpamPyzor(Default::default()), + ObjectType::SpamRule => ObjectInner::SpamRule(Default::default()), + ObjectType::SpamSettings => ObjectInner::SpamSettings(Default::default()), + ObjectType::SpamTag => ObjectInner::SpamTag(Default::default()), + ObjectType::SpamTrainingSample => ObjectInner::SpamTrainingSample(Default::default()), + ObjectType::SpfReportSettings => ObjectInner::SpfReportSettings(Default::default()), + ObjectType::StoreLookup => ObjectInner::StoreLookup(Default::default()), + ObjectType::SystemSettings => ObjectInner::SystemSettings(Default::default()), + ObjectType::Task => ObjectInner::Task(Default::default()), + ObjectType::TaskManager => ObjectInner::TaskManager(Default::default()), + ObjectType::Tenant => ObjectInner::Tenant(Default::default()), + ObjectType::TlsExternalReport => ObjectInner::TlsExternalReport(Default::default()), + ObjectType::TlsInternalReport => ObjectInner::TlsInternalReport(Default::default()), + ObjectType::TlsReportSettings => ObjectInner::TlsReportSettings(Default::default()), + ObjectType::Trace => ObjectInner::Trace(Default::default()), + ObjectType::Tracer => ObjectInner::Tracer(Default::default()), + ObjectType::TracingStore => ObjectInner::TracingStore(Default::default()), + ObjectType::WebDav => ObjectInner::WebDav(Default::default()), + ObjectType::WebHook => ObjectInner::WebHook(Default::default()), + } + } +} + +impl From for ObjectInner { + fn from(value: Account) -> Self { + ObjectInner::Account(value) + } +} + +impl From for Account { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Account(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AccountPassword) -> Self { + ObjectInner::AccountPassword(value) + } +} + +impl From for AccountPassword { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AccountPassword(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AccountSettings) -> Self { + ObjectInner::AccountSettings(value) + } +} + +impl From for AccountSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AccountSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AcmeProvider) -> Self { + ObjectInner::AcmeProvider(value) + } +} + +impl From for AcmeProvider { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AcmeProvider(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Action) -> Self { + ObjectInner::Action(value) + } +} + +impl From for Action { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Action(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AddressBook) -> Self { + ObjectInner::AddressBook(value) + } +} + +impl From for AddressBook { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AddressBook(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AiModel) -> Self { + ObjectInner::AiModel(value) + } +} + +impl From for AiModel { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AiModel(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Alert) -> Self { + ObjectInner::Alert(value) + } +} + +impl From for Alert { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Alert(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AllowedIp) -> Self { + ObjectInner::AllowedIp(value) + } +} + +impl From for AllowedIp { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AllowedIp(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ApiKey) -> Self { + ObjectInner::ApiKey(value) + } +} + +impl From for ApiKey { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ApiKey(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: AppPassword) -> Self { + ObjectInner::AppPassword(value) + } +} + +impl From for AppPassword { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::AppPassword(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Application) -> Self { + ObjectInner::Application(value) + } +} + +impl From for Application { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Application(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ArchivedItem) -> Self { + ObjectInner::ArchivedItem(value) + } +} + +impl From for ArchivedItem { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ArchivedItem(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ArfExternalReport) -> Self { + ObjectInner::ArfExternalReport(value) + } +} + +impl From for ArfExternalReport { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ArfExternalReport(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Asn) -> Self { + ObjectInner::Asn(value) + } +} + +impl From for Asn { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Asn(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Authentication) -> Self { + ObjectInner::Authentication(value) + } +} + +impl From for Authentication { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Authentication(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: BlobStore) -> Self { + ObjectInner::BlobStore(value) + } +} + +impl From for BlobStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::BlobStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: BlockedIp) -> Self { + ObjectInner::BlockedIp(value) + } +} + +impl From for BlockedIp { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::BlockedIp(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Bootstrap) -> Self { + ObjectInner::Bootstrap(value) + } +} + +impl From for Bootstrap { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Bootstrap(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Cache) -> Self { + ObjectInner::Cache(value) + } +} + +impl From for Cache { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Cache(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Calendar) -> Self { + ObjectInner::Calendar(value) + } +} + +impl From for Calendar { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Calendar(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: CalendarAlarm) -> Self { + ObjectInner::CalendarAlarm(value) + } +} + +impl From for CalendarAlarm { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::CalendarAlarm(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: CalendarScheduling) -> Self { + ObjectInner::CalendarScheduling(value) + } +} + +impl From for CalendarScheduling { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::CalendarScheduling(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Certificate) -> Self { + ObjectInner::Certificate(value) + } +} + +impl From for Certificate { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Certificate(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ClusterNode) -> Self { + ObjectInner::ClusterNode(value) + } +} + +impl From for ClusterNode { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ClusterNode(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ClusterRole) -> Self { + ObjectInner::ClusterRole(value) + } +} + +impl From for ClusterRole { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ClusterRole(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Coordinator) -> Self { + ObjectInner::Coordinator(value) + } +} + +impl From for Coordinator { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Coordinator(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DataRetention) -> Self { + ObjectInner::DataRetention(value) + } +} + +impl From for DataRetention { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DataRetention(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DataStore) -> Self { + ObjectInner::DataStore(value) + } +} + +impl From for DataStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DataStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Directory) -> Self { + ObjectInner::Directory(value) + } +} + +impl From for Directory { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Directory(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DkimReportSettings) -> Self { + ObjectInner::DkimReportSettings(value) + } +} + +impl From for DkimReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DkimReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DkimSignature) -> Self { + ObjectInner::DkimSignature(value) + } +} + +impl From for DkimSignature { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DkimSignature(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DmarcExternalReport) -> Self { + ObjectInner::DmarcExternalReport(value) + } +} + +impl From for DmarcExternalReport { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DmarcExternalReport(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DmarcInternalReport) -> Self { + ObjectInner::DmarcInternalReport(value) + } +} + +impl From for DmarcInternalReport { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DmarcInternalReport(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DmarcReportSettings) -> Self { + ObjectInner::DmarcReportSettings(value) + } +} + +impl From for DmarcReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DmarcReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DnsResolver) -> Self { + ObjectInner::DnsResolver(value) + } +} + +impl From for DnsResolver { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DnsResolver(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DnsServer) -> Self { + ObjectInner::DnsServer(value) + } +} + +impl From for DnsServer { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DnsServer(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Domain) -> Self { + ObjectInner::Domain(value) + } +} + +impl From for Domain { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Domain(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: DsnReportSettings) -> Self { + ObjectInner::DsnReportSettings(value) + } +} + +impl From for DsnReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::DsnReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Email) -> Self { + ObjectInner::Email(value) + } +} + +impl From for Email { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Email(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Enterprise) -> Self { + ObjectInner::Enterprise(value) + } +} + +impl From for Enterprise { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Enterprise(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: EventTracingLevel) -> Self { + ObjectInner::EventTracingLevel(value) + } +} + +impl From for EventTracingLevel { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::EventTracingLevel(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: FileStorage) -> Self { + ObjectInner::FileStorage(value) + } +} + +impl From for FileStorage { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::FileStorage(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Http) -> Self { + ObjectInner::Http(value) + } +} + +impl From for Http { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Http(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: HttpForm) -> Self { + ObjectInner::HttpForm(value) + } +} + +impl From for HttpForm { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::HttpForm(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: HttpLookup) -> Self { + ObjectInner::HttpLookup(value) + } +} + +impl From for HttpLookup { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::HttpLookup(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Imap) -> Self { + ObjectInner::Imap(value) + } +} + +impl From for Imap { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Imap(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: InMemoryStore) -> Self { + ObjectInner::InMemoryStore(value) + } +} + +impl From for InMemoryStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::InMemoryStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Jmap) -> Self { + ObjectInner::Jmap(value) + } +} + +impl From for Jmap { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Jmap(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Log) -> Self { + ObjectInner::Log(value) + } +} + +impl From for Log { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Log(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MailingList) -> Self { + ObjectInner::MailingList(value) + } +} + +impl From for MailingList { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MailingList(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MaskedEmail) -> Self { + ObjectInner::MaskedEmail(value) + } +} + +impl From for MaskedEmail { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MaskedEmail(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MemoryLookupKey) -> Self { + ObjectInner::MemoryLookupKey(value) + } +} + +impl From for MemoryLookupKey { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MemoryLookupKey(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MemoryLookupKeyValue) -> Self { + ObjectInner::MemoryLookupKeyValue(value) + } +} + +impl From for MemoryLookupKeyValue { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MemoryLookupKeyValue(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Metric) -> Self { + ObjectInner::Metric(value) + } +} + +impl From for Metric { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Metric(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Metrics) -> Self { + ObjectInner::Metrics(value) + } +} + +impl From for Metrics { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Metrics(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MetricsStore) -> Self { + ObjectInner::MetricsStore(value) + } +} + +impl From for MetricsStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MetricsStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaConnectionStrategy) -> Self { + ObjectInner::MtaConnectionStrategy(value) + } +} + +impl From for MtaConnectionStrategy { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaConnectionStrategy(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaDeliverySchedule) -> Self { + ObjectInner::MtaDeliverySchedule(value) + } +} + +impl From for MtaDeliverySchedule { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaDeliverySchedule(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaExtensions) -> Self { + ObjectInner::MtaExtensions(value) + } +} + +impl From for MtaExtensions { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaExtensions(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaHook) -> Self { + ObjectInner::MtaHook(value) + } +} + +impl From for MtaHook { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaHook(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaInboundSession) -> Self { + ObjectInner::MtaInboundSession(value) + } +} + +impl From for MtaInboundSession { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaInboundSession(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaInboundThrottle) -> Self { + ObjectInner::MtaInboundThrottle(value) + } +} + +impl From for MtaInboundThrottle { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaInboundThrottle(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaMilter) -> Self { + ObjectInner::MtaMilter(value) + } +} + +impl From for MtaMilter { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaMilter(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaOutboundStrategy) -> Self { + ObjectInner::MtaOutboundStrategy(value) + } +} + +impl From for MtaOutboundStrategy { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaOutboundStrategy(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaOutboundThrottle) -> Self { + ObjectInner::MtaOutboundThrottle(value) + } +} + +impl From for MtaOutboundThrottle { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaOutboundThrottle(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaQueueQuota) -> Self { + ObjectInner::MtaQueueQuota(value) + } +} + +impl From for MtaQueueQuota { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaQueueQuota(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaRoute) -> Self { + ObjectInner::MtaRoute(value) + } +} + +impl From for MtaRoute { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaRoute(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageAuth) -> Self { + ObjectInner::MtaStageAuth(value) + } +} + +impl From for MtaStageAuth { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageAuth(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageConnect) -> Self { + ObjectInner::MtaStageConnect(value) + } +} + +impl From for MtaStageConnect { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageConnect(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageData) -> Self { + ObjectInner::MtaStageData(value) + } +} + +impl From for MtaStageData { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageData(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageEhlo) -> Self { + ObjectInner::MtaStageEhlo(value) + } +} + +impl From for MtaStageEhlo { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageEhlo(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageMail) -> Self { + ObjectInner::MtaStageMail(value) + } +} + +impl From for MtaStageMail { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageMail(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaStageRcpt) -> Self { + ObjectInner::MtaStageRcpt(value) + } +} + +impl From for MtaStageRcpt { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaStageRcpt(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaSts) -> Self { + ObjectInner::MtaSts(value) + } +} + +impl From for MtaSts { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaSts(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaTlsStrategy) -> Self { + ObjectInner::MtaTlsStrategy(value) + } +} + +impl From for MtaTlsStrategy { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaTlsStrategy(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: MtaVirtualQueue) -> Self { + ObjectInner::MtaVirtualQueue(value) + } +} + +impl From for MtaVirtualQueue { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::MtaVirtualQueue(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: NetworkListener) -> Self { + ObjectInner::NetworkListener(value) + } +} + +impl From for NetworkListener { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::NetworkListener(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: OAuthClient) -> Self { + ObjectInner::OAuthClient(value) + } +} + +impl From for OAuthClient { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::OAuthClient(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: OidcProvider) -> Self { + ObjectInner::OidcProvider(value) + } +} + +impl From for OidcProvider { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::OidcProvider(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: PublicKey) -> Self { + ObjectInner::PublicKey(value) + } +} + +impl From for PublicKey { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::PublicKey(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: QueuedMessage) -> Self { + ObjectInner::QueuedMessage(value) + } +} + +impl From for QueuedMessage { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::QueuedMessage(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: ReportSettings) -> Self { + ObjectInner::ReportSettings(value) + } +} + +impl From for ReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::ReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Role) -> Self { + ObjectInner::Role(value) + } +} + +impl From for Role { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Role(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Search) -> Self { + ObjectInner::Search(value) + } +} + +impl From for Search { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Search(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SearchStore) -> Self { + ObjectInner::SearchStore(value) + } +} + +impl From for SearchStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SearchStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Security) -> Self { + ObjectInner::Security(value) + } +} + +impl From for Security { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Security(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SenderAuth) -> Self { + ObjectInner::SenderAuth(value) + } +} + +impl From for SenderAuth { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SenderAuth(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Sharing) -> Self { + ObjectInner::Sharing(value) + } +} + +impl From for Sharing { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Sharing(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SieveSystemInterpreter) -> Self { + ObjectInner::SieveSystemInterpreter(value) + } +} + +impl From for SieveSystemInterpreter { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SieveSystemInterpreter(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SieveSystemScript) -> Self { + ObjectInner::SieveSystemScript(value) + } +} + +impl From for SieveSystemScript { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SieveSystemScript(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SieveUserInterpreter) -> Self { + ObjectInner::SieveUserInterpreter(value) + } +} + +impl From for SieveUserInterpreter { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SieveUserInterpreter(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SieveUserScript) -> Self { + ObjectInner::SieveUserScript(value) + } +} + +impl From for SieveUserScript { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SieveUserScript(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamClassifier) -> Self { + ObjectInner::SpamClassifier(value) + } +} + +impl From for SpamClassifier { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamClassifier(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamDnsblServer) -> Self { + ObjectInner::SpamDnsblServer(value) + } +} + +impl From for SpamDnsblServer { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamDnsblServer(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamDnsblSettings) -> Self { + ObjectInner::SpamDnsblSettings(value) + } +} + +impl From for SpamDnsblSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamDnsblSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamFileExtension) -> Self { + ObjectInner::SpamFileExtension(value) + } +} + +impl From for SpamFileExtension { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamFileExtension(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamLlm) -> Self { + ObjectInner::SpamLlm(value) + } +} + +impl From for SpamLlm { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamLlm(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamPyzor) -> Self { + ObjectInner::SpamPyzor(value) + } +} + +impl From for SpamPyzor { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamPyzor(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamRule) -> Self { + ObjectInner::SpamRule(value) + } +} + +impl From for SpamRule { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamRule(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamSettings) -> Self { + ObjectInner::SpamSettings(value) + } +} + +impl From for SpamSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamTag) -> Self { + ObjectInner::SpamTag(value) + } +} + +impl From for SpamTag { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamTag(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpamTrainingSample) -> Self { + ObjectInner::SpamTrainingSample(value) + } +} + +impl From for SpamTrainingSample { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpamTrainingSample(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SpfReportSettings) -> Self { + ObjectInner::SpfReportSettings(value) + } +} + +impl From for SpfReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SpfReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: StoreLookup) -> Self { + ObjectInner::StoreLookup(value) + } +} + +impl From for StoreLookup { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::StoreLookup(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: SystemSettings) -> Self { + ObjectInner::SystemSettings(value) + } +} + +impl From for SystemSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::SystemSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Task) -> Self { + ObjectInner::Task(value) + } +} + +impl From for Task { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Task(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: TaskManager) -> Self { + ObjectInner::TaskManager(value) + } +} + +impl From for TaskManager { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::TaskManager(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Tenant) -> Self { + ObjectInner::Tenant(value) + } +} + +impl From for Tenant { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Tenant(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: TlsExternalReport) -> Self { + ObjectInner::TlsExternalReport(value) + } +} + +impl From for TlsExternalReport { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::TlsExternalReport(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: TlsInternalReport) -> Self { + ObjectInner::TlsInternalReport(value) + } +} + +impl From for TlsInternalReport { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::TlsInternalReport(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: TlsReportSettings) -> Self { + ObjectInner::TlsReportSettings(value) + } +} + +impl From for TlsReportSettings { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::TlsReportSettings(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Trace) -> Self { + ObjectInner::Trace(value) + } +} + +impl From for Trace { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Trace(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: Tracer) -> Self { + ObjectInner::Tracer(value) + } +} + +impl From for Tracer { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::Tracer(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: TracingStore) -> Self { + ObjectInner::TracingStore(value) + } +} + +impl From for TracingStore { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::TracingStore(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: WebDav) -> Self { + ObjectInner::WebDav(value) + } +} + +impl From for WebDav { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::WebDav(obj) => obj, + _ => unreachable!(), + } + } +} + +impl From for ObjectInner { + fn from(value: WebHook) -> Self { + ObjectInner::WebHook(value) + } +} + +impl From for WebHook { + fn from(obj: Object) -> Self { + match obj.inner { + ObjectInner::WebHook(obj) => obj, + _ => unreachable!(), + } + } +} diff --git a/crates/registry/src/schema/structs.rs b/crates/registry/src/schema/structs.rs new file mode 100644 index 00000000..13c4cef2 --- /dev/null +++ b/crates/registry/src/schema/structs.rs @@ -0,0 +1,5133 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +use crate::schema::prelude::*; +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Account { + User(UserAccount), + Group(GroupAccount), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AccountPassword { + #[serde(rename = "secret")] + pub secret: String, + #[serde(rename = "currentSecret")] + pub current_secret: Option, + #[serde(rename = "otpAuth")] + pub otp_auth: OtpAuth, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AccountSettings { + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "locale")] + pub locale: Locale, + #[serde(rename = "timeZone")] + pub time_zone: Option, + #[serde(rename = "encryptionAtRest")] + pub encryption_at_rest: EncryptionAtRest, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AcmeProvider { + #[serde(rename = "challengeType")] + pub challenge_type: AcmeChallengeType, + #[serde(rename = "contact")] + pub contact: Map, + #[serde(rename = "directory")] + pub directory: String, + #[serde(rename = "accountKey")] + pub account_key: String, + #[serde(rename = "accountUri")] + pub account_uri: String, + #[serde(rename = "renewBefore")] + pub renew_before: AcmeRenewBefore, + #[serde(rename = "maxRetries")] + pub max_retries: i64, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Action { + ReloadSettings, + ReloadTlsCertificates, + ReloadLookupStores, + ReloadBlockedIps, + UpdateApps, + TroubleshootDmarc(DmarcTroubleshoot), + ClassifySpam(SpamClassify), + InvalidateCaches, + InvalidateNegativeCaches, + PauseMtaQueue, + ResumeMtaQueue, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AddressBook { + #[serde(rename = "defaultDisplayName")] + pub default_display_name: Option, + #[serde(rename = "defaultHrefName")] + pub default_href_name: Option, + #[serde(rename = "maxVCardSize")] + pub max_v_card_size: u64, + #[serde(rename = "maxAddressBooks")] + pub max_address_books: Option, + #[serde(rename = "maxContacts")] + pub max_contacts: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AiModel { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "temperature")] + pub temperature: Float, + #[serde(rename = "model")] + pub model: String, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "modelType")] + pub model_type: AiModelType, + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Alert { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "emailAlert")] + pub email_alert: AlertEmail, + #[serde(rename = "eventAlert")] + pub event_alert: AlertEvent, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum AlertEmail { + Disabled, + Enabled(AlertEmailProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AlertEmailProperties { + #[serde(rename = "body")] + pub body: String, + #[serde(rename = "fromAddress")] + pub from_address: String, + #[serde(rename = "fromName")] + pub from_name: Option, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "to")] + pub to: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum AlertEvent { + Disabled, + Enabled(AlertEventProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AlertEventProperties { + #[serde(rename = "eventMessage")] + pub event_message: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AllowedIp { + #[serde(rename = "address")] + pub address: IpAddrOrMask, + #[serde(rename = "reason")] + pub reason: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ApiKey { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "secret")] + pub secret: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "permissions")] + pub permissions: CredentialPermissions, + #[serde(rename = "allowedIps")] + pub allowed_ips: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AppPassword { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "secret")] + pub secret: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "permissions")] + pub permissions: CredentialPermissions, + #[serde(rename = "allowedIps")] + pub allowed_ips: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Application { + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "resourceUrl")] + pub resource_url: String, + #[serde(rename = "urlPrefix")] + pub url_prefix: Map, + #[serde(rename = "autoUpdateFrequency")] + pub auto_update_frequency: Duration, + #[serde(rename = "unpackDirectory")] + pub unpack_directory: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArchivedCalendarEvent { + #[serde(rename = "title")] + pub title: String, + #[serde(rename = "startTime")] + pub start_time: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "archivedAt")] + pub archived_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "blobId")] + pub blob_id: BlobId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArchivedContactCard { + #[serde(rename = "name")] + pub name: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "archivedAt")] + pub archived_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "blobId")] + pub blob_id: BlobId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArchivedEmail { + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "receivedAt")] + pub received_at: UTCDateTime, + #[serde(rename = "size")] + pub size: u64, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "archivedAt")] + pub archived_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "blobId")] + pub blob_id: BlobId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArchivedFileNode { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "archivedAt")] + pub archived_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "blobId")] + pub blob_id: BlobId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum ArchivedItem { + Email(ArchivedEmail), + FileNode(ArchivedFileNode), + CalendarEvent(ArchivedCalendarEvent), + ContactCard(ArchivedContactCard), + SieveScript(ArchivedSieveScript), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArchivedSieveScript { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "content")] + pub content: String, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "archivedAt")] + pub archived_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "blobId")] + pub blob_id: BlobId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArfExternalReport { + #[serde(rename = "report")] + pub report: ArfFeedbackReport, + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "to")] + pub to: Map, + #[serde(rename = "receivedAt")] + pub received_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: UTCDateTime, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ArfFeedbackReport { + #[serde(rename = "feedbackType")] + pub feedback_type: ArfFeedbackType, + #[serde(rename = "arrivalDate")] + pub arrival_date: Option, + #[serde(rename = "authenticationResults")] + pub authentication_results: Map, + #[serde(rename = "incidents")] + pub incidents: u64, + #[serde(rename = "originalEnvelopeId")] + pub original_envelope_id: Option, + #[serde(rename = "originalMailFrom")] + pub original_mail_from: Option, + #[serde(rename = "originalRcptTo")] + pub original_rcpt_to: Option, + #[serde(rename = "reportedDomains")] + pub reported_domains: Map, + #[serde(rename = "reportedUris")] + pub reported_uris: Map, + #[serde(rename = "reportingMta")] + pub reporting_mta: Option, + #[serde(rename = "sourceIp")] + pub source_ip: Option, + #[serde(rename = "sourcePort")] + pub source_port: Option, + #[serde(rename = "userAgent")] + pub user_agent: Option, + #[serde(rename = "version")] + pub version: u64, + #[serde(rename = "authFailure")] + pub auth_failure: ArfAuthFailureType, + #[serde(rename = "deliveryResult")] + pub delivery_result: ArfDeliveryResult, + #[serde(rename = "dkimAdspDns")] + pub dkim_adsp_dns: Option, + #[serde(rename = "dkimCanonicalizedBody")] + pub dkim_canonicalized_body: Option, + #[serde(rename = "dkimCanonicalizedHeader")] + pub dkim_canonicalized_header: Option, + #[serde(rename = "dkimDomain")] + pub dkim_domain: Option, + #[serde(rename = "dkimIdentity")] + pub dkim_identity: Option, + #[serde(rename = "dkimSelector")] + pub dkim_selector: Option, + #[serde(rename = "dkimSelectorDns")] + pub dkim_selector_dns: Option, + #[serde(rename = "spfDns")] + pub spf_dns: Option, + #[serde(rename = "identityAlignment")] + pub identity_alignment: ArfIdentityAlignment, + #[serde(rename = "message")] + pub message: Option, + #[serde(rename = "headers")] + pub headers: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Asn { + Disabled, + Resource(AsnResource), + Dns(AsnDns), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AsnDns { + #[serde(rename = "indexAsn")] + pub index_asn: u64, + #[serde(rename = "indexAsnName")] + pub index_asn_name: Option, + #[serde(rename = "indexCountry")] + pub index_country: Option, + #[serde(rename = "separator")] + pub separator: String, + #[serde(rename = "zoneIpV4")] + pub zone_ip_v4: String, + #[serde(rename = "zoneIpV6")] + pub zone_ip_v6: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AsnResource { + #[serde(rename = "expires")] + pub expires: Duration, + #[serde(rename = "maxSize")] + pub max_size: u64, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "asnUrls")] + pub asn_urls: Map, + #[serde(rename = "geoUrls")] + pub geo_urls: Map, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Authentication { + #[serde(rename = "directoryId")] + pub directory_id: Option, + #[serde(rename = "defaultUserRoleIds")] + pub default_user_role_ids: Map, + #[serde(rename = "defaultGroupRoleIds")] + pub default_group_role_ids: Map, + #[serde(rename = "defaultTenantRoleIds")] + pub default_tenant_role_ids: Map, + #[serde(rename = "defaultAdminRoleIds")] + pub default_admin_role_ids: Map, + #[serde(rename = "passwordHashAlgorithm")] + pub password_hash_algorithm: PasswordHashAlgorithm, + #[serde(rename = "passwordMinLength")] + pub password_min_length: u64, + #[serde(rename = "passwordMaxLength")] + pub password_max_length: u64, + #[serde(rename = "passwordMinStrength")] + pub password_min_strength: PasswordStrength, + #[serde(rename = "passwordDefaultExpiry")] + pub password_default_expiry: Option, + #[serde(rename = "maxAppPasswords")] + pub max_app_passwords: Option, + #[serde(rename = "maxApiKeys")] + pub max_api_keys: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct AzureStore { + #[serde(rename = "storageAccount")] + pub storage_account: String, + #[serde(rename = "container")] + pub container: String, + #[serde(rename = "accessKey")] + pub access_key: SecretKeyOptional, + #[serde(rename = "sasToken")] + pub sas_token: SecretKeyOptional, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "maxRetries")] + pub max_retries: u64, + #[serde(rename = "keyPrefix")] + pub key_prefix: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum BlobStore { + Default, + Sharded(ShardedBlobStore), + S3(S3Store), + Azure(AzureStore), + FileSystem(FileSystemStore), + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum BlobStoreBase { + S3(S3Store), + Azure(AzureStore), + FileSystem(FileSystemStore), + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct BlockedIp { + #[serde(rename = "address")] + pub address: IpAddrOrMask, + #[serde(rename = "reason")] + pub reason: BlockReason, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Bootstrap { + #[serde(rename = "serverHostname")] + pub server_hostname: String, + #[serde(rename = "defaultDomain")] + pub default_domain: String, + #[serde(rename = "requestTlsCertificate")] + pub request_tls_certificate: bool, + #[serde(rename = "generateDkimKeys")] + pub generate_dkim_keys: bool, + #[serde(rename = "dataStore")] + pub data_store: DataStore, + #[serde(rename = "blobStore")] + pub blob_store: BlobStore, + #[serde(rename = "searchStore")] + pub search_store: SearchStore, + #[serde(rename = "inMemoryStore")] + pub in_memory_store: InMemoryStore, + #[serde(rename = "directory")] + pub directory: DirectoryBootstrap, + #[serde(rename = "tracer")] + pub tracer: Tracer, + #[serde(rename = "dnsServer")] + pub dns_server: DnsServerBootstrap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Cache { + #[serde(rename = "accessTokens")] + pub access_tokens: u64, + #[serde(rename = "contacts")] + pub contacts: u64, + #[serde(rename = "dnsIpv4")] + pub dns_ipv4: u64, + #[serde(rename = "dnsIpv6")] + pub dns_ipv6: u64, + #[serde(rename = "dnsMtaSts")] + pub dns_mta_sts: u64, + #[serde(rename = "dnsMx")] + pub dns_mx: u64, + #[serde(rename = "dnsPtr")] + pub dns_ptr: u64, + #[serde(rename = "dnsRbl")] + pub dns_rbl: u64, + #[serde(rename = "dnsTlsa")] + pub dns_tlsa: u64, + #[serde(rename = "dnsTxt")] + pub dns_txt: u64, + #[serde(rename = "events")] + pub events: u64, + #[serde(rename = "scheduling")] + pub scheduling: u64, + #[serde(rename = "files")] + pub files: u64, + #[serde(rename = "httpAuth")] + pub http_auth: u64, + #[serde(rename = "messages")] + pub messages: u64, + #[serde(rename = "domains")] + pub domains: u64, + #[serde(rename = "domainNames")] + pub domain_names: u64, + #[serde(rename = "domainNamesNegative")] + pub domain_names_negative: u64, + #[serde(rename = "emailAddresses")] + pub email_addresses: u64, + #[serde(rename = "emailAddressesNegative")] + pub email_addresses_negative: u64, + #[serde(rename = "accounts")] + pub accounts: u64, + #[serde(rename = "roles")] + pub roles: u64, + #[serde(rename = "tenants")] + pub tenants: u64, + #[serde(rename = "mailingLists")] + pub mailing_lists: u64, + #[serde(rename = "dkimSignatures")] + pub dkim_signatures: u64, + #[serde(rename = "negativeTtl")] + pub negative_ttl: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Calendar { + #[serde(rename = "defaultDisplayName")] + pub default_display_name: Option, + #[serde(rename = "defaultHrefName")] + pub default_href_name: Option, + #[serde(rename = "maxAttendees")] + pub max_attendees: u64, + #[serde(rename = "maxRecurrenceExpansions")] + pub max_recurrence_expansions: u64, + #[serde(rename = "maxICalendarSize")] + pub max_i_calendar_size: u64, + #[serde(rename = "maxCalendars")] + pub max_calendars: Option, + #[serde(rename = "maxEvents")] + pub max_events: Option, + #[serde(rename = "maxParticipantIdentities")] + pub max_participant_identities: Option, + #[serde(rename = "maxEventNotifications")] + pub max_event_notifications: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CalendarAlarm { + #[serde(rename = "allowExternalRcpts")] + pub allow_external_rcpts: bool, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "fromEmail")] + pub from_email: Option, + #[serde(rename = "fromName")] + pub from_name: String, + #[serde(rename = "minTriggerInterval")] + pub min_trigger_interval: Duration, + #[serde(rename = "template")] + pub template: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CalendarScheduling { + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "httpRsvpEnable")] + pub http_rsvp_enable: bool, + #[serde(rename = "httpRsvpLinkExpiry")] + pub http_rsvp_link_expiry: Duration, + #[serde(rename = "httpRsvpUrl")] + pub http_rsvp_url: Option, + #[serde(rename = "autoAddInvitations")] + pub auto_add_invitations: bool, + #[serde(rename = "itipMaxSize")] + pub itip_max_size: u64, + #[serde(rename = "maxRecipients")] + pub max_recipients: u64, + #[serde(rename = "emailTemplate")] + pub email_template: Option, + #[serde(rename = "httpRsvpTemplate")] + pub http_rsvp_template: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Certificate { + #[serde(rename = "certificate")] + pub certificate: PublicText, + #[serde(rename = "privateKey")] + pub private_key: SecretText, + #[serde(rename = "subjectAlternativeNames")] + pub subject_alternative_names: Map, + #[serde(rename = "notValidAfter")] + pub not_valid_after: UTCDateTime, + #[serde(rename = "notValidBefore")] + pub not_valid_before: UTCDateTime, + #[serde(rename = "issuer")] + pub issuer: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum CertificateManagement { + Manual, + Automatic(CertificateManagementProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CertificateManagementProperties { + #[serde(rename = "acmeProviderId")] + pub acme_provider_id: Id, + #[serde(rename = "subjectAlternativeNames")] + pub subject_alternative_names: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum ClusterListenerGroup { + EnableAll, + DisableAll, + EnableSome(ClusterListenerGroupProperties), + DisableSome(ClusterListenerGroupProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ClusterListenerGroupProperties { + #[serde(rename = "listenerIds")] + pub listener_ids: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ClusterNode { + #[serde(rename = "nodeId")] + pub node_id: u64, + #[serde(rename = "hostname")] + pub hostname: String, + #[serde(rename = "lastRenewal")] + pub last_renewal: UTCDateTime, + #[serde(rename = "status")] + pub status: ClusterNodeStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ClusterRole { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "tasks")] + pub tasks: ClusterTaskGroup, + #[serde(rename = "listeners")] + pub listeners: ClusterListenerGroup, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum ClusterTaskGroup { + EnableAll, + DisableAll, + EnableSome(ClusterTaskGroupProperties), + DisableSome(ClusterTaskGroupProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ClusterTaskGroupProperties { + #[serde(rename = "taskTypes")] + pub task_types: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Coordinator { + Disabled, + Default, + Kafka(KafkaCoordinator), + Nats(NatsCoordinator), + Zenoh(ZenohCoordinator), + Redis(RedisStore), + RedisCluster(RedisClusterStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Credential { + Password(PasswordCredential), + AppPassword(SecondaryCredential), + ApiKey(SecondaryCredential), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum CredentialPermissions { + Inherit, + Disable(CredentialPermissionsList), + Replace(CredentialPermissionsList), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CredentialPermissionsList { + #[serde(rename = "permissions")] + pub permissions: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Cron { + Daily(CronDaily), + Weekly(CronWeekly), + Hourly(CronHourly), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CronDaily { + #[serde(rename = "hour")] + pub hour: u64, + #[serde(rename = "minute")] + pub minute: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CronHourly { + #[serde(rename = "minute")] + pub minute: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CronWeekly { + #[serde(rename = "day")] + pub day: u64, + #[serde(rename = "hour")] + pub hour: u64, + #[serde(rename = "minute")] + pub minute: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct CustomRoles { + #[serde(rename = "roleIds")] + pub role_ids: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DataRetention { + #[serde(rename = "expungeTrashAfter")] + pub expunge_trash_after: Option, + #[serde(rename = "expungeSubmissionsAfter")] + pub expunge_submissions_after: Option, + #[serde(rename = "expungeShareNotifyAfter")] + pub expunge_share_notify_after: Option, + #[serde(rename = "expungeSchedulingInboxAfter")] + pub expunge_scheduling_inbox_after: Option, + #[serde(rename = "expungeSchedule")] + pub expunge_schedule: Cron, + #[serde(rename = "dataCleanupSchedule")] + pub data_cleanup_schedule: Cron, + #[serde(rename = "blobCleanupSchedule")] + pub blob_cleanup_schedule: Cron, + #[serde(rename = "maxChangesHistory")] + pub max_changes_history: Option, + #[serde(rename = "archiveDeletedItemsFor")] + pub archive_deleted_items_for: Option, + #[serde(rename = "archiveDeletedAccountsFor")] + pub archive_deleted_accounts_for: Option, + #[serde(rename = "holdMtaReportsFor")] + pub hold_mta_reports_for: Option, + #[serde(rename = "holdTracesFor")] + pub hold_traces_for: Option, + #[serde(rename = "holdMetricsFor")] + pub hold_metrics_for: Option, + #[serde(rename = "metricsCollectionInterval")] + pub metrics_collection_interval: Cron, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DataStore { + RocksDb(RocksDbStore), + Sqlite(SqliteStore), + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DeliveryError { + #[serde(rename = "errorType")] + pub error_type: DeliveryErrorType, + #[serde(rename = "errorMessage")] + pub error_message: Option, + #[serde(rename = "errorCommand")] + pub error_command: Option, + #[serde(rename = "responseHostname")] + pub response_hostname: Option, + #[serde(rename = "responseCode")] + pub response_code: Option, + #[serde(rename = "responseEnhanced")] + pub response_enhanced: Option, + #[serde(rename = "responseMessage")] + pub response_message: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Directory { + Ldap(LdapDirectory), + Sql(SqlDirectory), + Oidc(OidcDirectory), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DirectoryBootstrap { + Internal, + Ldap(LdapDirectory), + Sql(SqlDirectory), + Oidc(OidcDirectory), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Dkim1Signature { + #[serde(rename = "auid")] + pub auid: Option, + #[serde(rename = "canonicalization")] + pub canonicalization: DkimCanonicalization, + #[serde(rename = "expire")] + pub expire: Option, + #[serde(rename = "headers")] + pub headers: Map, + #[serde(rename = "privateKey")] + pub private_key: SecretText, + #[serde(rename = "report")] + pub report: bool, + #[serde(rename = "thirdParty")] + pub third_party: Option, + #[serde(rename = "thirdPartyHash")] + pub third_party_hash: Option, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "selector")] + pub selector: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "nextTransitionAt")] + pub next_transition_at: Option, + #[serde(rename = "stage")] + pub stage: DkimRotationStage, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DkimManagement { + Automatic(DkimManagementProperties), + Manual, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DkimManagementProperties { + #[serde(rename = "algorithms")] + pub algorithms: Map, + #[serde(rename = "selectorTemplate")] + pub selector_template: String, + #[serde(rename = "rotateAfter")] + pub rotate_after: Duration, + #[serde(rename = "retireAfter")] + pub retire_after: Duration, + #[serde(rename = "deleteAfter")] + pub delete_after: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DkimReportSettings { + #[serde(rename = "fromAddress")] + pub from_address: Expression, + #[serde(rename = "fromName")] + pub from_name: Expression, + #[serde(rename = "sendFrequency")] + pub send_frequency: Expression, + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, + #[serde(rename = "subject")] + pub subject: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DkimSignature { + Dkim1Ed25519Sha256(Dkim1Signature), + Dkim1RsaSha256(Dkim1Signature), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcDkimResult { + #[serde(rename = "domain")] + pub domain: String, + #[serde(rename = "selector")] + pub selector: String, + #[serde(rename = "result")] + pub result: DkimAuthResult, + #[serde(rename = "humanResult")] + pub human_result: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcExtension { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "definition")] + pub definition: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcExternalReport { + #[serde(rename = "report")] + pub report: DmarcReport, + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "to")] + pub to: Map, + #[serde(rename = "receivedAt")] + pub received_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: UTCDateTime, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcInternalReport { + #[serde(rename = "rua")] + pub rua: Map, + #[serde(rename = "policyIdentifier")] + pub policy_identifier: u64, + #[serde(rename = "report")] + pub report: DmarcReport, + #[serde(rename = "domain")] + pub domain: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "deliverAt")] + pub deliver_at: UTCDateTime, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcPolicyOverrideReason { + #[serde(rename = "overrideType")] + pub override_type: DmarcPolicyOverride, + #[serde(rename = "comment")] + pub comment: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcReport { + #[serde(rename = "version")] + pub version: Float, + #[serde(rename = "orgName")] + pub org_name: String, + #[serde(rename = "email")] + pub email: String, + #[serde(rename = "extraContactInfo")] + pub extra_contact_info: Option, + #[serde(rename = "reportId")] + pub report_id: String, + #[serde(rename = "dateRangeBegin")] + pub date_range_begin: UTCDateTime, + #[serde(rename = "dateRangeEnd")] + pub date_range_end: UTCDateTime, + #[serde(rename = "errors")] + pub errors: Map, + #[serde(rename = "policyDomain")] + pub policy_domain: String, + #[serde(rename = "policyVersion")] + pub policy_version: Option, + #[serde(rename = "policyAdkim")] + pub policy_adkim: DmarcAlignment, + #[serde(rename = "policyAspf")] + pub policy_aspf: DmarcAlignment, + #[serde(rename = "policyDisposition")] + pub policy_disposition: DmarcDisposition, + #[serde(rename = "policySubdomainDisposition")] + pub policy_subdomain_disposition: DmarcDisposition, + #[serde(rename = "policyTestingMode")] + pub policy_testing_mode: bool, + #[serde(rename = "policyFailureReportingOptions")] + pub policy_failure_reporting_options: Map, + #[serde(rename = "records")] + pub records: List, + #[serde(rename = "extensions")] + pub extensions: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcReportRecord { + #[serde(rename = "sourceIp")] + pub source_ip: Option, + #[serde(rename = "count")] + pub count: u64, + #[serde(rename = "evaluatedDisposition")] + pub evaluated_disposition: DmarcActionDisposition, + #[serde(rename = "evaluatedDkim")] + pub evaluated_dkim: DmarcResult, + #[serde(rename = "evaluatedSpf")] + pub evaluated_spf: DmarcResult, + #[serde(rename = "policyOverrideReasons")] + pub policy_override_reasons: List, + #[serde(rename = "envelopeTo")] + pub envelope_to: Option, + #[serde(rename = "envelopeFrom")] + pub envelope_from: String, + #[serde(rename = "headerFrom")] + pub header_from: String, + #[serde(rename = "dkimResults")] + pub dkim_results: List, + #[serde(rename = "spfResults")] + pub spf_results: List, + #[serde(rename = "extensions")] + pub extensions: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcReportSettings { + #[serde(rename = "aggregateContactInfo")] + pub aggregate_contact_info: Expression, + #[serde(rename = "aggregateFromAddress")] + pub aggregate_from_address: Expression, + #[serde(rename = "aggregateFromName")] + pub aggregate_from_name: Expression, + #[serde(rename = "aggregateMaxReportSize")] + pub aggregate_max_report_size: Expression, + #[serde(rename = "aggregateOrgName")] + pub aggregate_org_name: Expression, + #[serde(rename = "aggregateSendFrequency")] + pub aggregate_send_frequency: Expression, + #[serde(rename = "aggregateDkimSignDomain")] + pub aggregate_dkim_sign_domain: Expression, + #[serde(rename = "aggregateSubject")] + pub aggregate_subject: Expression, + #[serde(rename = "failureFromAddress")] + pub failure_from_address: Expression, + #[serde(rename = "failureFromName")] + pub failure_from_name: Expression, + #[serde(rename = "failureSendFrequency")] + pub failure_send_frequency: Expression, + #[serde(rename = "failureDkimSignDomain")] + pub failure_dkim_sign_domain: Expression, + #[serde(rename = "failureSubject")] + pub failure_subject: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcSpfResult { + #[serde(rename = "domain")] + pub domain: String, + #[serde(rename = "scope")] + pub scope: SpfDomainScope, + #[serde(rename = "result")] + pub result: SpfAuthResult, + #[serde(rename = "humanResult")] + pub human_result: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcTroubleshoot { + #[serde(rename = "remoteIp")] + pub remote_ip: IpAddr, + #[serde(rename = "ehloDomain")] + pub ehlo_domain: String, + #[serde(rename = "mailFrom")] + pub mail_from: String, + #[serde(rename = "message")] + pub message: Option, + #[serde(rename = "spfEhloDomain")] + pub spf_ehlo_domain: String, + #[serde(rename = "spfEhloResult")] + pub spf_ehlo_result: DmarcTroubleshootAuthResult, + #[serde(rename = "spfMailFromDomain")] + pub spf_mail_from_domain: String, + #[serde(rename = "spfMailFromResult")] + pub spf_mail_from_result: DmarcTroubleshootAuthResult, + #[serde(rename = "ipRevResult")] + pub ip_rev_result: DmarcTroubleshootAuthResult, + #[serde(rename = "ipRevPtr")] + pub ip_rev_ptr: Map, + #[serde(rename = "dkimResults")] + pub dkim_results: List, + #[serde(rename = "dkimPass")] + pub dkim_pass: bool, + #[serde(rename = "arcResult")] + pub arc_result: DmarcTroubleshootAuthResult, + #[serde(rename = "dmarcResult")] + pub dmarc_result: DmarcTroubleshootAuthResult, + #[serde(rename = "dmarcPass")] + pub dmarc_pass: bool, + #[serde(rename = "dmarcPolicy")] + pub dmarc_policy: DmarcDisposition, + #[serde(rename = "elapsed")] + pub elapsed: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DmarcTroubleshootAuthResult { + Pass, + Fail(DmarcTroubleshootDetails), + SoftFail(DmarcTroubleshootDetails), + TempError(DmarcTroubleshootDetails), + PermError(DmarcTroubleshootDetails), + Neutral(DmarcTroubleshootDetails), + None, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DmarcTroubleshootDetails { + #[serde(rename = "details")] + pub details: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsCustomResolver { + #[serde(rename = "protocol")] + pub protocol: DnsResolverProtocol, + #[serde(rename = "address")] + pub address: IpAddr, + #[serde(rename = "port")] + pub port: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DnsManagement { + Manual, + Automatic(DnsManagementProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsManagementProperties { + #[serde(rename = "dnsServerId")] + pub dns_server_id: Id, + #[serde(rename = "origin")] + pub origin: Option, + #[serde(rename = "publishRecords")] + pub publish_records: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DnsResolver { + System(DnsResolverCommon), + Custom(DnsResolverCustom), + Cloudflare(DnsResolverTls), + Quad9(DnsResolverTls), + Google(DnsResolverCommon), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsResolverCommon { + #[serde(rename = "attempts")] + pub attempts: u64, + #[serde(rename = "concurrency")] + pub concurrency: u64, + #[serde(rename = "enableEdns")] + pub enable_edns: bool, + #[serde(rename = "preserveIntermediates")] + pub preserve_intermediates: bool, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "tcpOnError")] + pub tcp_on_error: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsResolverCustom { + #[serde(rename = "servers")] + pub servers: List, + #[serde(rename = "attempts")] + pub attempts: u64, + #[serde(rename = "concurrency")] + pub concurrency: u64, + #[serde(rename = "enableEdns")] + pub enable_edns: bool, + #[serde(rename = "preserveIntermediates")] + pub preserve_intermediates: bool, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "tcpOnError")] + pub tcp_on_error: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsResolverTls { + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "attempts")] + pub attempts: u64, + #[serde(rename = "concurrency")] + pub concurrency: u64, + #[serde(rename = "enableEdns")] + pub enable_edns: bool, + #[serde(rename = "preserveIntermediates")] + pub preserve_intermediates: bool, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "tcpOnError")] + pub tcp_on_error: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DnsServer { + Tsig(DnsServerTsig), + Sig0(DnsServerSig0), + Cloudflare(DnsServerCloudflare), + DigitalOcean(DnsServerCloud), + DeSEC(DnsServerCloud), + Ovh(DnsServerOvh), + Bunny(DnsServerCloud), + Porkbun(DnsServerPorkbun), + Dnsimple(DnsServerDnsimple), + Spaceship(DnsServerSpaceship), + Route53(DnsServerRoute53), + GoogleCloudDns(DnsServerGoogleCloudDns), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum DnsServerBootstrap { + Manual, + Tsig(DnsServerTsig), + Sig0(DnsServerSig0), + Cloudflare(DnsServerCloudflare), + DigitalOcean(DnsServerCloud), + DeSEC(DnsServerCloud), + Ovh(DnsServerOvh), + Bunny(DnsServerCloud), + Porkbun(DnsServerPorkbun), + Dnsimple(DnsServerDnsimple), + Spaceship(DnsServerSpaceship), + Route53(DnsServerRoute53), + GoogleCloudDns(DnsServerGoogleCloudDns), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerCloud { + #[serde(rename = "secret")] + pub secret: SecretKey, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerCloudflare { + #[serde(rename = "email")] + pub email: Option, + #[serde(rename = "secret")] + pub secret: SecretKey, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerDnsimple { + #[serde(rename = "authToken")] + pub auth_token: SecretKey, + #[serde(rename = "accountIdentifier")] + pub account_identifier: String, + #[serde(rename = "secret")] + pub secret: SecretKey, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerGoogleCloudDns { + #[serde(rename = "serviceAccountJson")] + pub service_account_json: SecretText, + #[serde(rename = "projectId")] + pub project_id: String, + #[serde(rename = "managedZone")] + pub managed_zone: Option, + #[serde(rename = "privateZone")] + pub private_zone: bool, + #[serde(rename = "impersonateServiceAccount")] + pub impersonate_service_account: Option, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerOvh { + #[serde(rename = "applicationKey")] + pub application_key: String, + #[serde(rename = "applicationSecret")] + pub application_secret: SecretKey, + #[serde(rename = "consumerKey")] + pub consumer_key: SecretKey, + #[serde(rename = "ovhEndpoint")] + pub ovh_endpoint: OvhEndpoint, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerPorkbun { + #[serde(rename = "apiKey")] + pub api_key: String, + #[serde(rename = "secretApiKey")] + pub secret_api_key: SecretKey, + #[serde(rename = "secret")] + pub secret: SecretKey, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerRoute53 { + #[serde(rename = "accessKeyId")] + pub access_key_id: String, + #[serde(rename = "secretAccessKey")] + pub secret_access_key: SecretKey, + #[serde(rename = "sessionToken")] + pub session_token: SecretKeyOptional, + #[serde(rename = "region")] + pub region: String, + #[serde(rename = "hostedZoneId")] + pub hosted_zone_id: Option, + #[serde(rename = "privateZoneOnly")] + pub private_zone_only: bool, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerSig0 { + #[serde(rename = "host")] + pub host: IpAddr, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "publicKey")] + pub public_key: String, + #[serde(rename = "key")] + pub key: SecretText, + #[serde(rename = "signerName")] + pub signer_name: String, + #[serde(rename = "protocol")] + pub protocol: IpProtocol, + #[serde(rename = "sig0Algorithm")] + pub sig0_algorithm: Sig0Algorithm, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerSpaceship { + #[serde(rename = "apiKey")] + pub api_key: String, + #[serde(rename = "secret")] + pub secret: SecretKey, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DnsServerTsig { + #[serde(rename = "host")] + pub host: IpAddr, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "keyName")] + pub key_name: String, + #[serde(rename = "key")] + pub key: SecretKey, + #[serde(rename = "protocol")] + pub protocol: IpProtocol, + #[serde(rename = "tsigAlgorithm")] + pub tsig_algorithm: TsigAlgorithm, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "ttl")] + pub ttl: Duration, + #[serde(rename = "pollingInterval")] + pub polling_interval: Duration, + #[serde(rename = "propagationTimeout")] + pub propagation_timeout: Duration, + #[serde(rename = "propagationDelay")] + pub propagation_delay: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Domain { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "aliases")] + pub aliases: Map, + #[serde(rename = "isEnabled")] + pub is_enabled: bool, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "logo")] + pub logo: Option, + #[serde(rename = "certificateManagement")] + pub certificate_management: CertificateManagement, + #[serde(rename = "dkimManagement")] + pub dkim_management: DkimManagement, + #[serde(rename = "dnsManagement")] + pub dns_management: DnsManagement, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "directoryId")] + pub directory_id: Option, + #[serde(rename = "catchAllAddress")] + pub catch_all_address: Option, + #[serde(rename = "subAddressing")] + pub sub_addressing: SubAddressing, + #[serde(rename = "allowRelaying")] + pub allow_relaying: bool, + #[serde(rename = "reportAddressUri")] + pub report_address_uri: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct DsnReportSettings { + #[serde(rename = "fromAddress")] + pub from_address: Expression, + #[serde(rename = "fromName")] + pub from_name: Expression, + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ElasticSearchStore { + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "numReplicas")] + pub num_replicas: u64, + #[serde(rename = "numShards")] + pub num_shards: u64, + #[serde(rename = "includeSource")] + pub include_source: bool, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Email { + #[serde(rename = "maxAttachmentSize")] + pub max_attachment_size: u64, + #[serde(rename = "maxMessageSize")] + pub max_message_size: u64, + #[serde(rename = "maxMailboxDepth")] + pub max_mailbox_depth: u64, + #[serde(rename = "maxMailboxNameLength")] + pub max_mailbox_name_length: u64, + #[serde(rename = "encryptOnAppend")] + pub encrypt_on_append: bool, + #[serde(rename = "encryptAtRest")] + pub encrypt_at_rest: bool, + #[serde(rename = "compressionAlgorithm")] + pub compression_algorithm: CompressionAlgo, + #[serde(rename = "defaultFolders")] + pub default_folders: VecMap, + #[serde(rename = "maxMessages")] + pub max_messages: Option, + #[serde(rename = "maxSubmissions")] + pub max_submissions: Option, + #[serde(rename = "maxIdentities")] + pub max_identities: Option, + #[serde(rename = "maxMailboxes")] + pub max_mailboxes: Option, + #[serde(rename = "maxMaskedAddresses")] + pub max_masked_addresses: Option, + #[serde(rename = "maxPublicKeys")] + pub max_public_keys: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct EmailAlias { + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "description")] + pub description: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct EmailFolder { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "create")] + pub create: bool, + #[serde(rename = "subscribe")] + pub subscribe: bool, + #[serde(rename = "aliases")] + pub aliases: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum EncryptionAtRest { + Disabled, + Aes128(EncryptionSettings), + Aes256(EncryptionSettings), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct EncryptionSettings { + #[serde(rename = "publicKey")] + pub public_key: Id, + #[serde(rename = "encryptOnAppend")] + pub encrypt_on_append: bool, + #[serde(rename = "allowSpamTraining")] + pub allow_spam_training: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Enterprise { + #[serde(rename = "apiKey")] + pub api_key: SecretKeyOptional, + #[serde(rename = "licenseKey")] + pub license_key: SecretKeyOptional, + #[serde(rename = "logoUrl")] + pub logo_url: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct EventTracingLevel { + #[serde(rename = "event")] + pub event: trc::EventType, + #[serde(rename = "level")] + pub level: TracingLevelOpt, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Expression { + #[serde(rename = "match")] + pub match_: List, + #[serde(rename = "else")] + pub else_: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ExpressionMatch { + #[serde(rename = "if")] + pub if_: String, + #[serde(rename = "then")] + pub then: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct FileStorage { + #[serde(rename = "maxSize")] + pub max_size: u64, + #[serde(rename = "maxFiles")] + pub max_files: Option, + #[serde(rename = "maxFolders")] + pub max_folders: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct FileSystemStore { + #[serde(rename = "path")] + pub path: String, + #[serde(rename = "depth")] + pub depth: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct FoundationDbStore { + #[serde(rename = "clusterFile")] + pub cluster_file: Option, + #[serde(rename = "datacenterId")] + pub datacenter_id: Option, + #[serde(rename = "machineId")] + pub machine_id: Option, + #[serde(rename = "transactionRetryDelay")] + pub transaction_retry_delay: Option, + #[serde(rename = "transactionRetryLimit")] + pub transaction_retry_limit: Option, + #[serde(rename = "transactionTimeout")] + pub transaction_timeout: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct FtrlParameters { + #[serde(rename = "alpha")] + pub alpha: Float, + #[serde(rename = "beta")] + pub beta: Float, + #[serde(rename = "numFeatures")] + pub num_features: ModelSize, + #[serde(rename = "l1Ratio")] + pub l1_ratio: Float, + #[serde(rename = "l2Ratio")] + pub l2_ratio: Float, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct GroupAccount { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "roles")] + pub roles: Roles, + #[serde(rename = "quotas")] + pub quotas: VecMap, + #[serde(rename = "permissions")] + pub permissions: Permissions, + #[serde(rename = "aliases")] + pub aliases: List, + #[serde(rename = "locale")] + pub locale: Locale, + #[serde(rename = "timeZone")] + pub time_zone: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Http { + #[serde(rename = "rateLimitAuthenticated")] + pub rate_limit_authenticated: Option, + #[serde(rename = "rateLimitAnonymous")] + pub rate_limit_anonymous: Option, + #[serde(rename = "allowedEndpoints")] + pub allowed_endpoints: Expression, + #[serde(rename = "enableHsts")] + pub enable_hsts: bool, + #[serde(rename = "usePermissiveCors")] + pub use_permissive_cors: bool, + #[serde(rename = "responseHeaders")] + pub response_headers: VecMap, + #[serde(rename = "useXForwarded")] + pub use_x_forwarded: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum HttpAuth { + Unauthenticated, + Basic(HttpAuthBasic), + Bearer(HttpAuthBearer), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct HttpAuthBasic { + #[serde(rename = "username")] + pub username: String, + #[serde(rename = "secret")] + pub secret: SecretKey, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct HttpAuthBearer { + #[serde(rename = "bearerToken")] + pub bearer_token: SecretKey, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct HttpForm { + #[serde(rename = "deliverTo")] + pub deliver_to: Map, + #[serde(rename = "defaultFromAddress")] + pub default_from_address: String, + #[serde(rename = "fieldEmail")] + pub field_email: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "fieldHoneyPot")] + pub field_honey_pot: Option, + #[serde(rename = "maxSize")] + pub max_size: u64, + #[serde(rename = "defaultName")] + pub default_name: String, + #[serde(rename = "fieldName")] + pub field_name: Option, + #[serde(rename = "rateLimit")] + pub rate_limit: Option, + #[serde(rename = "defaultSubject")] + pub default_subject: String, + #[serde(rename = "fieldSubject")] + pub field_subject: Option, + #[serde(rename = "validateDomain")] + pub validate_domain: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct HttpLookup { + #[serde(rename = "namespace")] + pub namespace: String, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "format")] + pub format: HttpLookupFormat, + #[serde(rename = "isGzipped")] + pub is_gzipped: bool, + #[serde(rename = "maxEntries")] + pub max_entries: u64, + #[serde(rename = "maxEntrySize")] + pub max_entry_size: u64, + #[serde(rename = "maxSize")] + pub max_size: u64, + #[serde(rename = "refresh")] + pub refresh: Duration, + #[serde(rename = "retry")] + pub retry: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "url")] + pub url: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct HttpLookupCsv { + #[serde(rename = "indexKey")] + pub index_key: u64, + #[serde(rename = "indexValue")] + pub index_value: Option, + #[serde(rename = "separator")] + pub separator: String, + #[serde(rename = "skipFirst")] + pub skip_first: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum HttpLookupFormat { + Csv(HttpLookupCsv), + List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Imap { + #[serde(rename = "allowPlainTextAuth")] + pub allow_plain_text_auth: bool, + #[serde(rename = "maxAuthFailures")] + pub max_auth_failures: u64, + #[serde(rename = "maxConcurrent")] + pub max_concurrent: Option, + #[serde(rename = "maxRequestRate")] + pub max_request_rate: Option, + #[serde(rename = "maxRequestSize")] + pub max_request_size: u64, + #[serde(rename = "timeoutAnonymous")] + pub timeout_anonymous: Duration, + #[serde(rename = "timeoutAuthenticated")] + pub timeout_authenticated: Duration, + #[serde(rename = "timeoutIdle")] + pub timeout_idle: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum InMemoryStore { + Default, + Sharded(ShardedInMemoryStore), + Redis(RedisStore), + RedisCluster(RedisClusterStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum InMemoryStoreBase { + Redis(RedisStore), + RedisCluster(RedisClusterStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Jmap { + #[serde(rename = "parseLimitEvent")] + pub parse_limit_event: u64, + #[serde(rename = "parseLimitContact")] + pub parse_limit_contact: u64, + #[serde(rename = "parseLimitEmail")] + pub parse_limit_email: u64, + #[serde(rename = "changesMaxResults")] + pub changes_max_results: u64, + #[serde(rename = "getMaxResults")] + pub get_max_results: u64, + #[serde(rename = "queryMaxResults")] + pub query_max_results: u64, + #[serde(rename = "maxMethodCalls")] + pub max_method_calls: u64, + #[serde(rename = "maxConcurrentRequests")] + pub max_concurrent_requests: Option, + #[serde(rename = "maxRequestSize")] + pub max_request_size: u64, + #[serde(rename = "setMaxObjects")] + pub set_max_objects: u64, + #[serde(rename = "snippetMaxResults")] + pub snippet_max_results: u64, + #[serde(rename = "maxConcurrentUploads")] + pub max_concurrent_uploads: Option, + #[serde(rename = "maxUploadSize")] + pub max_upload_size: u64, + #[serde(rename = "maxUploadCount")] + pub max_upload_count: u64, + #[serde(rename = "uploadQuota")] + pub upload_quota: u64, + #[serde(rename = "uploadTtl")] + pub upload_ttl: Duration, + #[serde(rename = "eventSourceThrottle")] + pub event_source_throttle: Duration, + #[serde(rename = "pushAttemptWait")] + pub push_attempt_wait: Duration, + #[serde(rename = "pushMaxAttempts")] + pub push_max_attempts: u64, + #[serde(rename = "pushRetryWait")] + pub push_retry_wait: Duration, + #[serde(rename = "pushThrottle")] + pub push_throttle: Duration, + #[serde(rename = "pushRequestTimeout")] + pub push_request_timeout: Duration, + #[serde(rename = "pushVerifyTimeout")] + pub push_verify_timeout: Duration, + #[serde(rename = "pushShardsTotal")] + pub push_shards_total: u64, + #[serde(rename = "websocketHeartbeat")] + pub websocket_heartbeat: Duration, + #[serde(rename = "websocketThrottle")] + pub websocket_throttle: Duration, + #[serde(rename = "websocketTimeout")] + pub websocket_timeout: Duration, + #[serde(rename = "maxSubscriptions")] + pub max_subscriptions: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct KafkaCoordinator { + #[serde(rename = "brokers")] + pub brokers: Map, + #[serde(rename = "groupId")] + pub group_id: String, + #[serde(rename = "timeoutMessage")] + pub timeout_message: Duration, + #[serde(rename = "timeoutSession")] + pub timeout_session: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct LdapDirectory { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "baseDn")] + pub base_dn: String, + #[serde(rename = "bindDn")] + pub bind_dn: Option, + #[serde(rename = "bindSecret")] + pub bind_secret: SecretKeyOptional, + #[serde(rename = "bindAuthentication")] + pub bind_authentication: bool, + #[serde(rename = "filterLogin")] + pub filter_login: String, + #[serde(rename = "filterMailbox")] + pub filter_mailbox: String, + #[serde(rename = "filterMemberOf")] + pub filter_member_of: Option, + #[serde(rename = "attrClass")] + pub attr_class: Map, + #[serde(rename = "attrDescription")] + pub attr_description: Map, + #[serde(rename = "attrEmail")] + pub attr_email: Map, + #[serde(rename = "attrEmailAlias")] + pub attr_email_alias: Map, + #[serde(rename = "attrMemberOf")] + pub attr_member_of: Map, + #[serde(rename = "attrSecret")] + pub attr_secret: Map, + #[serde(rename = "attrSecretChanged")] + pub attr_secret_changed: Map, + #[serde(rename = "groupClass")] + pub group_class: String, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: u64, + #[serde(rename = "poolTimeoutCreate")] + pub pool_timeout_create: Duration, + #[serde(rename = "poolTimeoutRecycle")] + pub pool_timeout_recycle: Duration, + #[serde(rename = "poolTimeoutWait")] + pub pool_timeout_wait: Duration, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Log { + #[serde(rename = "timestamp")] + pub timestamp: UTCDateTime, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "event")] + pub event: trc::EventType, + #[serde(rename = "details")] + pub details: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum LookupStore { + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), + Sqlite(SqliteStore), + Sharded(ShardedInMemoryStore), + Redis(RedisStore), + RedisCluster(RedisClusterStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MailExchanger { + #[serde(rename = "hostname")] + pub hostname: Option, + #[serde(rename = "priority")] + pub priority: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MailingList { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "aliases")] + pub aliases: List, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "recipients")] + pub recipients: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MaskedEmail { + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "email")] + pub email: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "forDomain")] + pub for_domain: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "createdBy")] + pub created_by: Option, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "url")] + pub url: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MeilisearchStore { + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "pollInterval")] + pub poll_interval: Duration, + #[serde(rename = "maxRetries")] + pub max_retries: u64, + #[serde(rename = "failOnTimeout")] + pub fail_on_timeout: bool, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MemoryLookupKey { + #[serde(rename = "namespace")] + pub namespace: String, + #[serde(rename = "key")] + pub key: String, + #[serde(rename = "isGlobPattern")] + pub is_glob_pattern: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MemoryLookupKeyValue { + #[serde(rename = "namespace")] + pub namespace: String, + #[serde(rename = "key")] + pub key: String, + #[serde(rename = "value")] + pub value: String, + #[serde(rename = "isGlobPattern")] + pub is_glob_pattern: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Metric { + Counter(MetricCount), + Gauge(MetricCount), + Histogram(MetricSum), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MetricCount { + #[serde(rename = "count")] + pub count: u64, + #[serde(rename = "metric")] + pub metric: trc::MetricType, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MetricSum { + #[serde(rename = "count")] + pub count: u64, + #[serde(rename = "sum")] + pub sum: u64, + #[serde(rename = "metric")] + pub metric: trc::MetricType, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Metrics { + #[serde(rename = "openTelemetry")] + pub open_telemetry: MetricsOtel, + #[serde(rename = "prometheus")] + pub prometheus: MetricsPrometheus, + #[serde(rename = "metrics")] + pub metrics: Map, + #[serde(rename = "metricsPolicy")] + pub metrics_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MetricsOtel { + Disabled, + Http(MetricsOtelHttp), + Grpc(MetricsOtelGrpc), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MetricsOtelGrpc { + #[serde(rename = "endpoint")] + pub endpoint: Option, + #[serde(rename = "interval")] + pub interval: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MetricsOtelHttp { + #[serde(rename = "endpoint")] + pub endpoint: String, + #[serde(rename = "interval")] + pub interval: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MetricsPrometheus { + Disabled, + Enabled(MetricsPrometheusProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MetricsPrometheusProperties { + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "authUsername")] + pub auth_username: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MetricsStore { + Disabled, + Default, + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaConnectionIpHost { + #[serde(rename = "ehloHostname")] + pub ehlo_hostname: Option, + #[serde(rename = "sourceIp")] + pub source_ip: IpAddr, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaConnectionStrategy { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "ehloHostname")] + pub ehlo_hostname: Option, + #[serde(rename = "sourceIps")] + pub source_ips: List, + #[serde(rename = "connectTimeout")] + pub connect_timeout: Duration, + #[serde(rename = "dataTimeout")] + pub data_timeout: Duration, + #[serde(rename = "ehloTimeout")] + pub ehlo_timeout: Duration, + #[serde(rename = "greetingTimeout")] + pub greeting_timeout: Duration, + #[serde(rename = "mailFromTimeout")] + pub mail_from_timeout: Duration, + #[serde(rename = "rcptToTimeout")] + pub rcpt_to_timeout: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MtaDeliveryExpiration { + Ttl(MtaDeliveryExpirationTtl), + Attempts(MtaDeliveryExpirationAttempts), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaDeliveryExpirationAttempts { + #[serde(rename = "maxAttempts")] + pub max_attempts: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaDeliveryExpirationTtl { + #[serde(rename = "expire")] + pub expire: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaDeliverySchedule { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "expiry")] + pub expiry: MtaDeliveryExpiration, + #[serde(rename = "notify")] + pub notify: MtaDeliveryScheduleIntervalsOrDefault, + #[serde(rename = "queueId")] + pub queue_id: Id, + #[serde(rename = "retry")] + pub retry: MtaDeliveryScheduleIntervalsOrDefault, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaDeliveryScheduleInterval { + #[serde(rename = "duration")] + pub duration: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaDeliveryScheduleIntervals { + #[serde(rename = "intervals")] + pub intervals: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MtaDeliveryScheduleIntervalsOrDefault { + Default, + Custom(MtaDeliveryScheduleIntervals), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaExtensions { + #[serde(rename = "chunking")] + pub chunking: Expression, + #[serde(rename = "deliverBy")] + pub deliver_by: Expression, + #[serde(rename = "dsn")] + pub dsn: Expression, + #[serde(rename = "expn")] + pub expn: Expression, + #[serde(rename = "futureRelease")] + pub future_release: Expression, + #[serde(rename = "mtPriority")] + pub mt_priority: Expression, + #[serde(rename = "noSoliciting")] + pub no_soliciting: Expression, + #[serde(rename = "pipelining")] + pub pipelining: Expression, + #[serde(rename = "requireTls")] + pub require_tls: Expression, + #[serde(rename = "vrfy")] + pub vrfy: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaHook { + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "enable")] + pub enable: Expression, + #[serde(rename = "maxResponseSize")] + pub max_response_size: u64, + #[serde(rename = "tempFailOnError")] + pub temp_fail_on_error: bool, + #[serde(rename = "stages")] + pub stages: Map, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaInboundSession { + #[serde(rename = "maxDuration")] + pub max_duration: Expression, + #[serde(rename = "timeout")] + pub timeout: Expression, + #[serde(rename = "transferLimit")] + pub transfer_limit: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaInboundThrottle { + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "key")] + pub key: Map, + #[serde(rename = "match")] + pub match_: Expression, + #[serde(rename = "rate")] + pub rate: Rate, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaMilter { + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "enable")] + pub enable: Expression, + #[serde(rename = "hostname")] + pub hostname: String, + #[serde(rename = "maxResponseSize")] + pub max_response_size: u64, + #[serde(rename = "tempFailOnError")] + pub temp_fail_on_error: bool, + #[serde(rename = "protocolVersion")] + pub protocol_version: MilterVersion, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "stages")] + pub stages: Map, + #[serde(rename = "timeoutCommand")] + pub timeout_command: Duration, + #[serde(rename = "timeoutConnect")] + pub timeout_connect: Duration, + #[serde(rename = "timeoutData")] + pub timeout_data: Duration, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "flagsAction")] + pub flags_action: Option, + #[serde(rename = "flagsProtocol")] + pub flags_protocol: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaOutboundStrategy { + #[serde(rename = "connection")] + pub connection: Expression, + #[serde(rename = "route")] + pub route: Expression, + #[serde(rename = "schedule")] + pub schedule: Expression, + #[serde(rename = "tls")] + pub tls: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaOutboundThrottle { + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "key")] + pub key: Map, + #[serde(rename = "match")] + pub match_: Expression, + #[serde(rename = "rate")] + pub rate: Rate, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaQueueQuota { + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "key")] + pub key: Map, + #[serde(rename = "match")] + pub match_: Expression, + #[serde(rename = "messages")] + pub messages: Option, + #[serde(rename = "size")] + pub size: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum MtaRoute { + Mx(MtaRouteMx), + Relay(MtaRouteRelay), + Local(MtaRouteCommon), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaRouteCommon { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaRouteMx { + #[serde(rename = "ipLookupStrategy")] + pub ip_lookup_strategy: MtaIpStrategy, + #[serde(rename = "maxMultihomed")] + pub max_multihomed: u64, + #[serde(rename = "maxMxHosts")] + pub max_mx_hosts: u64, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaRouteRelay { + #[serde(rename = "address")] + pub address: String, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "protocol")] + pub protocol: MtaProtocol, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "implicitTls")] + pub implicit_tls: bool, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageAuth { + #[serde(rename = "maxFailures")] + pub max_failures: Expression, + #[serde(rename = "waitOnFail")] + pub wait_on_fail: Expression, + #[serde(rename = "saslMechanisms")] + pub sasl_mechanisms: Expression, + #[serde(rename = "mustMatchSender")] + pub must_match_sender: Expression, + #[serde(rename = "require")] + pub require: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageConnect { + #[serde(rename = "smtpGreeting")] + pub smtp_greeting: Expression, + #[serde(rename = "hostname")] + pub hostname: Expression, + #[serde(rename = "script")] + pub script: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageData { + #[serde(rename = "addAuthResultsHeader")] + pub add_auth_results_header: Expression, + #[serde(rename = "addDateHeader")] + pub add_date_header: Expression, + #[serde(rename = "addDeliveredToHeader")] + pub add_delivered_to_header: bool, + #[serde(rename = "addMessageIdHeader")] + pub add_message_id_header: Expression, + #[serde(rename = "addReceivedHeader")] + pub add_received_header: Expression, + #[serde(rename = "addReceivedSpfHeader")] + pub add_received_spf_header: Expression, + #[serde(rename = "addReturnPathHeader")] + pub add_return_path_header: Expression, + #[serde(rename = "maxMessages")] + pub max_messages: Expression, + #[serde(rename = "maxReceivedHeaders")] + pub max_received_headers: Expression, + #[serde(rename = "maxMessageSize")] + pub max_message_size: Expression, + #[serde(rename = "script")] + pub script: Expression, + #[serde(rename = "enableSpamFilter")] + pub enable_spam_filter: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageEhlo { + #[serde(rename = "rejectNonFqdn")] + pub reject_non_fqdn: Expression, + #[serde(rename = "require")] + pub require: Expression, + #[serde(rename = "script")] + pub script: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageMail { + #[serde(rename = "isSenderAllowed")] + pub is_sender_allowed: Expression, + #[serde(rename = "rewrite")] + pub rewrite: Expression, + #[serde(rename = "script")] + pub script: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaStageRcpt { + #[serde(rename = "maxFailures")] + pub max_failures: Expression, + #[serde(rename = "waitOnFail")] + pub wait_on_fail: Expression, + #[serde(rename = "maxRecipients")] + pub max_recipients: Expression, + #[serde(rename = "allowRelaying")] + pub allow_relaying: Expression, + #[serde(rename = "rewrite")] + pub rewrite: Expression, + #[serde(rename = "script")] + pub script: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaSts { + #[serde(rename = "maxAge")] + pub max_age: Duration, + #[serde(rename = "mode")] + pub mode: PolicyEnforcement, + #[serde(rename = "mxHosts")] + pub mx_hosts: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaTlsStrategy { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "dane")] + pub dane: MtaRequiredOrOptional, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "mtaSts")] + pub mta_sts: MtaRequiredOrOptional, + #[serde(rename = "startTls")] + pub start_tls: MtaRequiredOrOptional, + #[serde(rename = "mtaStsTimeout")] + pub mta_sts_timeout: Duration, + #[serde(rename = "tlsTimeout")] + pub tls_timeout: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MtaVirtualQueue { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "threadsPerNode")] + pub threads_per_node: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MySqlSettings { + #[serde(rename = "host")] + pub host: String, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "database")] + pub database: String, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct MySqlStore { + #[serde(rename = "timeout")] + pub timeout: Option, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "maxAllowedPacket")] + pub max_allowed_packet: Option, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: Option, + #[serde(rename = "poolMinConnections")] + pub pool_min_connections: Option, + #[serde(rename = "readReplicas")] + pub read_replicas: List, + #[serde(rename = "host")] + pub host: String, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "database")] + pub database: String, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct NatsCoordinator { + #[serde(rename = "addresses")] + pub addresses: Map, + #[serde(rename = "maxReconnects")] + pub max_reconnects: Option, + #[serde(rename = "timeoutConnection")] + pub timeout_connection: Duration, + #[serde(rename = "timeoutRequest")] + pub timeout_request: Duration, + #[serde(rename = "pingInterval")] + pub ping_interval: Duration, + #[serde(rename = "capacityClient")] + pub capacity_client: u64, + #[serde(rename = "capacityReadBuffer")] + pub capacity_read_buffer: u64, + #[serde(rename = "capacitySubscription")] + pub capacity_subscription: u64, + #[serde(rename = "noEcho")] + pub no_echo: bool, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "credentials")] + pub credentials: SecretTextOptional, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct NetworkListener { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "bind")] + pub bind: Map, + #[serde(rename = "protocol")] + pub protocol: NetworkListenerProtocol, + #[serde(rename = "overrideProxyTrustedNetworks")] + pub override_proxy_trusted_networks: Map, + #[serde(rename = "socketBacklog")] + pub socket_backlog: Option, + #[serde(rename = "socketNoDelay")] + pub socket_no_delay: bool, + #[serde(rename = "socketReceiveBufferSize")] + pub socket_receive_buffer_size: Option, + #[serde(rename = "socketReuseAddress")] + pub socket_reuse_address: bool, + #[serde(rename = "socketReusePort")] + pub socket_reuse_port: bool, + #[serde(rename = "socketSendBufferSize")] + pub socket_send_buffer_size: Option, + #[serde(rename = "socketTosV4")] + pub socket_tos_v4: Option, + #[serde(rename = "socketTtl")] + pub socket_ttl: Option, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "tlsDisableCipherSuites")] + pub tls_disable_cipher_suites: Map, + #[serde(rename = "tlsDisableProtocols")] + pub tls_disable_protocols: Map, + #[serde(rename = "tlsIgnoreClientOrder")] + pub tls_ignore_client_order: bool, + #[serde(rename = "tlsImplicit")] + pub tls_implicit: bool, + #[serde(rename = "tlsTimeout")] + pub tls_timeout: Option, + #[serde(rename = "maxConnections")] + pub max_connections: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct OAuthClient { + #[serde(rename = "clientId")] + pub client_id: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "contacts")] + pub contacts: Map, + #[serde(rename = "secret")] + pub secret: Option, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "redirectUris")] + pub redirect_uris: Map, + #[serde(rename = "logo")] + pub logo: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct OidcDirectory { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "issuerUrl")] + pub issuer_url: String, + #[serde(rename = "requireAudience")] + pub require_audience: Option, + #[serde(rename = "requireScopes")] + pub require_scopes: Map, + #[serde(rename = "claimUsername")] + pub claim_username: String, + #[serde(rename = "usernameDomain")] + pub username_domain: Option, + #[serde(rename = "claimName")] + pub claim_name: Option, + #[serde(rename = "claimGroups")] + pub claim_groups: Option, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct OidcProvider { + #[serde(rename = "authCodeMaxAttempts")] + pub auth_code_max_attempts: u64, + #[serde(rename = "anonymousClientRegistration")] + pub anonymous_client_registration: bool, + #[serde(rename = "requireClientRegistration")] + pub require_client_registration: bool, + #[serde(rename = "authCodeExpiry")] + pub auth_code_expiry: Duration, + #[serde(rename = "refreshTokenExpiry")] + pub refresh_token_expiry: Duration, + #[serde(rename = "refreshTokenRenewal")] + pub refresh_token_renewal: Duration, + #[serde(rename = "accessTokenExpiry")] + pub access_token_expiry: Duration, + #[serde(rename = "userCodeExpiry")] + pub user_code_expiry: Duration, + #[serde(rename = "idTokenExpiry")] + pub id_token_expiry: Duration, + #[serde(rename = "encryptionKey")] + pub encryption_key: SecretKey, + #[serde(rename = "signatureAlgorithm")] + pub signature_algorithm: JwtSignatureAlgorithm, + #[serde(rename = "signatureKey")] + pub signature_key: SecretText, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct OtpAuth { + #[serde(rename = "otpCode")] + pub otp_code: Option, + #[serde(rename = "otpUrl")] + pub otp_url: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PasswordCredential { + #[serde(rename = "credentialId")] + pub credential_id: Id, + #[serde(rename = "secret")] + pub secret: String, + #[serde(rename = "otpAuth")] + pub otp_auth: Option, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "allowedIps")] + pub allowed_ips: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Permissions { + Inherit, + Merge(PermissionsList), + Replace(PermissionsList), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PermissionsList { + #[serde(rename = "enabledPermissions")] + pub enabled_permissions: Map, + #[serde(rename = "disabledPermissions")] + pub disabled_permissions: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PostgreSqlSettings { + #[serde(rename = "host")] + pub host: String, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "database")] + pub database: String, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "options")] + pub options: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PostgreSqlStore { + #[serde(rename = "timeout")] + pub timeout: Option, + #[serde(rename = "useTls")] + pub use_tls: bool, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: Option, + #[serde(rename = "poolRecyclingMethod")] + pub pool_recycling_method: PostgreSqlRecyclingMethod, + #[serde(rename = "readReplicas")] + pub read_replicas: List, + #[serde(rename = "host")] + pub host: String, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "database")] + pub database: String, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "options")] + pub options: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PublicKey { + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "key")] + pub key: String, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "emailAddresses")] + pub email_addresses: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum PublicText { + Text(PublicTextValue), + EnvironmentVariable(SecretKeyEnvironmentVariable), + File(SecretKeyFile), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct PublicTextValue { + #[serde(rename = "value")] + pub value: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum QueueExpiry { + Ttl(QueueExpiryTtl), + Attempts(QueueExpiryAttempts), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct QueueExpiryAttempts { + #[serde(rename = "expiresAttempts")] + pub expires_attempts: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct QueueExpiryTtl { + #[serde(rename = "expiresAt")] + pub expires_at: UTCDateTime, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct QueuedMessage { + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "nextRetry")] + pub next_retry: Option, + #[serde(rename = "nextNotify")] + pub next_notify: Option, + #[serde(rename = "blobId")] + pub blob_id: BlobId, + #[serde(rename = "returnPath")] + pub return_path: String, + #[serde(rename = "recipients")] + pub recipients: VecMap, + #[serde(rename = "receivedFromIp")] + pub received_from_ip: IpAddr, + #[serde(rename = "receivedViaPort")] + pub received_via_port: u64, + #[serde(rename = "flags")] + pub flags: Map, + #[serde(rename = "envId")] + pub env_id: Option, + #[serde(rename = "priority")] + pub priority: i64, + #[serde(rename = "size")] + pub size: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct QueuedRecipient { + #[serde(rename = "retryCount")] + pub retry_count: u64, + #[serde(rename = "retryDue")] + pub retry_due: UTCDateTime, + #[serde(rename = "notifyCount")] + pub notify_count: u64, + #[serde(rename = "notifyDue")] + pub notify_due: UTCDateTime, + #[serde(rename = "expires")] + pub expires: QueueExpiry, + #[serde(rename = "queueName")] + pub queue_name: String, + #[serde(rename = "status")] + pub status: RecipientStatus, + #[serde(rename = "flags")] + pub flags: Map, + #[serde(rename = "orcpt")] + pub orcpt: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Rate { + #[serde(rename = "count")] + pub count: u64, + #[serde(rename = "period")] + pub period: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum RecipientStatus { + Scheduled, + Completed(ServerResponse), + TemporaryFailure(DeliveryError), + PermanentFailure(DeliveryError), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct RedisClusterStore { + #[serde(rename = "urls")] + pub urls: Map, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "authUsername")] + pub auth_username: Option, + #[serde(rename = "authSecret")] + pub auth_secret: SecretKeyOptional, + #[serde(rename = "maxRetryWait")] + pub max_retry_wait: Option, + #[serde(rename = "minRetryWait")] + pub min_retry_wait: Option, + #[serde(rename = "maxRetries")] + pub max_retries: Option, + #[serde(rename = "readFromReplicas")] + pub read_from_replicas: bool, + #[serde(rename = "protocolVersion")] + pub protocol_version: RedisProtocol, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: u64, + #[serde(rename = "poolTimeoutCreate")] + pub pool_timeout_create: Option, + #[serde(rename = "poolTimeoutWait")] + pub pool_timeout_wait: Option, + #[serde(rename = "poolTimeoutRecycle")] + pub pool_timeout_recycle: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct RedisStore { + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: u64, + #[serde(rename = "poolTimeoutCreate")] + pub pool_timeout_create: Option, + #[serde(rename = "poolTimeoutWait")] + pub pool_timeout_wait: Option, + #[serde(rename = "poolTimeoutRecycle")] + pub pool_timeout_recycle: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ReportSettings { + #[serde(rename = "inboundReportAddresses")] + pub inbound_report_addresses: Map, + #[serde(rename = "inboundReportForwarding")] + pub inbound_report_forwarding: bool, + #[serde(rename = "outboundReportDomain")] + pub outbound_report_domain: Option, + #[serde(rename = "outboundReportSubmitter")] + pub outbound_report_submitter: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct RocksDbStore { + #[serde(rename = "path")] + pub path: String, + #[serde(rename = "blobSize")] + pub blob_size: u64, + #[serde(rename = "bufferSize")] + pub buffer_size: u64, + #[serde(rename = "poolWorkers")] + pub pool_workers: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Role { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "roleIds")] + pub role_ids: Map, + #[serde(rename = "enabledPermissions")] + pub enabled_permissions: Map, + #[serde(rename = "disabledPermissions")] + pub disabled_permissions: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Roles { + Default, + Custom(CustomRoles), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct S3Store { + #[serde(rename = "region")] + pub region: S3StoreRegion, + #[serde(rename = "bucket")] + pub bucket: String, + #[serde(rename = "accessKey")] + pub access_key: Option, + #[serde(rename = "secretKey")] + pub secret_key: SecretKeyOptional, + #[serde(rename = "securityToken")] + pub security_token: SecretKeyOptional, + #[serde(rename = "sessionToken")] + pub session_token: SecretKeyOptional, + #[serde(rename = "profile")] + pub profile: Option, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "maxRetries")] + pub max_retries: u64, + #[serde(rename = "keyPrefix")] + pub key_prefix: Option, + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct S3StoreCustomRegion { + #[serde(rename = "customEndpoint")] + pub custom_endpoint: String, + #[serde(rename = "customRegion")] + pub custom_region: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum S3StoreRegion { + UsEast1, + UsEast2, + UsWest1, + UsWest2, + CaCentral1, + AfSouth1, + ApEast1, + ApSouth1, + ApNortheast1, + ApNortheast2, + ApNortheast3, + ApSoutheast1, + ApSoutheast2, + CnNorth1, + CnNorthwest1, + EuNorth1, + EuCentral1, + EuCentral2, + EuWest1, + EuWest2, + EuWest3, + IlCentral1, + MeSouth1, + SaEast1, + DoNyc3, + DoAms3, + DoSgp1, + DoFra1, + Yandex, + WaUsEast1, + WaUsEast2, + WaUsCentral1, + WaUsWest1, + WaCaCentral1, + WaEuCentral1, + WaEuCentral2, + WaEuWest1, + WaEuWest2, + WaApNortheast1, + WaApNortheast2, + WaApSoutheast1, + WaApSoutheast2, + Custom(S3StoreCustomRegion), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Search { + #[serde(rename = "indexBatchSize")] + pub index_batch_size: u64, + #[serde(rename = "defaultLanguage")] + pub default_language: Locale, + #[serde(rename = "disableLanguages")] + pub disable_languages: Map, + #[serde(rename = "indexCalendar")] + pub index_calendar: bool, + #[serde(rename = "indexCalendarFields")] + pub index_calendar_fields: Map, + #[serde(rename = "indexContacts")] + pub index_contacts: bool, + #[serde(rename = "indexContactFields")] + pub index_contact_fields: Map, + #[serde(rename = "indexEmail")] + pub index_email: bool, + #[serde(rename = "indexEmailFields")] + pub index_email_fields: Map, + #[serde(rename = "indexTelemetry")] + pub index_telemetry: bool, + #[serde(rename = "indexTracingFields")] + pub index_tracing_fields: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SearchStore { + Default, + ElasticSearch(ElasticSearchStore), + Meilisearch(MeilisearchStore), + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SecondaryCredential { + #[serde(rename = "credentialId")] + pub credential_id: Id, + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "secret")] + pub secret: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: Option, + #[serde(rename = "permissions")] + pub permissions: CredentialPermissions, + #[serde(rename = "allowedIps")] + pub allowed_ips: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SecretKey { + Value(SecretKeyValue), + EnvironmentVariable(SecretKeyEnvironmentVariable), + File(SecretKeyFile), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SecretKeyEnvironmentVariable { + #[serde(rename = "variableName")] + pub variable_name: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SecretKeyFile { + #[serde(rename = "filePath")] + pub file_path: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SecretKeyOptional { + None, + Value(SecretKeyValue), + EnvironmentVariable(SecretKeyEnvironmentVariable), + File(SecretKeyFile), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SecretKeyValue { + #[serde(rename = "secret")] + pub secret: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SecretText { + Text(SecretTextValue), + EnvironmentVariable(SecretKeyEnvironmentVariable), + File(SecretKeyFile), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SecretTextOptional { + None, + Text(SecretTextValue), + EnvironmentVariable(SecretKeyEnvironmentVariable), + File(SecretKeyFile), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SecretTextValue { + #[serde(rename = "secret")] + pub secret: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Security { + #[serde(rename = "abuseBanRate")] + pub abuse_ban_rate: Option, + #[serde(rename = "abuseBanPeriod")] + pub abuse_ban_period: Option, + #[serde(rename = "authBanRate")] + pub auth_ban_rate: Option, + #[serde(rename = "authBanPeriod")] + pub auth_ban_period: Option, + #[serde(rename = "loiterBanRate")] + pub loiter_ban_rate: Option, + #[serde(rename = "loiterBanPeriod")] + pub loiter_ban_period: Option, + #[serde(rename = "scanBanPaths")] + pub scan_ban_paths: Map, + #[serde(rename = "scanBanRate")] + pub scan_ban_rate: Option, + #[serde(rename = "scanBanPeriod")] + pub scan_ban_period: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SenderAuth { + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, + #[serde(rename = "dkimStrict")] + pub dkim_strict: bool, + #[serde(rename = "dkimVerify")] + pub dkim_verify: Expression, + #[serde(rename = "spfEhloVerify")] + pub spf_ehlo_verify: Expression, + #[serde(rename = "spfFromVerify")] + pub spf_from_verify: Expression, + #[serde(rename = "arcVerify")] + pub arc_verify: Expression, + #[serde(rename = "dmarcVerify")] + pub dmarc_verify: Expression, + #[serde(rename = "reverseIpVerify")] + pub reverse_ip_verify: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ServerResponse { + #[serde(rename = "responseHostname")] + pub response_hostname: Option, + #[serde(rename = "responseCode")] + pub response_code: Option, + #[serde(rename = "responseEnhanced")] + pub response_enhanced: Option, + #[serde(rename = "responseMessage")] + pub response_message: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Service { + #[serde(rename = "hostname")] + pub hostname: Option, + #[serde(rename = "cleartext")] + pub cleartext: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ShardedBlobStore { + #[serde(rename = "stores")] + pub stores: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ShardedInMemoryStore { + #[serde(rename = "stores")] + pub stores: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Sharing { + #[serde(rename = "allowDirectoryQueries")] + pub allow_directory_queries: bool, + #[serde(rename = "maxShares")] + pub max_shares: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SieveSystemInterpreter { + #[serde(rename = "defaultFromAddress")] + pub default_from_address: Expression, + #[serde(rename = "defaultFromName")] + pub default_from_name: Expression, + #[serde(rename = "messageIdHostname")] + pub message_id_hostname: Option, + #[serde(rename = "duplicateExpiry")] + pub duplicate_expiry: Duration, + #[serde(rename = "noCapabilityCheck")] + pub no_capability_check: bool, + #[serde(rename = "defaultReturnPath")] + pub default_return_path: Expression, + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, + #[serde(rename = "maxCpuCycles")] + pub max_cpu_cycles: u64, + #[serde(rename = "maxNestedIncludes")] + pub max_nested_includes: u64, + #[serde(rename = "maxOutMessages")] + pub max_out_messages: u64, + #[serde(rename = "maxReceivedHeaders")] + pub max_received_headers: u64, + #[serde(rename = "maxRedirects")] + pub max_redirects: u64, + #[serde(rename = "maxVarSize")] + pub max_var_size: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SieveSystemScript { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "isActive")] + pub is_active: bool, + #[serde(rename = "contents")] + pub contents: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SieveUserInterpreter { + #[serde(rename = "defaultExpiryDuplicate")] + pub default_expiry_duplicate: Duration, + #[serde(rename = "defaultExpiryVacation")] + pub default_expiry_vacation: Duration, + #[serde(rename = "disableCapabilities")] + pub disable_capabilities: Map, + #[serde(rename = "allowedNotifyUris")] + pub allowed_notify_uris: Map, + #[serde(rename = "protectedHeaders")] + pub protected_headers: Map, + #[serde(rename = "defaultSubject")] + pub default_subject: String, + #[serde(rename = "defaultSubjectPrefix")] + pub default_subject_prefix: String, + #[serde(rename = "maxCpuCycles")] + pub max_cpu_cycles: u64, + #[serde(rename = "maxHeaderSize")] + pub max_header_size: u64, + #[serde(rename = "maxIncludes")] + pub max_includes: u64, + #[serde(rename = "maxLocalVars")] + pub max_local_vars: u64, + #[serde(rename = "maxMatchVars")] + pub max_match_vars: u64, + #[serde(rename = "maxScriptNameLength")] + pub max_script_name_length: u64, + #[serde(rename = "maxNestedBlocks")] + pub max_nested_blocks: u64, + #[serde(rename = "maxNestedForEvery")] + pub max_nested_for_every: u64, + #[serde(rename = "maxNestedIncludes")] + pub max_nested_includes: u64, + #[serde(rename = "maxNestedTests")] + pub max_nested_tests: u64, + #[serde(rename = "maxOutMessages")] + pub max_out_messages: u64, + #[serde(rename = "maxReceivedHeaders")] + pub max_received_headers: u64, + #[serde(rename = "maxRedirects")] + pub max_redirects: u64, + #[serde(rename = "maxScriptSize")] + pub max_script_size: u64, + #[serde(rename = "maxStringLength")] + pub max_string_length: u64, + #[serde(rename = "maxVarNameLength")] + pub max_var_name_length: u64, + #[serde(rename = "maxVarSize")] + pub max_var_size: u64, + #[serde(rename = "maxScripts")] + pub max_scripts: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SieveUserScript { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "isActive")] + pub is_active: bool, + #[serde(rename = "contents")] + pub contents: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamClassifier { + #[serde(rename = "model")] + pub model: SpamClassifierModel, + #[serde(rename = "learnHamFromCard")] + pub learn_ham_from_card: bool, + #[serde(rename = "learnSpamFromRblHits")] + pub learn_spam_from_rbl_hits: u64, + #[serde(rename = "learnSpamFromTraps")] + pub learn_spam_from_traps: bool, + #[serde(rename = "holdSamplesFor")] + pub hold_samples_for: Duration, + #[serde(rename = "minHamSamples")] + pub min_ham_samples: u64, + #[serde(rename = "minSpamSamples")] + pub min_spam_samples: u64, + #[serde(rename = "reservoirCapacity")] + pub reservoir_capacity: u64, + #[serde(rename = "trainFrequency")] + pub train_frequency: Option, + #[serde(rename = "learnHamFromReply")] + pub learn_ham_from_reply: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamClassifierFtrlCcfh { + #[serde(rename = "indicatorParameters")] + pub indicator_parameters: FtrlParameters, + #[serde(rename = "parameters")] + pub parameters: FtrlParameters, + #[serde(rename = "featureL2Normalize")] + pub feature_l2_normalize: bool, + #[serde(rename = "featureLogScale")] + pub feature_log_scale: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamClassifierFtrlFh { + #[serde(rename = "parameters")] + pub parameters: FtrlParameters, + #[serde(rename = "featureL2Normalize")] + pub feature_l2_normalize: bool, + #[serde(rename = "featureLogScale")] + pub feature_log_scale: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SpamClassifierModel { + FtrlFh(SpamClassifierFtrlFh), + FtrlCcfh(SpamClassifierFtrlCcfh), + Disabled, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamClassify { + #[serde(rename = "message")] + pub message: String, + #[serde(rename = "remoteIp")] + pub remote_ip: IpAddr, + #[serde(rename = "ehloDomain")] + pub ehlo_domain: String, + #[serde(rename = "authenticatedAs")] + pub authenticated_as: Option, + #[serde(rename = "isTls")] + pub is_tls: bool, + #[serde(rename = "envFrom")] + pub env_from: String, + #[serde(rename = "envFromParameters")] + pub env_from_parameters: Option, + #[serde(rename = "envRcptTo")] + pub env_rcpt_to: Map, + #[serde(rename = "score")] + pub score: Float, + #[serde(rename = "tags")] + pub tags: VecMap, + #[serde(rename = "result")] + pub result: SpamClassifyResult, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamClassifyTag { + #[serde(rename = "score")] + pub score: Float, + #[serde(rename = "disposition")] + pub disposition: SpamClassifyTagDisposition, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SpamDnsblServer { + Any(SpamDnsblServerAny), + Url(SpamDnsblServerUrl), + Domain(SpamDnsblServerDomain), + Email(SpamDnsblServerEmail), + Ip(SpamDnsblServerIp), + Header(SpamDnsblServerHeader), + Body(SpamDnsblServerBody), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerAny { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerBody { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerDomain { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerEmail { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerHeader { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerIp { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblServerUrl { + #[serde(rename = "tag")] + pub tag: Expression, + #[serde(rename = "zone")] + pub zone: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamDnsblSettings { + #[serde(rename = "domainLimit")] + pub domain_limit: u64, + #[serde(rename = "emailLimit")] + pub email_limit: u64, + #[serde(rename = "ipLimit")] + pub ip_limit: u64, + #[serde(rename = "urlLimit")] + pub url_limit: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamFileExtension { + #[serde(rename = "extension")] + pub extension: String, + #[serde(rename = "isArchive")] + pub is_archive: bool, + #[serde(rename = "isBad")] + pub is_bad: bool, + #[serde(rename = "isNz")] + pub is_nz: bool, + #[serde(rename = "contentTypes")] + pub content_types: Map, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SpamLlm { + Disable, + Enable(SpamLlmProperties), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamLlmProperties { + #[serde(rename = "categories")] + pub categories: Map, + #[serde(rename = "confidence")] + pub confidence: Map, + #[serde(rename = "responsePosCategory")] + pub response_pos_category: u64, + #[serde(rename = "responsePosConfidence")] + pub response_pos_confidence: Option, + #[serde(rename = "responsePosExplanation")] + pub response_pos_explanation: Option, + #[serde(rename = "modelId")] + pub model_id: Id, + #[serde(rename = "prompt")] + pub prompt: String, + #[serde(rename = "separator")] + pub separator: String, + #[serde(rename = "temperature")] + pub temperature: Float, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamPyzor { + #[serde(rename = "blockCount")] + pub block_count: u64, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "host")] + pub host: String, + #[serde(rename = "port")] + pub port: u64, + #[serde(rename = "ratio")] + pub ratio: Float, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "allowCount")] + pub allow_count: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SpamRule { + Any(SpamRuleAny), + Url(SpamRuleUrl), + Domain(SpamRuleDomain), + Email(SpamRuleEmail), + Ip(SpamRuleIp), + Header(SpamRuleHeader), + Body(SpamRuleBody), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleAny { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleBody { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleDomain { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleEmail { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleHeader { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleIp { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamRuleUrl { + #[serde(rename = "condition")] + pub condition: Expression, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "priority")] + pub priority: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamSettings { + #[serde(rename = "trustContacts")] + pub trust_contacts: bool, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "greylistFor")] + pub greylist_for: Option, + #[serde(rename = "scoreDiscard")] + pub score_discard: Float, + #[serde(rename = "scoreReject")] + pub score_reject: Float, + #[serde(rename = "scoreSpam")] + pub score_spam: Float, + #[serde(rename = "trustReplies")] + pub trust_replies: bool, + #[serde(rename = "spamFilterRulesUrl")] + pub spam_filter_rules_url: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SpamTag { + Score(SpamTagScore), + Discard(SpamTagAction), + Reject(SpamTagAction), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamTagAction { + #[serde(rename = "tag")] + pub tag: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamTagScore { + #[serde(rename = "tag")] + pub tag: String, + #[serde(rename = "score")] + pub score: Float, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpamTrainingSample { + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "blobId")] + pub blob_id: BlobId, + #[serde(rename = "isSpam")] + pub is_spam: bool, + #[serde(rename = "accountId")] + pub account_id: Option, + #[serde(rename = "expiresAt")] + pub expires_at: UTCDateTime, + #[serde(rename = "deleteAfterUse")] + pub delete_after_use: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpfReportSettings { + #[serde(rename = "fromAddress")] + pub from_address: Expression, + #[serde(rename = "fromName")] + pub from_name: Expression, + #[serde(rename = "sendFrequency")] + pub send_frequency: Expression, + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, + #[serde(rename = "subject")] + pub subject: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SqlAuthStore { + Default, + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), + Sqlite(SqliteStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SqlDirectory { + #[serde(rename = "description")] + pub description: String, + #[serde(rename = "store")] + pub store: SqlAuthStore, + #[serde(rename = "columnEmail")] + pub column_email: String, + #[serde(rename = "columnSecret")] + pub column_secret: String, + #[serde(rename = "columnClass")] + pub column_class: Option, + #[serde(rename = "columnDescription")] + pub column_description: Option, + #[serde(rename = "queryLogin")] + pub query_login: String, + #[serde(rename = "queryRecipient")] + pub query_recipient: String, + #[serde(rename = "queryMemberOf")] + pub query_member_of: Option, + #[serde(rename = "queryEmailAliases")] + pub query_email_aliases: Option, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SqliteStore { + #[serde(rename = "path")] + pub path: String, + #[serde(rename = "poolWorkers")] + pub pool_workers: Option, + #[serde(rename = "poolMaxConnections")] + pub pool_max_connections: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct StoreLookup { + #[serde(rename = "namespace")] + pub namespace: String, + #[serde(rename = "store")] + pub store: LookupStore, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum SubAddressing { + Enabled, + Custom(SubAddressingCustom), + Disabled, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SubAddressingCustom { + #[serde(rename = "customRule")] + pub custom_rule: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct SystemSettings { + #[serde(rename = "defaultHostname")] + pub default_hostname: String, + #[serde(rename = "defaultDomainId")] + pub default_domain_id: Id, + #[serde(rename = "defaultCertificateId")] + pub default_certificate_id: Option, + #[serde(rename = "threadPoolSize")] + pub thread_pool_size: Option, + #[serde(rename = "maxConnections")] + pub max_connections: u64, + #[serde(rename = "proxyTrustedNetworks")] + pub proxy_trusted_networks: Map, + #[serde(rename = "mailExchangers")] + pub mail_exchangers: List, + #[serde(rename = "services")] + pub services: VecMap, + #[serde(rename = "providerInfo")] + pub provider_info: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Task { + IndexDocument(TaskIndexDocument), + UnindexDocument(TaskIndexDocument), + IndexTrace(TaskIndexTrace), + CalendarAlarmEmail(TaskCalendarAlarmEmail), + CalendarAlarmNotification(TaskCalendarAlarmNotification), + CalendarItipMessage(TaskCalendarItipMessage), + MergeThreads(TaskMergeThreads), + DmarcReport(TaskDmarcReport), + TlsReport(TaskTlsReport), + RestoreArchivedItem(TaskRestoreArchivedItem), + DestroyAccount(TaskDestroyAccount), + AccountMaintenance(TaskAccountMaintenance), + TenantMaintenance(TaskTenantMaintenance), + StoreMaintenance(TaskStoreMaintenance), + SpamFilterMaintenance(TaskSpamFilterMaintenance), + AcmeRenewal(TaskDomainManagement), + DkimManagement(TaskDomainManagement), + DnsManagement(TaskDnsManagement), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskAccountMaintenance { + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "maintenanceType")] + pub maintenance_type: TaskAccountMaintenanceType, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskCalendarAlarmEmail { + #[serde(rename = "alarmId")] + pub alarm_id: u64, + #[serde(rename = "eventId")] + pub event_id: u64, + #[serde(rename = "eventStart")] + pub event_start: UTCDateTime, + #[serde(rename = "eventEnd")] + pub event_end: UTCDateTime, + #[serde(rename = "eventStartTz")] + pub event_start_tz: u64, + #[serde(rename = "eventEndTz")] + pub event_end_tz: u64, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "documentId")] + pub document_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskCalendarAlarmNotification { + #[serde(rename = "alarmId")] + pub alarm_id: u64, + #[serde(rename = "eventId")] + pub event_id: u64, + #[serde(rename = "recurrenceId")] + pub recurrence_id: Option, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "documentId")] + pub document_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskCalendarItipContents { + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "to")] + pub to: Map, + #[serde(rename = "isFromOrganizer")] + pub is_from_organizer: bool, + #[serde(rename = "iCalendarData")] + pub i_calendar_data: String, + #[serde(rename = "summary")] + pub summary: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskCalendarItipMessage { + #[serde(rename = "messages")] + pub messages: List, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "documentId")] + pub document_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskDestroyAccount { + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "accountName")] + pub account_name: String, + #[serde(rename = "accountDomainId")] + pub account_domain_id: Id, + #[serde(rename = "accountType")] + pub account_type: AccountType, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskDmarcReport { + #[serde(rename = "reportId")] + pub report_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskDnsManagement { + #[serde(rename = "updateRecords")] + pub update_records: Map, + #[serde(rename = "onSuccessRenewCertificate")] + pub on_success_renew_certificate: bool, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskDomainManagement { + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskIndexDocument { + #[serde(rename = "documentType")] + pub document_type: IndexDocumentType, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "documentId")] + pub document_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskIndexTrace { + #[serde(rename = "traceId")] + pub trace_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskManager { + #[serde(rename = "maxAttempts")] + pub max_attempts: u64, + #[serde(rename = "strategy")] + pub strategy: TaskRetryStrategy, + #[serde(rename = "totalDeadline")] + pub total_deadline: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskMergeThreads { + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "threadName")] + pub thread_name: String, + #[serde(rename = "messageIds")] + pub message_ids: Map, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskRestoreArchivedItem { + #[serde(rename = "blobId")] + pub blob_id: BlobId, + #[serde(rename = "archivedItemType")] + pub archived_item_type: ArchivedItemType, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "archivedUntil")] + pub archived_until: UTCDateTime, + #[serde(rename = "accountId")] + pub account_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum TaskRetryStrategy { + ExponentialBackoff(TaskRetryStrategyBackoff), + FixedDelay(TaskRetryStrategyFixed), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskRetryStrategyBackoff { + #[serde(rename = "factor")] + pub factor: Float, + #[serde(rename = "initialDelay")] + pub initial_delay: Duration, + #[serde(rename = "maxDelay")] + pub max_delay: Duration, + #[serde(rename = "jitter")] + pub jitter: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskRetryStrategyFixed { + #[serde(rename = "delay")] + pub delay: Duration, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskSpamFilterMaintenance { + #[serde(rename = "maintenanceType")] + pub maintenance_type: TaskSpamFilterMaintenanceType, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum TaskStatus { + Pending(TaskStatusPending), + Retry(TaskStatusRetry), + Failed(TaskStatusFailed), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskStatusFailed { + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "failedAt")] + pub failed_at: UTCDateTime, + #[serde(rename = "failedAttemptNumber")] + pub failed_attempt_number: u64, + #[serde(rename = "failureReason")] + pub failure_reason: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskStatusPending { + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "due")] + pub due: UTCDateTime, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskStatusRetry { + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "due")] + pub due: UTCDateTime, + #[serde(rename = "attemptNumber")] + pub attempt_number: u64, + #[serde(rename = "failureReason")] + pub failure_reason: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskStoreMaintenance { + #[serde(rename = "maintenanceType")] + pub maintenance_type: TaskStoreMaintenanceType, + #[serde(rename = "shardIndex")] + pub shard_index: Option, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskTenantMaintenance { + #[serde(rename = "tenantId")] + pub tenant_id: Id, + #[serde(rename = "maintenanceType")] + pub maintenance_type: TaskTenantMaintenanceType, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TaskTlsReport { + #[serde(rename = "reportId")] + pub report_id: Id, + #[serde(rename = "status")] + pub status: TaskStatus, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Tenant { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "logo")] + pub logo: Option, + #[serde(rename = "roles")] + pub roles: Roles, + #[serde(rename = "permissions")] + pub permissions: Permissions, + #[serde(rename = "quotas")] + pub quotas: VecMap, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsExternalReport { + #[serde(rename = "report")] + pub report: TlsReport, + #[serde(rename = "from")] + pub from: String, + #[serde(rename = "subject")] + pub subject: String, + #[serde(rename = "to")] + pub to: Map, + #[serde(rename = "receivedAt")] + pub received_at: UTCDateTime, + #[serde(rename = "expiresAt")] + pub expires_at: UTCDateTime, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsFailureDetails { + #[serde(rename = "resultType")] + pub result_type: TlsResultType, + #[serde(rename = "sendingMtaIp")] + pub sending_mta_ip: Option, + #[serde(rename = "receivingMxHostname")] + pub receiving_mx_hostname: Option, + #[serde(rename = "receivingMxHelo")] + pub receiving_mx_helo: Option, + #[serde(rename = "receivingIp")] + pub receiving_ip: Option, + #[serde(rename = "failedSessionCount")] + pub failed_session_count: u64, + #[serde(rename = "additionalInformation")] + pub additional_information: Option, + #[serde(rename = "failureReasonCode")] + pub failure_reason_code: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsInternalReport { + #[serde(rename = "policyIdentifiers")] + pub policy_identifiers: Map, + #[serde(rename = "mailRua")] + pub mail_rua: Map, + #[serde(rename = "httpRua")] + pub http_rua: Map, + #[serde(rename = "report")] + pub report: TlsReport, + #[serde(rename = "domain")] + pub domain: String, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "deliverAt")] + pub deliver_at: UTCDateTime, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsReport { + #[serde(rename = "organizationName")] + pub organization_name: Option, + #[serde(rename = "contactInfo")] + pub contact_info: Option, + #[serde(rename = "reportId")] + pub report_id: String, + #[serde(rename = "dateRangeStart")] + pub date_range_start: UTCDateTime, + #[serde(rename = "dateRangeEnd")] + pub date_range_end: UTCDateTime, + #[serde(rename = "policies")] + pub policies: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsReportPolicy { + #[serde(rename = "policyType")] + pub policy_type: TlsPolicyType, + #[serde(rename = "policyStrings")] + pub policy_strings: Map, + #[serde(rename = "policyDomain")] + pub policy_domain: String, + #[serde(rename = "mxHosts")] + pub mx_hosts: Map, + #[serde(rename = "totalSuccessfulSessions")] + pub total_successful_sessions: u64, + #[serde(rename = "totalFailedSessions")] + pub total_failed_sessions: u64, + #[serde(rename = "failureDetails")] + pub failure_details: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TlsReportSettings { + #[serde(rename = "contactInfo")] + pub contact_info: Expression, + #[serde(rename = "fromAddress")] + pub from_address: Expression, + #[serde(rename = "fromName")] + pub from_name: Expression, + #[serde(rename = "maxReportSize")] + pub max_report_size: Expression, + #[serde(rename = "orgName")] + pub org_name: Expression, + #[serde(rename = "sendFrequency")] + pub send_frequency: Expression, + #[serde(rename = "dkimSignDomain")] + pub dkim_sign_domain: Expression, + #[serde(rename = "subject")] + pub subject: Expression, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct Trace { + #[serde(rename = "events")] + pub events: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceEvent { + #[serde(rename = "event")] + pub event: trc::EventType, + #[serde(rename = "timestamp")] + pub timestamp: UTCDateTime, + #[serde(rename = "keyValues")] + pub key_values: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceKeyValue { + #[serde(rename = "key")] + pub key: trc::Key, + #[serde(rename = "value")] + pub value: TraceValue, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum TraceValue { + String(TraceValueString), + UnsignedInt(TraceValueUnsignedInt), + Integer(TraceValueInteger), + Boolean(TraceValueBoolean), + Float(TraceValueFloat), + UTCDateTime(TraceValueUTCDateTime), + Duration(TraceValueDuration), + IpAddr(TraceValueIpAddr), + List(TraceValueList), + Event(TraceValueEvent), + Null, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueBoolean { + #[serde(rename = "value")] + pub value: bool, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueDuration { + #[serde(rename = "value")] + pub value: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueEvent { + #[serde(rename = "event")] + pub event: trc::EventType, + #[serde(rename = "value")] + pub value: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueFloat { + #[serde(rename = "value")] + pub value: Float, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueInteger { + #[serde(rename = "value")] + pub value: i64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueIpAddr { + #[serde(rename = "value")] + pub value: IpAddr, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueList { + #[serde(rename = "value")] + pub value: List, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueString { + #[serde(rename = "value")] + pub value: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueUTCDateTime { + #[serde(rename = "value")] + pub value: UTCDateTime, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TraceValueUnsignedInt { + #[serde(rename = "value")] + pub value: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum Tracer { + Log(TracerLog), + Stdout(TracerStdout), + Journal(TracerCommon), + OtelHttp(TracerOtelHttp), + OtelGrpc(TracerOtelGrpc), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TracerCommon { + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TracerLog { + #[serde(rename = "path")] + pub path: String, + #[serde(rename = "prefix")] + pub prefix: String, + #[serde(rename = "rotate")] + pub rotate: LogRotateFrequency, + #[serde(rename = "ansi")] + pub ansi: bool, + #[serde(rename = "multiline")] + pub multiline: bool, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TracerOtelGrpc { + #[serde(rename = "endpoint")] + pub endpoint: Option, + #[serde(rename = "enableLogExporter")] + pub enable_log_exporter: bool, + #[serde(rename = "enableSpanExporter")] + pub enable_span_exporter: bool, + #[serde(rename = "throttle")] + pub throttle: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TracerOtelHttp { + #[serde(rename = "endpoint")] + pub endpoint: String, + #[serde(rename = "enableLogExporter")] + pub enable_log_exporter: bool, + #[serde(rename = "enableSpanExporter")] + pub enable_span_exporter: bool, + #[serde(rename = "throttle")] + pub throttle: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct TracerStdout { + #[serde(rename = "buffered")] + pub buffered: bool, + #[serde(rename = "ansi")] + pub ansi: bool, + #[serde(rename = "multiline")] + pub multiline: bool, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum TracingStore { + Disabled, + Default, + FoundationDb(FoundationDbStore), + PostgreSql(PostgreSqlStore), + MySql(MySqlStore), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct UserAccount { + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "domainId")] + pub domain_id: Id, + #[serde(rename = "credentials")] + pub credentials: List, + #[serde(rename = "createdAt")] + pub created_at: UTCDateTime, + #[serde(rename = "memberGroupIds")] + pub member_group_ids: Map, + #[serde(rename = "memberTenantId")] + pub member_tenant_id: Option, + #[serde(rename = "roles")] + pub roles: UserRoles, + #[serde(rename = "permissions")] + pub permissions: Permissions, + #[serde(rename = "quotas")] + pub quotas: VecMap, + #[serde(rename = "aliases")] + pub aliases: List, + #[serde(rename = "description")] + pub description: Option, + #[serde(rename = "locale")] + pub locale: Locale, + #[serde(rename = "timeZone")] + pub time_zone: Option, + #[serde(rename = "encryptionAtRest")] + pub encryption_at_rest: EncryptionAtRest, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "@type")] +pub enum UserRoles { + User, + Admin, + Custom(CustomRoles), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct WebDav { + #[serde(rename = "enableAssistedDiscovery")] + pub enable_assisted_discovery: bool, + #[serde(rename = "maxLockTimeout")] + pub max_lock_timeout: Duration, + #[serde(rename = "maxLocks")] + pub max_locks: u64, + #[serde(rename = "deadPropertyMaxSize")] + pub dead_property_max_size: Option, + #[serde(rename = "livePropertyMaxSize")] + pub live_property_max_size: u64, + #[serde(rename = "requestMaxSize")] + pub request_max_size: u64, + #[serde(rename = "maxResults")] + pub max_results: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct WebHook { + #[serde(rename = "allowInvalidCerts")] + pub allow_invalid_certs: bool, + #[serde(rename = "signatureKey")] + pub signature_key: SecretKeyOptional, + #[serde(rename = "throttle")] + pub throttle: Duration, + #[serde(rename = "timeout")] + pub timeout: Duration, + #[serde(rename = "discardAfter")] + pub discard_after: Duration, + #[serde(rename = "url")] + pub url: String, + #[serde(rename = "httpAuth")] + pub http_auth: HttpAuth, + #[serde(rename = "httpHeaders")] + pub http_headers: VecMap, + #[serde(rename = "enable")] + pub enable: bool, + #[serde(rename = "level")] + pub level: TracingLevel, + #[serde(rename = "lossy")] + pub lossy: bool, + #[serde(rename = "events")] + pub events: Map, + #[serde(rename = "eventsPolicy")] + pub events_policy: EventPolicy, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default)] +pub struct ZenohCoordinator { + #[serde(rename = "config")] + pub config: String, +} diff --git a/crates/registry/src/schema/structs_impl.rs b/crates/registry/src/schema/structs_impl.rs new file mode 100644 index 00000000..74f09f5a --- /dev/null +++ b/crates/registry/src/schema/structs_impl.rs @@ -0,0 +1,39085 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +// This file is auto-generated. Do not edit directly. + +use crate::schema::prelude::*; + +impl ObjectImpl for Account { + const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Account; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Account::User(inner) => inner.validate(errors), + Account::Group(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + Account::User(object) => { + i.typ(0); + object.index(i); + } + Account::Group(object) => { + i.typ(1); + object.index(i); + } + } + } +} + +impl Default for Account { + fn default() -> Self { + Account::User(Default::default()) + } +} + +impl Pickle for Account { + fn pickle(&self, out: &mut Vec) { + match self { + Account::User(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Account::Group(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Account::User), + 1 => Pickle::unpickle(stream).map(Account::Group), + _ => None, + } + } +} + +impl IntoValue for Account { + fn into_value(self) -> JmapValue<'static> { + match self { + Account::User(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("User".into())); + obj + } + Account::Group(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Group".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Account { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + AccountType::User => *self = Account::User(Default::default()), + AccountType::Group => *self = Account::Group(Default::default()), + } + } + match self { + Account::User(inner) => inner.patch(pointer, value), + Account::Group(inner) => inner.patch(pointer, value), + } + } +} + +impl Account { + pub fn object_type(&self) -> AccountType { + match self { + Account::User(_) => AccountType::User, + Account::Group(_) => AccountType::Group, + } + } +} + +impl ObjectImpl for AccountPassword { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AccountPassword; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + if let Some(value) = &self.current_secret { + if value.is_empty() { + errors.push(ValidationError::required(Property::CurrentSecret)); + } + } + let value = &self.otp_auth; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for AccountPassword { + fn pickle(&self, out: &mut Vec) { + self.secret.pickle(out); + self.current_secret.pickle(out); + self.otp_auth.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.secret = Pickle::unpickle(stream)?; + this.current_secret = Pickle::unpickle(stream)?; + this.otp_auth = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AccountPassword { + fn default() -> Self { + Self { + secret: Default::default(), + current_secret: Default::default(), + otp_auth: Default::default(), + } + } +} + +impl IntoValue for AccountPassword { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + if self.current_secret.is_some() { + map.insert_unchecked( + Property::CurrentSecret, + JmapValue::Str(MASKED_PASSWORD.into()), + ); + } + map.insert_unchecked(Property::OtpAuth, self.otp_auth.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AccountPassword { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::CurrentSecret) => self.current_secret.patch(pointer, value), + Some(Property::OtpAuth) => self.otp_auth.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for AccountSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AccountSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.encryption_at_rest; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + self.encryption_at_rest.index(i); + } +} + +impl Pickle for AccountSettings { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.locale.pickle(out); + self.time_zone.pickle(out); + self.encryption_at_rest.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.locale = Pickle::unpickle(stream)?; + this.time_zone = Pickle::unpickle(stream)?; + this.encryption_at_rest = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AccountSettings { + fn default() -> Self { + Self { + description: Default::default(), + locale: Locale::EnUS, + time_zone: Default::default(), + encryption_at_rest: Default::default(), + } + } +} + +impl IntoValue for AccountSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Locale, self.locale.into_value()); + map.insert_unchecked(Property::TimeZone, self.time_zone.into_value()); + map.insert_unchecked( + Property::EncryptionAtRest, + self.encryption_at_rest.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AccountSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Locale) => self.locale.patch(pointer, value), + Some(Property::TimeZone) => self.time_zone.patch(pointer, value), + Some(Property::EncryptionAtRest) => self.encryption_at_rest.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for AcmeProvider { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AcmeProvider; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.contact; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Contact)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Contact, 1)); + } + let value = &self.directory; + if value.is_empty() { + errors.push(ValidationError::required(Property::Directory)); + } + let value = &self.account_key; + if value.is_empty() { + errors.push(ValidationError::required(Property::AccountKey)); + } + let value = &self.account_uri; + if value.is_empty() { + errors.push(ValidationError::required(Property::AccountUri)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + for value in self.contact.iter() { + i.text(Property::Text, value); + } + i.text(Property::Text, &self.directory); + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for AcmeProvider { + fn pickle(&self, out: &mut Vec) { + self.challenge_type.pickle(out); + self.contact.pickle(out); + self.directory.pickle(out); + self.account_key.pickle(out); + self.account_uri.pickle(out); + self.renew_before.pickle(out); + self.max_retries.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.challenge_type = Pickle::unpickle(stream)?; + this.contact = Pickle::unpickle(stream)?; + this.directory = Pickle::unpickle(stream)?; + this.account_key = Pickle::unpickle(stream)?; + this.account_uri = Pickle::unpickle(stream)?; + this.renew_before = Pickle::unpickle(stream)?; + this.max_retries = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AcmeProvider { + fn default() -> Self { + Self { + challenge_type: AcmeChallengeType::TlsAlpn01, + contact: Default::default(), + directory: "https://acme-v02.api.letsencrypt.org/directory".to_string(), + account_key: Default::default(), + account_uri: Default::default(), + renew_before: AcmeRenewBefore::R23, + max_retries: 10i64, + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for AcmeProvider { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::ChallengeType, self.challenge_type.into_value()); + map.insert_unchecked(Property::Contact, self.contact.into_value()); + map.insert_unchecked(Property::Directory, self.directory.into_value()); + map.insert_unchecked(Property::AccountKey, JmapValue::Str(MASKED_PASSWORD.into())); + map.insert_unchecked(Property::AccountUri, self.account_uri.into_value()); + map.insert_unchecked(Property::RenewBefore, self.renew_before.into_value()); + map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AcmeProvider { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ChallengeType) => self.challenge_type.patch(pointer, value), + Some(Property::Contact) => self + .contact + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Directory) => self.directory.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Trim]), + value, + ), + Some(property @ Property::EabHmacKey) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(property @ Property::EabKeyId) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(Property::AccountKey) => pointer.assert_server_set(), + Some(Property::AccountUri) => pointer.assert_server_set(), + Some(Property::RenewBefore) => self.renew_before.patch(pointer, value), + Some(Property::MaxRetries) => self.max_retries.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Action { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Action; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Action::ReloadSettings => true, + Action::ReloadTlsCertificates => true, + Action::ReloadLookupStores => true, + Action::ReloadBlockedIps => true, + Action::UpdateApps => true, + Action::TroubleshootDmarc(inner) => inner.validate(errors), + Action::ClassifySpam(inner) => inner.validate(errors), + Action::InvalidateCaches => true, + Action::InvalidateNegativeCaches => true, + Action::PauseMtaQueue => true, + Action::ResumeMtaQueue => true, + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for Action { + fn default() -> Self { + Action::ReloadSettings + } +} + +impl Pickle for Action { + fn pickle(&self, out: &mut Vec) { + match self { + Action::ReloadSettings => { + 0u16.pickle(out); + } + Action::ReloadTlsCertificates => { + 1u16.pickle(out); + } + Action::ReloadLookupStores => { + 2u16.pickle(out); + } + Action::ReloadBlockedIps => { + 3u16.pickle(out); + } + Action::UpdateApps => { + 4u16.pickle(out); + } + Action::TroubleshootDmarc(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + Action::ClassifySpam(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + Action::InvalidateCaches => { + 7u16.pickle(out); + } + Action::InvalidateNegativeCaches => { + 8u16.pickle(out); + } + Action::PauseMtaQueue => { + 9u16.pickle(out); + } + Action::ResumeMtaQueue => { + 10u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(Action::ReloadSettings), + 1 => Some(Action::ReloadTlsCertificates), + 2 => Some(Action::ReloadLookupStores), + 3 => Some(Action::ReloadBlockedIps), + 4 => Some(Action::UpdateApps), + 5 => Pickle::unpickle(stream).map(Action::TroubleshootDmarc), + 6 => Pickle::unpickle(stream).map(Action::ClassifySpam), + 7 => Some(Action::InvalidateCaches), + 8 => Some(Action::InvalidateNegativeCaches), + 9 => Some(Action::PauseMtaQueue), + 10 => Some(Action::ResumeMtaQueue), + _ => None, + } + } +} + +impl IntoValue for Action { + fn into_value(self) -> JmapValue<'static> { + match self { + Action::ReloadSettings => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadSettings".into())); + JmapValue::Object(obj) + } + Action::ReloadTlsCertificates => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked( + Property::Type, + JmapValue::Str("ReloadTlsCertificates".into()), + ); + JmapValue::Object(obj) + } + Action::ReloadLookupStores => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadLookupStores".into())); + JmapValue::Object(obj) + } + Action::ReloadBlockedIps => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ReloadBlockedIps".into())); + JmapValue::Object(obj) + } + Action::UpdateApps => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("UpdateApps".into())); + JmapValue::Object(obj) + } + Action::TroubleshootDmarc(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("TroubleshootDmarc".into())); + obj + } + Action::ClassifySpam(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("ClassifySpam".into())); + obj + } + Action::InvalidateCaches => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("InvalidateCaches".into())); + JmapValue::Object(obj) + } + Action::InvalidateNegativeCaches => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked( + Property::Type, + JmapValue::Str("InvalidateNegativeCaches".into()), + ); + JmapValue::Object(obj) + } + Action::PauseMtaQueue => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("PauseMtaQueue".into())); + JmapValue::Object(obj) + } + Action::ResumeMtaQueue => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ResumeMtaQueue".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for Action { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + ActionType::ReloadSettings => *self = Action::ReloadSettings, + ActionType::ReloadTlsCertificates => *self = Action::ReloadTlsCertificates, + ActionType::ReloadLookupStores => *self = Action::ReloadLookupStores, + ActionType::ReloadBlockedIps => *self = Action::ReloadBlockedIps, + ActionType::UpdateApps => *self = Action::UpdateApps, + ActionType::TroubleshootDmarc => { + *self = Action::TroubleshootDmarc(Default::default()) + } + ActionType::ClassifySpam => *self = Action::ClassifySpam(Default::default()), + ActionType::InvalidateCaches => *self = Action::InvalidateCaches, + ActionType::InvalidateNegativeCaches => *self = Action::InvalidateNegativeCaches, + ActionType::PauseMtaQueue => *self = Action::PauseMtaQueue, + ActionType::ResumeMtaQueue => *self = Action::ResumeMtaQueue, + } + } + match self { + Action::ReloadSettings => pointer.assert_eof(), + Action::ReloadTlsCertificates => pointer.assert_eof(), + Action::ReloadLookupStores => pointer.assert_eof(), + Action::ReloadBlockedIps => pointer.assert_eof(), + Action::UpdateApps => pointer.assert_eof(), + Action::TroubleshootDmarc(inner) => inner.patch(pointer, value), + Action::ClassifySpam(inner) => inner.patch(pointer, value), + Action::InvalidateCaches => pointer.assert_eof(), + Action::InvalidateNegativeCaches => pointer.assert_eof(), + Action::PauseMtaQueue => pointer.assert_eof(), + Action::ResumeMtaQueue => pointer.assert_eof(), + } + } +} + +impl Action { + pub fn object_type(&self) -> ActionType { + match self { + Action::ReloadSettings => ActionType::ReloadSettings, + Action::ReloadTlsCertificates => ActionType::ReloadTlsCertificates, + Action::ReloadLookupStores => ActionType::ReloadLookupStores, + Action::ReloadBlockedIps => ActionType::ReloadBlockedIps, + Action::UpdateApps => ActionType::UpdateApps, + Action::TroubleshootDmarc(_) => ActionType::TroubleshootDmarc, + Action::ClassifySpam(_) => ActionType::ClassifySpam, + Action::InvalidateCaches => ActionType::InvalidateCaches, + Action::InvalidateNegativeCaches => ActionType::InvalidateNegativeCaches, + Action::PauseMtaQueue => ActionType::PauseMtaQueue, + Action::ResumeMtaQueue => ActionType::ResumeMtaQueue, + } + } +} + +impl ObjectImpl for AddressBook { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AddressBook; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.default_display_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultDisplayName)); + } + } + if let Some(value) = &self.default_href_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultHrefName)); + } + } + if let Some(value) = &self.max_address_books { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAddressBooks, 1)); + } + } + if let Some(value) = &self.max_contacts { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxContacts, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for AddressBook { + fn pickle(&self, out: &mut Vec) { + self.default_display_name.pickle(out); + self.default_href_name.pickle(out); + self.max_v_card_size.pickle(out); + self.max_address_books.pickle(out); + self.max_contacts.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.default_display_name = Pickle::unpickle(stream)?; + this.default_href_name = Pickle::unpickle(stream)?; + this.max_v_card_size = Pickle::unpickle(stream)?; + this.max_address_books = Pickle::unpickle(stream)?; + this.max_contacts = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AddressBook { + fn default() -> Self { + Self { + default_display_name: Some("Stalwart Address Book".to_string()), + default_href_name: Some("default".to_string()), + max_v_card_size: 524288u64, + max_address_books: Some(250u64), + max_contacts: Default::default(), + } + } +} + +impl IntoValue for AddressBook { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked( + Property::DefaultDisplayName, + self.default_display_name.into_value(), + ); + map.insert_unchecked( + Property::DefaultHrefName, + self.default_href_name.into_value(), + ); + map.insert_unchecked(Property::MaxVCardSize, self.max_v_card_size.into_value()); + map.insert_unchecked( + Property::MaxAddressBooks, + self.max_address_books.into_value(), + ); + map.insert_unchecked(Property::MaxContacts, self.max_contacts.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AddressBook { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DefaultDisplayName) => self + .default_display_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DefaultHrefName) => self + .default_href_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MaxVCardSize) => self.max_v_card_size.patch(pointer, value), + Some(Property::MaxAddressBooks) => self.max_address_books.patch(pointer, value), + Some(Property::MaxContacts) => self.max_contacts.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for AiModel { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AiModel; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.temperature; + if *value > Float::new(1.0) { + errors.push(ValidationError::max_value(Property::Temperature, 1)); + } + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::Temperature, 0)); + } + let value = &self.model; + if value.is_empty() { + errors.push(ValidationError::required(Property::Model)); + } + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for AiModel { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.allow_invalid_certs.pickle(out); + self.temperature.pickle(out); + self.model.pickle(out); + self.timeout.pickle(out); + self.model_type.pickle(out); + self.url.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.temperature = Pickle::unpickle(stream)?; + this.model = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.model_type = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AiModel { + fn default() -> Self { + Self { + name: Default::default(), + allow_invalid_certs: false, + temperature: Float::new(0.7f64), + model: Default::default(), + timeout: Duration::from_millis(120000), + model_type: AiModelType::Chat, + url: Default::default(), + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for AiModel { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::Temperature, self.temperature.into_value()); + map.insert_unchecked(Property::Model, self.model.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::ModelType, self.model_type.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AiModel { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self + .name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::Temperature) => self.temperature.patch(pointer, value), + Some(Property::Model) => self + .model + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::ModelType) => self.model_type.patch(pointer, value), + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Alert { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Alert; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.email_alert; + value.validate(errors); + let value = &self.event_alert; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Alert { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: &[], + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for Alert { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.email_alert.pickle(out); + self.event_alert.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.email_alert = Pickle::unpickle(stream)?; + this.event_alert = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Alert { + fn default() -> Self { + Self { + condition: Default::default(), + email_alert: Default::default(), + event_alert: Default::default(), + enable: true, + } + } +} + +impl IntoValue for Alert { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::EmailAlert, self.email_alert.into_value()); + map.insert_unchecked(Property::EventAlert, self.event_alert.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Alert { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::EmailAlert) => self.email_alert.patch(pointer, value), + Some(Property::EventAlert) => self.event_alert.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl AlertEmail { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + AlertEmail::Disabled => true, + AlertEmail::Enabled(inner) => inner.validate(errors), + } + } +} + +impl Default for AlertEmail { + fn default() -> Self { + AlertEmail::Disabled + } +} + +impl Pickle for AlertEmail { + fn pickle(&self, out: &mut Vec) { + match self { + AlertEmail::Disabled => { + 0u16.pickle(out); + } + AlertEmail::Enabled(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(AlertEmail::Disabled), + 1 => Pickle::unpickle(stream).map(AlertEmail::Enabled), + _ => None, + } + } +} + +impl IntoValue for AlertEmail { + fn into_value(self) -> JmapValue<'static> { + match self { + AlertEmail::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + AlertEmail::Enabled(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Enabled".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for AlertEmail { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + AlertEmailType::Disabled => *self = AlertEmail::Disabled, + AlertEmailType::Enabled => *self = AlertEmail::Enabled(Default::default()), + } + } + match self { + AlertEmail::Disabled => pointer.assert_eof(), + AlertEmail::Enabled(inner) => inner.patch(pointer, value), + } + } +} + +impl AlertEmail { + pub fn object_type(&self) -> AlertEmailType { + match self { + AlertEmail::Disabled => AlertEmailType::Disabled, + AlertEmail::Enabled(_) => AlertEmailType::Enabled, + } + } +} + +impl AlertEmailProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.body; + if value.is_empty() { + errors.push(ValidationError::required(Property::Body)); + } + let value = &self.from_address; + if value.is_empty() { + errors.push(ValidationError::required(Property::FromAddress)); + } + if let Some(value) = &self.from_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::FromName)); + } + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::To)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::To, 1)); + } + errors.len() == neb + } +} + +impl Pickle for AlertEmailProperties { + fn pickle(&self, out: &mut Vec) { + self.body.pickle(out); + self.from_address.pickle(out); + self.from_name.pickle(out); + self.subject.pickle(out); + self.to.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.body = Pickle::unpickle(stream)?; + this.from_address = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.to = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AlertEmailProperties { + fn default() -> Self { + Self { + body: Default::default(), + from_address: Default::default(), + from_name: Default::default(), + subject: Default::default(), + to: Default::default(), + } + } +} + +impl IntoValue for AlertEmailProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Body, self.body.into_value()); + map.insert_unchecked(Property::FromAddress, self.from_address.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::To, self.to.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AlertEmailProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Body) => self.body.patch(pointer, value), + Some(Property::FromAddress) => self + .from_address + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::FromName) => self.from_name.patch(pointer, value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::To) => self + .to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl AlertEvent { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + AlertEvent::Disabled => true, + AlertEvent::Enabled(inner) => inner.validate(errors), + } + } +} + +impl Default for AlertEvent { + fn default() -> Self { + AlertEvent::Disabled + } +} + +impl Pickle for AlertEvent { + fn pickle(&self, out: &mut Vec) { + match self { + AlertEvent::Disabled => { + 0u16.pickle(out); + } + AlertEvent::Enabled(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(AlertEvent::Disabled), + 1 => Pickle::unpickle(stream).map(AlertEvent::Enabled), + _ => None, + } + } +} + +impl IntoValue for AlertEvent { + fn into_value(self) -> JmapValue<'static> { + match self { + AlertEvent::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + AlertEvent::Enabled(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Enabled".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for AlertEvent { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + AlertEventType::Disabled => *self = AlertEvent::Disabled, + AlertEventType::Enabled => *self = AlertEvent::Enabled(Default::default()), + } + } + match self { + AlertEvent::Disabled => pointer.assert_eof(), + AlertEvent::Enabled(inner) => inner.patch(pointer, value), + } + } +} + +impl AlertEvent { + pub fn object_type(&self) -> AlertEventType { + match self { + AlertEvent::Disabled => AlertEventType::Disabled, + AlertEvent::Enabled(_) => AlertEventType::Enabled, + } + } +} + +impl AlertEventProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.event_message { + if value.is_empty() { + errors.push(ValidationError::required(Property::EventMessage)); + } + } + errors.len() == neb + } +} + +impl Pickle for AlertEventProperties { + fn pickle(&self, out: &mut Vec) { + self.event_message.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.event_message = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AlertEventProperties { + fn default() -> Self { + Self { + event_message: Default::default(), + } + } +} + +impl IntoValue for AlertEventProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::EventMessage, self.event_message.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AlertEventProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::EventMessage) => self.event_message.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for AllowedIp { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AllowedIp; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.address; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Address, value)); + } + if let Some(value) = &self.reason { + if value.is_empty() { + errors.push(ValidationError::required(Property::Reason)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Address, &self.address); + } +} + +impl Pickle for AllowedIp { + fn pickle(&self, out: &mut Vec) { + self.address.pickle(out); + self.reason.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.address = Pickle::unpickle(stream)?; + this.reason = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AllowedIp { + fn default() -> Self { + Self { + address: Default::default(), + reason: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + } + } +} + +impl IntoValue for AllowedIp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Address, self.address.into_value()); + map.insert_unchecked(Property::Reason, self.reason.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AllowedIp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Address) => self.address.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Trim]), + value, + ), + Some(Property::Reason) => self + .reason + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::CreatedAt) => self.created_at.patch(pointer.assert_read_only()?, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ApiKey { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ApiKey; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + let value = &self.permissions; + value.validate(errors); + let value = &self.allowed_ips; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::AllowedIps, value)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for ApiKey { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.secret.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + self.permissions.pickle(out); + self.allowed_ips.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.allowed_ips = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ApiKey { + fn default() -> Self { + Self { + description: Default::default(), + secret: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + permissions: Default::default(), + allowed_ips: Default::default(), + } + } +} + +impl IntoValue for ApiKey { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ApiKey { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Secret) => pointer.assert_server_set(), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for AppPassword { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::AppPassword; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + let value = &self.permissions; + value.validate(errors); + let value = &self.allowed_ips; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::AllowedIps, value)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for AppPassword { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.secret.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + self.permissions.pickle(out); + self.allowed_ips.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.allowed_ips = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AppPassword { + fn default() -> Self { + Self { + description: Default::default(), + secret: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + permissions: Default::default(), + allowed_ips: Default::default(), + } + } +} + +impl IntoValue for AppPassword { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AppPassword { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Secret) => pointer.assert_server_set(), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Application { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Application; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.resource_url; + if value.is_empty() { + errors.push(ValidationError::required(Property::ResourceUrl)); + } + let value = &self.url_prefix; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::UrlPrefix)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::UrlPrefix, 1)); + } + if let Some(value) = &self.unpack_directory { + if value.is_empty() { + errors.push(ValidationError::required(Property::UnpackDirectory)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Application { + fn pickle(&self, out: &mut Vec) { + self.enabled.pickle(out); + self.description.pickle(out); + self.resource_url.pickle(out); + self.url_prefix.pickle(out); + self.auto_update_frequency.pickle(out); + self.unpack_directory.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enabled = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.resource_url = Pickle::unpickle(stream)?; + this.url_prefix = Pickle::unpickle(stream)?; + this.auto_update_frequency = Pickle::unpickle(stream)?; + this.unpack_directory = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Application { + fn default() -> Self { + Self { + enabled: true, + description: Default::default(), + resource_url: Default::default(), + url_prefix: Default::default(), + auto_update_frequency: Duration::from_millis(7776000000), + unpack_directory: Default::default(), + } + } +} + +impl IntoValue for Application { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Enabled, self.enabled.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::ResourceUrl, self.resource_url.into_value()); + map.insert_unchecked(Property::UrlPrefix, self.url_prefix.into_value()); + map.insert_unchecked( + Property::AutoUpdateFrequency, + self.auto_update_frequency.into_value(), + ); + map.insert_unchecked( + Property::UnpackDirectory, + self.unpack_directory.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Application { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enabled) => self.enabled.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ResourceUrl) => self + .resource_url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::UrlPrefix) => self + .url_prefix + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AutoUpdateFrequency) => self.auto_update_frequency.patch(pointer, value), + Some(Property::UnpackDirectory) => self + .unpack_directory + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ArchivedCalendarEvent { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.title; + if value.is_empty() { + errors.push(ValidationError::required(Property::Title)); + } + if let Some(value) = &self.start_time { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::StartTime, value)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.archived_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for ArchivedCalendarEvent { + fn pickle(&self, out: &mut Vec) { + self.title.pickle(out); + self.start_time.pickle(out); + self.created_at.pickle(out); + self.account_id.pickle(out); + self.archived_at.pickle(out); + self.archived_until.pickle(out); + self.blob_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.title = Pickle::unpickle(stream)?; + this.start_time = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.archived_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArchivedCalendarEvent { + fn default() -> Self { + Self { + title: Default::default(), + start_time: Default::default(), + created_at: Default::default(), + account_id: Default::default(), + archived_at: Default::default(), + archived_until: Default::default(), + blob_id: Default::default(), + } + } +} + +impl IntoValue for ArchivedCalendarEvent { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Title, self.title.into_value()); + map.insert_unchecked(Property::StartTime, self.start_time.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArchivedCalendarEvent { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Title) => self.title.patch(pointer, value), + Some(Property::StartTime) => self.start_time.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_can_set_account()?, value), + Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value), + Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value), + Some(Property::BlobId) => self.blob_id.patch(pointer, value), + Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ArchivedContactCard { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.name { + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.archived_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for ArchivedContactCard { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.created_at.pickle(out); + self.account_id.pickle(out); + self.archived_at.pickle(out); + self.archived_until.pickle(out); + self.blob_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.archived_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArchivedContactCard { + fn default() -> Self { + Self { + name: Default::default(), + created_at: Default::default(), + account_id: Default::default(), + archived_at: Default::default(), + archived_until: Default::default(), + blob_id: Default::default(), + } + } +} + +impl IntoValue for ArchivedContactCard { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArchivedContactCard { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_can_set_account()?, value), + Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value), + Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value), + Some(Property::BlobId) => self.blob_id.patch(pointer, value), + Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ArchivedEmail { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.received_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivedAt, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.archived_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for ArchivedEmail { + fn pickle(&self, out: &mut Vec) { + self.from.pickle(out); + self.subject.pickle(out); + self.received_at.pickle(out); + self.size.pickle(out); + self.account_id.pickle(out); + self.archived_at.pickle(out); + self.archived_until.pickle(out); + self.blob_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.received_at = Pickle::unpickle(stream)?; + this.size = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.archived_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArchivedEmail { + fn default() -> Self { + Self { + from: Default::default(), + subject: Default::default(), + received_at: Default::default(), + size: 0u64, + account_id: Default::default(), + archived_at: Default::default(), + archived_until: Default::default(), + blob_id: Default::default(), + } + } +} + +impl IntoValue for ArchivedEmail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value()); + map.insert_unchecked(Property::Size, self.size.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArchivedEmail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::From) => self.from.patch(pointer, value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::ReceivedAt) => self.received_at.patch(pointer, value), + Some(Property::Size) => self.size.patch(pointer.assert_read_only()?, value), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_can_set_account()?, value), + Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value), + Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value), + Some(Property::BlobId) => self.blob_id.patch(pointer, value), + Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ArchivedFileNode { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.archived_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for ArchivedFileNode { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.created_at.pickle(out); + self.account_id.pickle(out); + self.archived_at.pickle(out); + self.archived_until.pickle(out); + self.blob_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.archived_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArchivedFileNode { + fn default() -> Self { + Self { + name: Default::default(), + created_at: Default::default(), + account_id: Default::default(), + archived_at: Default::default(), + archived_until: Default::default(), + blob_id: Default::default(), + } + } +} + +impl IntoValue for ArchivedFileNode { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArchivedFileNode { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_can_set_account()?, value), + Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value), + Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value), + Some(Property::BlobId) => self.blob_id.patch(pointer, value), + Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ArchivedItem { + const FLAGS: u64 = OBJ_FILTER_ACCOUNT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ArchivedItem; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + ArchivedItem::Email(inner) => inner.validate(errors), + ArchivedItem::FileNode(inner) => inner.validate(errors), + ArchivedItem::CalendarEvent(inner) => inner.validate(errors), + ArchivedItem::ContactCard(inner) => inner.validate(errors), + ArchivedItem::SieveScript(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + ArchivedItem::Email(object) => { + object.index(i); + } + ArchivedItem::FileNode(object) => { + object.index(i); + } + ArchivedItem::CalendarEvent(object) => { + object.index(i); + } + ArchivedItem::ContactCard(object) => { + object.index(i); + } + ArchivedItem::SieveScript(object) => { + object.index(i); + } + } + } +} + +impl Default for ArchivedItem { + fn default() -> Self { + ArchivedItem::Email(Default::default()) + } +} + +impl Pickle for ArchivedItem { + fn pickle(&self, out: &mut Vec) { + match self { + ArchivedItem::Email(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + ArchivedItem::FileNode(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + ArchivedItem::CalendarEvent(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + ArchivedItem::ContactCard(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + ArchivedItem::SieveScript(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(ArchivedItem::Email), + 1 => Pickle::unpickle(stream).map(ArchivedItem::FileNode), + 2 => Pickle::unpickle(stream).map(ArchivedItem::CalendarEvent), + 3 => Pickle::unpickle(stream).map(ArchivedItem::ContactCard), + 4 => Pickle::unpickle(stream).map(ArchivedItem::SieveScript), + _ => None, + } + } +} + +impl IntoValue for ArchivedItem { + fn into_value(self) -> JmapValue<'static> { + match self { + ArchivedItem::Email(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Email".into())); + obj + } + ArchivedItem::FileNode(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FileNode".into())); + obj + } + ArchivedItem::CalendarEvent(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("CalendarEvent".into())); + obj + } + ArchivedItem::ContactCard(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("ContactCard".into())); + obj + } + ArchivedItem::SieveScript(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("SieveScript".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for ArchivedItem { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + ArchivedItemType::Email => *self = ArchivedItem::Email(Default::default()), + ArchivedItemType::FileNode => *self = ArchivedItem::FileNode(Default::default()), + ArchivedItemType::CalendarEvent => { + *self = ArchivedItem::CalendarEvent(Default::default()) + } + ArchivedItemType::ContactCard => { + *self = ArchivedItem::ContactCard(Default::default()) + } + ArchivedItemType::SieveScript => { + *self = ArchivedItem::SieveScript(Default::default()) + } + } + } + match self { + ArchivedItem::Email(inner) => inner.patch(pointer, value), + ArchivedItem::FileNode(inner) => inner.patch(pointer, value), + ArchivedItem::CalendarEvent(inner) => inner.patch(pointer, value), + ArchivedItem::ContactCard(inner) => inner.patch(pointer, value), + ArchivedItem::SieveScript(inner) => inner.patch(pointer, value), + } + } +} + +impl ArchivedItem { + pub fn object_type(&self) -> ArchivedItemType { + match self { + ArchivedItem::Email(_) => ArchivedItemType::Email, + ArchivedItem::FileNode(_) => ArchivedItemType::FileNode, + ArchivedItem::CalendarEvent(_) => ArchivedItemType::CalendarEvent, + ArchivedItem::ContactCard(_) => ArchivedItemType::ContactCard, + ArchivedItem::SieveScript(_) => ArchivedItemType::SieveScript, + } + } +} + +impl ArchivedSieveScript { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.content; + if value.is_empty() { + errors.push(ValidationError::required(Property::Content)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.archived_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for ArchivedSieveScript { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.created_at.pickle(out); + self.content.pickle(out); + self.account_id.pickle(out); + self.archived_at.pickle(out); + self.archived_until.pickle(out); + self.blob_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.content = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.archived_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArchivedSieveScript { + fn default() -> Self { + Self { + name: Default::default(), + created_at: Default::default(), + content: Default::default(), + account_id: Default::default(), + archived_at: Default::default(), + archived_until: Default::default(), + blob_id: Default::default(), + } + } +} + +impl IntoValue for ArchivedSieveScript { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::Content, self.content.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ArchivedAt, self.archived_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArchivedSieveScript { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::Content) => self.content.patch(pointer, value), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_can_set_account()?, value), + Some(Property::ArchivedAt) => self.archived_at.patch(pointer, value), + Some(Property::ArchivedUntil) => self.archived_until.patch(pointer, value), + Some(Property::BlobId) => self.blob_id.patch(pointer, value), + Some(property @ Property::Status) => Ok(MaybeUnpatched::Unpatched { property, value }), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ArfExternalReport { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ArfExternalReport; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.report; + value.validate(errors); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::To)); + } + } + let value = &self.received_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivedAt, value)); + } + let value = &self.expires_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + } +} + +impl Pickle for ArfExternalReport { + fn pickle(&self, out: &mut Vec) { + self.report.pickle(out); + self.from.pickle(out); + self.subject.pickle(out); + self.to.pickle(out); + self.received_at.pickle(out); + self.expires_at.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.report = Pickle::unpickle(stream)?; + this.from = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.to = Pickle::unpickle(stream)?; + this.received_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArfExternalReport { + fn default() -> Self { + Self { + report: Default::default(), + from: Default::default(), + subject: Default::default(), + to: Default::default(), + received_at: Default::default(), + expires_at: Default::default(), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for ArfExternalReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::To, self.to.into_value()); + map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArfExternalReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::From) => self + .from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::To) => self + .to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::ReceivedAt) => self.received_at.patch(pointer, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ArfFeedbackReport { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.arrival_date { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArrivalDate, value)); + } + } + let value = &self.authentication_results; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthenticationResults)); + } + } + if let Some(value) = &self.original_envelope_id { + if value.is_empty() { + errors.push(ValidationError::required(Property::OriginalEnvelopeId)); + } + } + if let Some(value) = &self.original_mail_from { + if value.is_empty() { + errors.push(ValidationError::required(Property::OriginalMailFrom)); + } + } + if let Some(value) = &self.original_rcpt_to { + if value.is_empty() { + errors.push(ValidationError::required(Property::OriginalRcptTo)); + } + } + let value = &self.reported_domains; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportedDomains)); + } + } + let value = &self.reported_uris; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportedUris)); + } + } + if let Some(value) = &self.reporting_mta { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportingMta)); + } + } + if let Some(value) = &self.source_ip { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::SourceIp, value)); + } + } + if let Some(value) = &self.source_port { + if *value < 1 { + errors.push(ValidationError::min_value(Property::SourcePort, 1)); + } + if *value > 65535 { + errors.push(ValidationError::max_value(Property::SourcePort, 65535)); + } + } + if let Some(value) = &self.user_agent { + if value.is_empty() { + errors.push(ValidationError::required(Property::UserAgent)); + } + } + if let Some(value) = &self.dkim_adsp_dns { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimAdspDns)); + } + } + if let Some(value) = &self.dkim_canonicalized_body { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimCanonicalizedBody)); + } + } + if let Some(value) = &self.dkim_canonicalized_header { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimCanonicalizedHeader)); + } + } + if let Some(value) = &self.dkim_domain { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimDomain)); + } + } + if let Some(value) = &self.dkim_identity { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimIdentity)); + } + } + if let Some(value) = &self.dkim_selector { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimSelector)); + } + } + if let Some(value) = &self.dkim_selector_dns { + if value.is_empty() { + errors.push(ValidationError::required(Property::DkimSelectorDns)); + } + } + if let Some(value) = &self.spf_dns { + if value.is_empty() { + errors.push(ValidationError::required(Property::SpfDns)); + } + } + if let Some(value) = &self.message { + if value.is_empty() { + errors.push(ValidationError::required(Property::Message)); + } + } + if let Some(value) = &self.headers { + if value.is_empty() { + errors.push(ValidationError::required(Property::Headers)); + } + } + errors.len() == neb + } +} + +impl Pickle for ArfFeedbackReport { + fn pickle(&self, out: &mut Vec) { + self.feedback_type.pickle(out); + self.arrival_date.pickle(out); + self.authentication_results.pickle(out); + self.incidents.pickle(out); + self.original_envelope_id.pickle(out); + self.original_mail_from.pickle(out); + self.original_rcpt_to.pickle(out); + self.reported_domains.pickle(out); + self.reported_uris.pickle(out); + self.reporting_mta.pickle(out); + self.source_ip.pickle(out); + self.source_port.pickle(out); + self.user_agent.pickle(out); + self.version.pickle(out); + self.auth_failure.pickle(out); + self.delivery_result.pickle(out); + self.dkim_adsp_dns.pickle(out); + self.dkim_canonicalized_body.pickle(out); + self.dkim_canonicalized_header.pickle(out); + self.dkim_domain.pickle(out); + self.dkim_identity.pickle(out); + self.dkim_selector.pickle(out); + self.dkim_selector_dns.pickle(out); + self.spf_dns.pickle(out); + self.identity_alignment.pickle(out); + self.message.pickle(out); + self.headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.feedback_type = Pickle::unpickle(stream)?; + this.arrival_date = Pickle::unpickle(stream)?; + this.authentication_results = Pickle::unpickle(stream)?; + this.incidents = Pickle::unpickle(stream)?; + this.original_envelope_id = Pickle::unpickle(stream)?; + this.original_mail_from = Pickle::unpickle(stream)?; + this.original_rcpt_to = Pickle::unpickle(stream)?; + this.reported_domains = Pickle::unpickle(stream)?; + this.reported_uris = Pickle::unpickle(stream)?; + this.reporting_mta = Pickle::unpickle(stream)?; + this.source_ip = Pickle::unpickle(stream)?; + this.source_port = Pickle::unpickle(stream)?; + this.user_agent = Pickle::unpickle(stream)?; + this.version = Pickle::unpickle(stream)?; + this.auth_failure = Pickle::unpickle(stream)?; + this.delivery_result = Pickle::unpickle(stream)?; + this.dkim_adsp_dns = Pickle::unpickle(stream)?; + this.dkim_canonicalized_body = Pickle::unpickle(stream)?; + this.dkim_canonicalized_header = Pickle::unpickle(stream)?; + this.dkim_domain = Pickle::unpickle(stream)?; + this.dkim_identity = Pickle::unpickle(stream)?; + this.dkim_selector = Pickle::unpickle(stream)?; + this.dkim_selector_dns = Pickle::unpickle(stream)?; + this.spf_dns = Pickle::unpickle(stream)?; + this.identity_alignment = Pickle::unpickle(stream)?; + this.message = Pickle::unpickle(stream)?; + this.headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ArfFeedbackReport { + fn default() -> Self { + Self { + feedback_type: Default::default(), + arrival_date: Default::default(), + authentication_results: Default::default(), + incidents: 0u64, + original_envelope_id: Default::default(), + original_mail_from: Default::default(), + original_rcpt_to: Default::default(), + reported_domains: Default::default(), + reported_uris: Default::default(), + reporting_mta: Default::default(), + source_ip: Default::default(), + source_port: Default::default(), + user_agent: Default::default(), + version: 1u64, + auth_failure: Default::default(), + delivery_result: Default::default(), + dkim_adsp_dns: Default::default(), + dkim_canonicalized_body: Default::default(), + dkim_canonicalized_header: Default::default(), + dkim_domain: Default::default(), + dkim_identity: Default::default(), + dkim_selector: Default::default(), + dkim_selector_dns: Default::default(), + spf_dns: Default::default(), + identity_alignment: Default::default(), + message: Default::default(), + headers: Default::default(), + } + } +} + +impl IntoValue for ArfFeedbackReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(29); + map.insert_unchecked(Property::FeedbackType, self.feedback_type.into_value()); + map.insert_unchecked(Property::ArrivalDate, self.arrival_date.into_value()); + map.insert_unchecked( + Property::AuthenticationResults, + self.authentication_results.into_value(), + ); + map.insert_unchecked(Property::Incidents, self.incidents.into_value()); + map.insert_unchecked( + Property::OriginalEnvelopeId, + self.original_envelope_id.into_value(), + ); + map.insert_unchecked( + Property::OriginalMailFrom, + self.original_mail_from.into_value(), + ); + map.insert_unchecked(Property::OriginalRcptTo, self.original_rcpt_to.into_value()); + map.insert_unchecked( + Property::ReportedDomains, + self.reported_domains.into_value(), + ); + map.insert_unchecked(Property::ReportedUris, self.reported_uris.into_value()); + map.insert_unchecked(Property::ReportingMta, self.reporting_mta.into_value()); + map.insert_unchecked(Property::SourceIp, self.source_ip.into_value()); + map.insert_unchecked(Property::SourcePort, self.source_port.into_value()); + map.insert_unchecked(Property::UserAgent, self.user_agent.into_value()); + map.insert_unchecked(Property::Version, self.version.into_value()); + map.insert_unchecked(Property::AuthFailure, self.auth_failure.into_value()); + map.insert_unchecked(Property::DeliveryResult, self.delivery_result.into_value()); + map.insert_unchecked(Property::DkimAdspDns, self.dkim_adsp_dns.into_value()); + map.insert_unchecked( + Property::DkimCanonicalizedBody, + self.dkim_canonicalized_body.into_value(), + ); + map.insert_unchecked( + Property::DkimCanonicalizedHeader, + self.dkim_canonicalized_header.into_value(), + ); + map.insert_unchecked(Property::DkimDomain, self.dkim_domain.into_value()); + map.insert_unchecked(Property::DkimIdentity, self.dkim_identity.into_value()); + map.insert_unchecked(Property::DkimSelector, self.dkim_selector.into_value()); + map.insert_unchecked( + Property::DkimSelectorDns, + self.dkim_selector_dns.into_value(), + ); + map.insert_unchecked(Property::SpfDns, self.spf_dns.into_value()); + map.insert_unchecked( + Property::IdentityAlignment, + self.identity_alignment.into_value(), + ); + map.insert_unchecked(Property::Message, self.message.into_value()); + map.insert_unchecked(Property::Headers, self.headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ArfFeedbackReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::FeedbackType) => self.feedback_type.patch(pointer, value), + Some(Property::ArrivalDate) => self.arrival_date.patch(pointer, value), + Some(Property::AuthenticationResults) => { + self.authentication_results.patch(pointer, value) + } + Some(Property::Incidents) => self.incidents.patch(pointer, value), + Some(Property::OriginalEnvelopeId) => self.original_envelope_id.patch(pointer, value), + Some(Property::OriginalMailFrom) => self + .original_mail_from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::OriginalRcptTo) => self + .original_rcpt_to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::ReportedDomains) => self + .reported_domains + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::ReportedUris) => self.reported_uris.patch(pointer, value), + Some(Property::ReportingMta) => self.reporting_mta.patch(pointer, value), + Some(Property::SourceIp) => self.source_ip.patch(pointer, value), + Some(Property::SourcePort) => self.source_port.patch(pointer, value), + Some(Property::UserAgent) => self.user_agent.patch(pointer, value), + Some(Property::Version) => self.version.patch(pointer, value), + Some(Property::AuthFailure) => self.auth_failure.patch(pointer, value), + Some(Property::DeliveryResult) => self.delivery_result.patch(pointer, value), + Some(Property::DkimAdspDns) => self.dkim_adsp_dns.patch(pointer, value), + Some(Property::DkimCanonicalizedBody) => { + self.dkim_canonicalized_body.patch(pointer, value) + } + Some(Property::DkimCanonicalizedHeader) => { + self.dkim_canonicalized_header.patch(pointer, value) + } + Some(Property::DkimDomain) => self.dkim_domain.patch(pointer, value), + Some(Property::DkimIdentity) => self.dkim_identity.patch(pointer, value), + Some(Property::DkimSelector) => self.dkim_selector.patch(pointer, value), + Some(Property::DkimSelectorDns) => self.dkim_selector_dns.patch(pointer, value), + Some(Property::SpfDns) => self.spf_dns.patch(pointer, value), + Some(Property::IdentityAlignment) => self.identity_alignment.patch(pointer, value), + Some(Property::Message) => self.message.patch(pointer, value), + Some(Property::Headers) => self.headers.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Asn { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Asn; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Asn::Disabled => true, + Asn::Resource(inner) => inner.validate(errors), + Asn::Dns(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for Asn { + fn default() -> Self { + Asn::Disabled + } +} + +impl Pickle for Asn { + fn pickle(&self, out: &mut Vec) { + match self { + Asn::Disabled => { + 0u16.pickle(out); + } + Asn::Resource(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Asn::Dns(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(Asn::Disabled), + 1 => Pickle::unpickle(stream).map(Asn::Resource), + 2 => Pickle::unpickle(stream).map(Asn::Dns), + _ => None, + } + } +} + +impl IntoValue for Asn { + fn into_value(self) -> JmapValue<'static> { + match self { + Asn::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + Asn::Resource(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Resource".into())); + obj + } + Asn::Dns(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Dns".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Asn { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + AsnType::Disabled => *self = Asn::Disabled, + AsnType::Resource => *self = Asn::Resource(Default::default()), + AsnType::Dns => *self = Asn::Dns(Default::default()), + } + } + match self { + Asn::Disabled => pointer.assert_eof(), + Asn::Resource(inner) => inner.patch(pointer, value), + Asn::Dns(inner) => inner.patch(pointer, value), + } + } +} + +impl Asn { + pub fn object_type(&self) -> AsnType { + match self { + Asn::Disabled => AsnType::Disabled, + Asn::Resource(_) => AsnType::Resource, + Asn::Dns(_) => AsnType::Dns, + } + } +} + +impl AsnDns { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.separator; + if value.is_empty() { + errors.push(ValidationError::required(Property::Separator)); + } + let value = &self.zone_ip_v4; + if value.is_empty() { + errors.push(ValidationError::required(Property::ZoneIpV4)); + } + let value = &self.zone_ip_v6; + if value.is_empty() { + errors.push(ValidationError::required(Property::ZoneIpV6)); + } + errors.len() == neb + } +} + +impl Pickle for AsnDns { + fn pickle(&self, out: &mut Vec) { + self.index_asn.pickle(out); + self.index_asn_name.pickle(out); + self.index_country.pickle(out); + self.separator.pickle(out); + self.zone_ip_v4.pickle(out); + self.zone_ip_v6.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.index_asn = Pickle::unpickle(stream)?; + this.index_asn_name = Pickle::unpickle(stream)?; + this.index_country = Pickle::unpickle(stream)?; + this.separator = Pickle::unpickle(stream)?; + this.zone_ip_v4 = Pickle::unpickle(stream)?; + this.zone_ip_v6 = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AsnDns { + fn default() -> Self { + Self { + index_asn: 0u64, + index_asn_name: Default::default(), + index_country: Default::default(), + separator: "|".to_string(), + zone_ip_v4: Default::default(), + zone_ip_v6: Default::default(), + } + } +} + +impl IntoValue for AsnDns { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::IndexAsn, self.index_asn.into_value()); + map.insert_unchecked(Property::IndexAsnName, self.index_asn_name.into_value()); + map.insert_unchecked(Property::IndexCountry, self.index_country.into_value()); + map.insert_unchecked(Property::Separator, self.separator.into_value()); + map.insert_unchecked(Property::ZoneIpV4, self.zone_ip_v4.into_value()); + map.insert_unchecked(Property::ZoneIpV6, self.zone_ip_v6.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AsnDns { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IndexAsn) => self.index_asn.patch(pointer, value), + Some(Property::IndexAsnName) => self.index_asn_name.patch(pointer, value), + Some(Property::IndexCountry) => self.index_country.patch(pointer, value), + Some(Property::Separator) => self + .separator + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ZoneIpV4) => self + .zone_ip_v4 + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ZoneIpV6) => self + .zone_ip_v6 + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl AsnResource { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.asn_urls; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AsnUrls)); + } + } + let value = &self.geo_urls; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::GeoUrls)); + } + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for AsnResource { + fn pickle(&self, out: &mut Vec) { + self.expires.pickle(out); + self.max_size.pickle(out); + self.timeout.pickle(out); + self.asn_urls.pickle(out); + self.geo_urls.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.expires = Pickle::unpickle(stream)?; + this.max_size = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.asn_urls = Pickle::unpickle(stream)?; + this.geo_urls = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AsnResource { + fn default() -> Self { + Self { + expires: Duration::from_millis(86400000), + max_size: 104857600, + timeout: Duration::from_millis(300000), + asn_urls: Default::default(), + geo_urls: Default::default(), + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for AsnResource { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Expires, self.expires.into_value()); + map.insert_unchecked(Property::MaxSize, self.max_size.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::AsnUrls, self.asn_urls.into_value()); + map.insert_unchecked(Property::GeoUrls, self.geo_urls.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AsnResource { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Expires) => self.expires.patch(pointer, value), + Some(Property::MaxSize) => self.max_size.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AsnUrls) => self + .asn_urls + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::GeoUrls) => self + .geo_urls + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Authentication { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Authentication; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.directory_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DirectoryId)); + } + } + let value = &self.default_user_role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultUserRoleIds)); + } + } + let value = &self.default_group_role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultGroupRoleIds)); + } + } + let value = &self.default_tenant_role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultTenantRoleIds)); + } + } + let value = &self.default_admin_role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultAdminRoleIds)); + } + } + let value = &self.password_min_length; + if *value < 1 { + errors.push(ValidationError::min_value(Property::PasswordMinLength, 1)); + } + if *value > 100 { + errors.push(ValidationError::max_value(Property::PasswordMinLength, 100)); + } + let value = &self.password_max_length; + if *value < 1 { + errors.push(ValidationError::min_value(Property::PasswordMaxLength, 1)); + } + if *value > 1000 { + errors.push(ValidationError::max_value( + Property::PasswordMaxLength, + 1000, + )); + } + if let Some(value) = &self.max_app_passwords { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAppPasswords, 1)); + } + } + if let Some(value) = &self.max_api_keys { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxApiKeys, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Directory, self.directory_id, None); + for id in self.default_user_role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + for id in self.default_group_role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + for id in self.default_tenant_role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + for id in self.default_admin_role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + } +} + +impl Pickle for Authentication { + fn pickle(&self, out: &mut Vec) { + self.directory_id.pickle(out); + self.default_user_role_ids.pickle(out); + self.default_group_role_ids.pickle(out); + self.default_tenant_role_ids.pickle(out); + self.default_admin_role_ids.pickle(out); + self.password_hash_algorithm.pickle(out); + self.password_min_length.pickle(out); + self.password_max_length.pickle(out); + self.password_min_strength.pickle(out); + self.password_default_expiry.pickle(out); + self.max_app_passwords.pickle(out); + self.max_api_keys.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.directory_id = Pickle::unpickle(stream)?; + this.default_user_role_ids = Pickle::unpickle(stream)?; + this.default_group_role_ids = Pickle::unpickle(stream)?; + this.default_tenant_role_ids = Pickle::unpickle(stream)?; + this.default_admin_role_ids = Pickle::unpickle(stream)?; + this.password_hash_algorithm = Pickle::unpickle(stream)?; + this.password_min_length = Pickle::unpickle(stream)?; + this.password_max_length = Pickle::unpickle(stream)?; + this.password_min_strength = Pickle::unpickle(stream)?; + this.password_default_expiry = Pickle::unpickle(stream)?; + this.max_app_passwords = Pickle::unpickle(stream)?; + this.max_api_keys = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Authentication { + fn default() -> Self { + Self { + directory_id: Default::default(), + default_user_role_ids: Default::default(), + default_group_role_ids: Default::default(), + default_tenant_role_ids: Default::default(), + default_admin_role_ids: Default::default(), + password_hash_algorithm: PasswordHashAlgorithm::Argon2id, + password_min_length: 8u64, + password_max_length: 128u64, + password_min_strength: PasswordStrength::Three, + password_default_expiry: Default::default(), + max_app_passwords: Some(5u64), + max_api_keys: Some(5u64), + } + } +} + +impl IntoValue for Authentication { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::DirectoryId, self.directory_id.into_value()); + map.insert_unchecked( + Property::DefaultUserRoleIds, + self.default_user_role_ids.into_value(), + ); + map.insert_unchecked( + Property::DefaultGroupRoleIds, + self.default_group_role_ids.into_value(), + ); + map.insert_unchecked( + Property::DefaultTenantRoleIds, + self.default_tenant_role_ids.into_value(), + ); + map.insert_unchecked( + Property::DefaultAdminRoleIds, + self.default_admin_role_ids.into_value(), + ); + map.insert_unchecked( + Property::PasswordHashAlgorithm, + self.password_hash_algorithm.into_value(), + ); + map.insert_unchecked( + Property::PasswordMinLength, + self.password_min_length.into_value(), + ); + map.insert_unchecked( + Property::PasswordMaxLength, + self.password_max_length.into_value(), + ); + map.insert_unchecked( + Property::PasswordMinStrength, + self.password_min_strength.into_value(), + ); + map.insert_unchecked( + Property::PasswordDefaultExpiry, + self.password_default_expiry.into_value(), + ); + map.insert_unchecked( + Property::MaxAppPasswords, + self.max_app_passwords.into_value(), + ); + map.insert_unchecked(Property::MaxApiKeys, self.max_api_keys.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Authentication { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DirectoryId) => self.directory_id.patch(pointer, value), + Some(Property::DefaultUserRoleIds) => self.default_user_role_ids.patch(pointer, value), + Some(Property::DefaultGroupRoleIds) => { + self.default_group_role_ids.patch(pointer, value) + } + Some(Property::DefaultTenantRoleIds) => { + self.default_tenant_role_ids.patch(pointer, value) + } + Some(Property::DefaultAdminRoleIds) => { + self.default_admin_role_ids.patch(pointer, value) + } + Some(Property::PasswordHashAlgorithm) => { + self.password_hash_algorithm.patch(pointer, value) + } + Some(Property::PasswordMinLength) => self.password_min_length.patch(pointer, value), + Some(Property::PasswordMaxLength) => self.password_max_length.patch(pointer, value), + Some(Property::PasswordMinStrength) => self.password_min_strength.patch(pointer, value), + Some(Property::PasswordDefaultExpiry) => { + self.password_default_expiry.patch(pointer, value) + } + Some(Property::MaxAppPasswords) => self.max_app_passwords.patch(pointer, value), + Some(Property::MaxApiKeys) => self.max_api_keys.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl AzureStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.storage_account; + if value.is_empty() { + errors.push(ValidationError::required(Property::StorageAccount)); + } + let value = &self.container; + if value.is_empty() { + errors.push(ValidationError::required(Property::Container)); + } + let value = &self.access_key; + value.validate(errors); + let value = &self.sas_token; + value.validate(errors); + let value = &self.max_retries; + if *value > 10 { + errors.push(ValidationError::max_value(Property::MaxRetries, 10)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRetries, 1)); + } + if let Some(value) = &self.key_prefix { + if value.is_empty() { + errors.push(ValidationError::required(Property::KeyPrefix)); + } + } + errors.len() == neb + } +} + +impl Pickle for AzureStore { + fn pickle(&self, out: &mut Vec) { + self.storage_account.pickle(out); + self.container.pickle(out); + self.access_key.pickle(out); + self.sas_token.pickle(out); + self.timeout.pickle(out); + self.max_retries.pickle(out); + self.key_prefix.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.storage_account = Pickle::unpickle(stream)?; + this.container = Pickle::unpickle(stream)?; + this.access_key = Pickle::unpickle(stream)?; + this.sas_token = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.max_retries = Pickle::unpickle(stream)?; + this.key_prefix = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for AzureStore { + fn default() -> Self { + Self { + storage_account: Default::default(), + container: Default::default(), + access_key: Default::default(), + sas_token: Default::default(), + timeout: Duration::from_millis(30000), + max_retries: 3u64, + key_prefix: Default::default(), + } + } +} + +impl IntoValue for AzureStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::StorageAccount, self.storage_account.into_value()); + map.insert_unchecked(Property::Container, self.container.into_value()); + map.insert_unchecked(Property::AccessKey, self.access_key.into_value()); + map.insert_unchecked(Property::SasToken, self.sas_token.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value()); + map.insert_unchecked(Property::KeyPrefix, self.key_prefix.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for AzureStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::StorageAccount) => self + .storage_account + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Container) => self + .container + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AccessKey) => self.access_key.patch(pointer, value), + Some(Property::SasToken) => self.sas_token.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::MaxRetries) => self.max_retries.patch(pointer, value), + Some(Property::KeyPrefix) => self + .key_prefix + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for BlobStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::BlobStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + BlobStore::Default => true, + BlobStore::Sharded(inner) => inner.validate(errors), + BlobStore::S3(inner) => inner.validate(errors), + BlobStore::Azure(inner) => inner.validate(errors), + BlobStore::FileSystem(inner) => inner.validate(errors), + BlobStore::FoundationDb(inner) => inner.validate(errors), + BlobStore::PostgreSql(inner) => inner.validate(errors), + BlobStore::MySql(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for BlobStore { + fn default() -> Self { + BlobStore::Default + } +} + +impl Pickle for BlobStore { + fn pickle(&self, out: &mut Vec) { + match self { + BlobStore::Default => { + 0u16.pickle(out); + } + BlobStore::Sharded(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + BlobStore::S3(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + BlobStore::Azure(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + BlobStore::FileSystem(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + BlobStore::FoundationDb(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + BlobStore::PostgreSql(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + BlobStore::MySql(inner) => { + 7u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(BlobStore::Default), + 1 => Pickle::unpickle(stream).map(BlobStore::Sharded), + 2 => Pickle::unpickle(stream).map(BlobStore::S3), + 3 => Pickle::unpickle(stream).map(BlobStore::Azure), + 4 => Pickle::unpickle(stream).map(BlobStore::FileSystem), + 5 => Pickle::unpickle(stream).map(BlobStore::FoundationDb), + 6 => Pickle::unpickle(stream).map(BlobStore::PostgreSql), + 7 => Pickle::unpickle(stream).map(BlobStore::MySql), + _ => None, + } + } +} + +impl IntoValue for BlobStore { + fn into_value(self) -> JmapValue<'static> { + match self { + BlobStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + BlobStore::Sharded(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sharded".into())); + obj + } + BlobStore::S3(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("S3".into())); + obj + } + BlobStore::Azure(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Azure".into())); + obj + } + BlobStore::FileSystem(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FileSystem".into())); + obj + } + BlobStore::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + BlobStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + BlobStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for BlobStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + BlobStoreType::Default => *self = BlobStore::Default, + BlobStoreType::Sharded => *self = BlobStore::Sharded(Default::default()), + BlobStoreType::S3 => *self = BlobStore::S3(Default::default()), + BlobStoreType::Azure => *self = BlobStore::Azure(Default::default()), + BlobStoreType::FileSystem => *self = BlobStore::FileSystem(Default::default()), + BlobStoreType::FoundationDb => *self = BlobStore::FoundationDb(Default::default()), + BlobStoreType::PostgreSql => *self = BlobStore::PostgreSql(Default::default()), + BlobStoreType::MySql => *self = BlobStore::MySql(Default::default()), + } + } + match self { + BlobStore::Default => pointer.assert_eof(), + BlobStore::Sharded(inner) => inner.patch(pointer, value), + BlobStore::S3(inner) => inner.patch(pointer, value), + BlobStore::Azure(inner) => inner.patch(pointer, value), + BlobStore::FileSystem(inner) => inner.patch(pointer, value), + BlobStore::FoundationDb(inner) => inner.patch(pointer, value), + BlobStore::PostgreSql(inner) => inner.patch(pointer, value), + BlobStore::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl BlobStore { + pub fn object_type(&self) -> BlobStoreType { + match self { + BlobStore::Default => BlobStoreType::Default, + BlobStore::Sharded(_) => BlobStoreType::Sharded, + BlobStore::S3(_) => BlobStoreType::S3, + BlobStore::Azure(_) => BlobStoreType::Azure, + BlobStore::FileSystem(_) => BlobStoreType::FileSystem, + BlobStore::FoundationDb(_) => BlobStoreType::FoundationDb, + BlobStore::PostgreSql(_) => BlobStoreType::PostgreSql, + BlobStore::MySql(_) => BlobStoreType::MySql, + } + } +} + +impl BlobStoreBase { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + BlobStoreBase::S3(inner) => inner.validate(errors), + BlobStoreBase::Azure(inner) => inner.validate(errors), + BlobStoreBase::FileSystem(inner) => inner.validate(errors), + BlobStoreBase::FoundationDb(inner) => inner.validate(errors), + BlobStoreBase::PostgreSql(inner) => inner.validate(errors), + BlobStoreBase::MySql(inner) => inner.validate(errors), + } + } +} + +impl Default for BlobStoreBase { + fn default() -> Self { + BlobStoreBase::S3(Default::default()) + } +} + +impl Pickle for BlobStoreBase { + fn pickle(&self, out: &mut Vec) { + match self { + BlobStoreBase::S3(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + BlobStoreBase::Azure(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + BlobStoreBase::FileSystem(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + BlobStoreBase::FoundationDb(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + BlobStoreBase::PostgreSql(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + BlobStoreBase::MySql(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(BlobStoreBase::S3), + 1 => Pickle::unpickle(stream).map(BlobStoreBase::Azure), + 2 => Pickle::unpickle(stream).map(BlobStoreBase::FileSystem), + 3 => Pickle::unpickle(stream).map(BlobStoreBase::FoundationDb), + 4 => Pickle::unpickle(stream).map(BlobStoreBase::PostgreSql), + 5 => Pickle::unpickle(stream).map(BlobStoreBase::MySql), + _ => None, + } + } +} + +impl IntoValue for BlobStoreBase { + fn into_value(self) -> JmapValue<'static> { + match self { + BlobStoreBase::S3(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("S3".into())); + obj + } + BlobStoreBase::Azure(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Azure".into())); + obj + } + BlobStoreBase::FileSystem(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FileSystem".into())); + obj + } + BlobStoreBase::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + BlobStoreBase::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + BlobStoreBase::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for BlobStoreBase { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + BlobStoreBaseType::S3 => *self = BlobStoreBase::S3(Default::default()), + BlobStoreBaseType::Azure => *self = BlobStoreBase::Azure(Default::default()), + BlobStoreBaseType::FileSystem => { + *self = BlobStoreBase::FileSystem(Default::default()) + } + BlobStoreBaseType::FoundationDb => { + *self = BlobStoreBase::FoundationDb(Default::default()) + } + BlobStoreBaseType::PostgreSql => { + *self = BlobStoreBase::PostgreSql(Default::default()) + } + BlobStoreBaseType::MySql => *self = BlobStoreBase::MySql(Default::default()), + } + } + match self { + BlobStoreBase::S3(inner) => inner.patch(pointer, value), + BlobStoreBase::Azure(inner) => inner.patch(pointer, value), + BlobStoreBase::FileSystem(inner) => inner.patch(pointer, value), + BlobStoreBase::FoundationDb(inner) => inner.patch(pointer, value), + BlobStoreBase::PostgreSql(inner) => inner.patch(pointer, value), + BlobStoreBase::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl BlobStoreBase { + pub fn object_type(&self) -> BlobStoreBaseType { + match self { + BlobStoreBase::S3(_) => BlobStoreBaseType::S3, + BlobStoreBase::Azure(_) => BlobStoreBaseType::Azure, + BlobStoreBase::FileSystem(_) => BlobStoreBaseType::FileSystem, + BlobStoreBase::FoundationDb(_) => BlobStoreBaseType::FoundationDb, + BlobStoreBase::PostgreSql(_) => BlobStoreBaseType::PostgreSql, + BlobStoreBase::MySql(_) => BlobStoreBaseType::MySql, + } + } +} + +impl ObjectImpl for BlockedIp { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::BlockedIp; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.address; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Address, value)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Address, &self.address); + } +} + +impl Pickle for BlockedIp { + fn pickle(&self, out: &mut Vec) { + self.address.pickle(out); + self.reason.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.address = Pickle::unpickle(stream)?; + this.reason = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for BlockedIp { + fn default() -> Self { + Self { + address: Default::default(), + reason: BlockReason::Manual, + created_at: Default::default(), + expires_at: Default::default(), + } + } +} + +impl IntoValue for BlockedIp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Address, self.address.into_value()); + map.insert_unchecked(Property::Reason, self.reason.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for BlockedIp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Address) => self.address.patch(pointer.assert_read_only()?, value), + Some(Property::Reason) => self.reason.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Bootstrap { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Bootstrap; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.server_hostname; + if value.is_empty() { + errors.push(ValidationError::required(Property::ServerHostname)); + } + let value = &self.default_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultDomain)); + } + let value = &self.data_store; + value.validate(errors); + let value = &self.blob_store; + value.validate(errors); + let value = &self.search_store; + value.validate(errors); + let value = &self.in_memory_store; + value.validate(errors); + let value = &self.directory; + value.validate(errors); + let value = &self.tracer; + value.validate(errors); + let value = &self.dns_server; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Bootstrap { + fn pickle(&self, out: &mut Vec) { + self.server_hostname.pickle(out); + self.default_domain.pickle(out); + self.request_tls_certificate.pickle(out); + self.generate_dkim_keys.pickle(out); + self.data_store.pickle(out); + self.blob_store.pickle(out); + self.search_store.pickle(out); + self.in_memory_store.pickle(out); + self.directory.pickle(out); + self.tracer.pickle(out); + self.dns_server.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.server_hostname = Pickle::unpickle(stream)?; + this.default_domain = Pickle::unpickle(stream)?; + this.request_tls_certificate = Pickle::unpickle(stream)?; + this.generate_dkim_keys = Pickle::unpickle(stream)?; + this.data_store = Pickle::unpickle(stream)?; + this.blob_store = Pickle::unpickle(stream)?; + this.search_store = Pickle::unpickle(stream)?; + this.in_memory_store = Pickle::unpickle(stream)?; + this.directory = Pickle::unpickle(stream)?; + this.tracer = Pickle::unpickle(stream)?; + this.dns_server = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Bootstrap { + fn default() -> Self { + Self { + server_hostname: Default::default(), + default_domain: Default::default(), + request_tls_certificate: true, + generate_dkim_keys: true, + data_store: DataStore::RocksDb(RocksDbStore { + path: "/var/lib/stalwart/".to_string(), + ..Default::default() + }), + blob_store: BlobStore::Default, + search_store: SearchStore::Default, + in_memory_store: InMemoryStore::Default, + directory: DirectoryBootstrap::Internal, + tracer: Tracer::Log(TracerLog { + path: "/var/log/stalwart/".to_string(), + ..Default::default() + }), + dns_server: DnsServerBootstrap::Manual, + } + } +} + +impl IntoValue for Bootstrap { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::ServerHostname, self.server_hostname.into_value()); + map.insert_unchecked(Property::DefaultDomain, self.default_domain.into_value()); + map.insert_unchecked( + Property::RequestTlsCertificate, + self.request_tls_certificate.into_value(), + ); + map.insert_unchecked( + Property::GenerateDkimKeys, + self.generate_dkim_keys.into_value(), + ); + map.insert_unchecked(Property::DataStore, self.data_store.into_value()); + map.insert_unchecked(Property::BlobStore, self.blob_store.into_value()); + map.insert_unchecked(Property::SearchStore, self.search_store.into_value()); + map.insert_unchecked(Property::InMemoryStore, self.in_memory_store.into_value()); + map.insert_unchecked(Property::Directory, self.directory.into_value()); + map.insert_unchecked(Property::Tracer, self.tracer.into_value()); + map.insert_unchecked(Property::DnsServer, self.dns_server.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Bootstrap { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ServerHostname) => self + .server_hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::DefaultDomain) => self.default_domain.patch(pointer, value), + Some(Property::RequestTlsCertificate) => { + self.request_tls_certificate.patch(pointer, value) + } + Some(Property::GenerateDkimKeys) => self.generate_dkim_keys.patch(pointer, value), + Some(Property::DataStore) => self.data_store.patch(pointer, value), + Some(Property::BlobStore) => self.blob_store.patch(pointer, value), + Some(Property::SearchStore) => self.search_store.patch(pointer, value), + Some(Property::InMemoryStore) => self.in_memory_store.patch(pointer, value), + Some(Property::Directory) => self.directory.patch(pointer, value), + Some(Property::Tracer) => self.tracer.patch(pointer, value), + Some(Property::DnsServer) => self.dns_server.patch(pointer, value), + Some(Property::Username) => pointer.assert_server_set(), + Some(Property::Secret) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Cache { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Cache; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.access_tokens; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::AccessTokens, 2048)); + } + let value = &self.contacts; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Contacts, 2048)); + } + let value = &self.dns_ipv4; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsIpv4, 2048)); + } + let value = &self.dns_ipv6; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsIpv6, 2048)); + } + let value = &self.dns_mta_sts; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsMtaSts, 2048)); + } + let value = &self.dns_mx; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsMx, 2048)); + } + let value = &self.dns_ptr; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsPtr, 2048)); + } + let value = &self.dns_rbl; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsRbl, 2048)); + } + let value = &self.dns_tlsa; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsTlsa, 2048)); + } + let value = &self.dns_txt; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DnsTxt, 2048)); + } + let value = &self.events; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Events, 2048)); + } + let value = &self.scheduling; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Scheduling, 2048)); + } + let value = &self.files; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Files, 2048)); + } + let value = &self.http_auth; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::HttpAuth, 2048)); + } + let value = &self.messages; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Messages, 2048)); + } + let value = &self.domains; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Domains, 2048)); + } + let value = &self.domain_names; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DomainNames, 2048)); + } + let value = &self.domain_names_negative; + if *value < 2048 { + errors.push(ValidationError::min_value( + Property::DomainNamesNegative, + 2048, + )); + } + let value = &self.email_addresses; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::EmailAddresses, 2048)); + } + let value = &self.email_addresses_negative; + if *value < 2048 { + errors.push(ValidationError::min_value( + Property::EmailAddressesNegative, + 2048, + )); + } + let value = &self.accounts; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Accounts, 2048)); + } + let value = &self.roles; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Roles, 2048)); + } + let value = &self.tenants; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::Tenants, 2048)); + } + let value = &self.mailing_lists; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::MailingLists, 2048)); + } + let value = &self.dkim_signatures; + if *value < 2048 { + errors.push(ValidationError::min_value(Property::DkimSignatures, 2048)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Cache { + fn pickle(&self, out: &mut Vec) { + self.access_tokens.pickle(out); + self.contacts.pickle(out); + self.dns_ipv4.pickle(out); + self.dns_ipv6.pickle(out); + self.dns_mta_sts.pickle(out); + self.dns_mx.pickle(out); + self.dns_ptr.pickle(out); + self.dns_rbl.pickle(out); + self.dns_tlsa.pickle(out); + self.dns_txt.pickle(out); + self.events.pickle(out); + self.scheduling.pickle(out); + self.files.pickle(out); + self.http_auth.pickle(out); + self.messages.pickle(out); + self.domains.pickle(out); + self.domain_names.pickle(out); + self.domain_names_negative.pickle(out); + self.email_addresses.pickle(out); + self.email_addresses_negative.pickle(out); + self.accounts.pickle(out); + self.roles.pickle(out); + self.tenants.pickle(out); + self.mailing_lists.pickle(out); + self.dkim_signatures.pickle(out); + self.negative_ttl.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.access_tokens = Pickle::unpickle(stream)?; + this.contacts = Pickle::unpickle(stream)?; + this.dns_ipv4 = Pickle::unpickle(stream)?; + this.dns_ipv6 = Pickle::unpickle(stream)?; + this.dns_mta_sts = Pickle::unpickle(stream)?; + this.dns_mx = Pickle::unpickle(stream)?; + this.dns_ptr = Pickle::unpickle(stream)?; + this.dns_rbl = Pickle::unpickle(stream)?; + this.dns_tlsa = Pickle::unpickle(stream)?; + this.dns_txt = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.scheduling = Pickle::unpickle(stream)?; + this.files = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.messages = Pickle::unpickle(stream)?; + this.domains = Pickle::unpickle(stream)?; + this.domain_names = Pickle::unpickle(stream)?; + this.domain_names_negative = Pickle::unpickle(stream)?; + this.email_addresses = Pickle::unpickle(stream)?; + this.email_addresses_negative = Pickle::unpickle(stream)?; + this.accounts = Pickle::unpickle(stream)?; + this.roles = Pickle::unpickle(stream)?; + this.tenants = Pickle::unpickle(stream)?; + this.mailing_lists = Pickle::unpickle(stream)?; + this.dkim_signatures = Pickle::unpickle(stream)?; + this.negative_ttl = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Cache { + fn default() -> Self { + Self { + access_tokens: 10485760, + contacts: 10485760, + dns_ipv4: 5242880, + dns_ipv6: 5242880, + dns_mta_sts: 1048576, + dns_mx: 5242880, + dns_ptr: 1048576, + dns_rbl: 5242880, + dns_tlsa: 1048576, + dns_txt: 5242880, + events: 10485760, + scheduling: 1048576, + files: 10485760, + http_auth: 1048576, + messages: 52428800, + domains: 5242880, + domain_names: 10485760, + domain_names_negative: 1048576, + email_addresses: 10485760, + email_addresses_negative: 2097152, + accounts: 20971520, + roles: 5242880, + tenants: 5242880, + mailing_lists: 2097152, + dkim_signatures: 10485760, + negative_ttl: Duration::from_millis(3600000), + } + } +} + +impl IntoValue for Cache { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(28); + map.insert_unchecked(Property::AccessTokens, self.access_tokens.into_value()); + map.insert_unchecked(Property::Contacts, self.contacts.into_value()); + map.insert_unchecked(Property::DnsIpv4, self.dns_ipv4.into_value()); + map.insert_unchecked(Property::DnsIpv6, self.dns_ipv6.into_value()); + map.insert_unchecked(Property::DnsMtaSts, self.dns_mta_sts.into_value()); + map.insert_unchecked(Property::DnsMx, self.dns_mx.into_value()); + map.insert_unchecked(Property::DnsPtr, self.dns_ptr.into_value()); + map.insert_unchecked(Property::DnsRbl, self.dns_rbl.into_value()); + map.insert_unchecked(Property::DnsTlsa, self.dns_tlsa.into_value()); + map.insert_unchecked(Property::DnsTxt, self.dns_txt.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::Scheduling, self.scheduling.into_value()); + map.insert_unchecked(Property::Files, self.files.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::Messages, self.messages.into_value()); + map.insert_unchecked(Property::Domains, self.domains.into_value()); + map.insert_unchecked(Property::DomainNames, self.domain_names.into_value()); + map.insert_unchecked( + Property::DomainNamesNegative, + self.domain_names_negative.into_value(), + ); + map.insert_unchecked(Property::EmailAddresses, self.email_addresses.into_value()); + map.insert_unchecked( + Property::EmailAddressesNegative, + self.email_addresses_negative.into_value(), + ); + map.insert_unchecked(Property::Accounts, self.accounts.into_value()); + map.insert_unchecked(Property::Roles, self.roles.into_value()); + map.insert_unchecked(Property::Tenants, self.tenants.into_value()); + map.insert_unchecked(Property::MailingLists, self.mailing_lists.into_value()); + map.insert_unchecked(Property::DkimSignatures, self.dkim_signatures.into_value()); + map.insert_unchecked(Property::NegativeTtl, self.negative_ttl.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Cache { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccessTokens) => self.access_tokens.patch(pointer, value), + Some(Property::Contacts) => self.contacts.patch(pointer, value), + Some(Property::DnsIpv4) => self.dns_ipv4.patch(pointer, value), + Some(Property::DnsIpv6) => self.dns_ipv6.patch(pointer, value), + Some(Property::DnsMtaSts) => self.dns_mta_sts.patch(pointer, value), + Some(Property::DnsMx) => self.dns_mx.patch(pointer, value), + Some(Property::DnsPtr) => self.dns_ptr.patch(pointer, value), + Some(Property::DnsRbl) => self.dns_rbl.patch(pointer, value), + Some(Property::DnsTlsa) => self.dns_tlsa.patch(pointer, value), + Some(Property::DnsTxt) => self.dns_txt.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::Scheduling) => self.scheduling.patch(pointer, value), + Some(Property::Files) => self.files.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::Messages) => self.messages.patch(pointer, value), + Some(Property::Domains) => self.domains.patch(pointer, value), + Some(Property::DomainNames) => self.domain_names.patch(pointer, value), + Some(Property::DomainNamesNegative) => self.domain_names_negative.patch(pointer, value), + Some(Property::EmailAddresses) => self.email_addresses.patch(pointer, value), + Some(Property::EmailAddressesNegative) => { + self.email_addresses_negative.patch(pointer, value) + } + Some(Property::Accounts) => self.accounts.patch(pointer, value), + Some(Property::Roles) => self.roles.patch(pointer, value), + Some(Property::Tenants) => self.tenants.patch(pointer, value), + Some(Property::MailingLists) => self.mailing_lists.patch(pointer, value), + Some(Property::DkimSignatures) => self.dkim_signatures.patch(pointer, value), + Some(Property::NegativeTtl) => self.negative_ttl.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Calendar { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Calendar; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.default_display_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultDisplayName)); + } + } + if let Some(value) = &self.default_href_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultHrefName)); + } + } + let value = &self.max_attendees; + if *value > 100000 { + errors.push(ValidationError::max_value(Property::MaxAttendees, 100000)); + } + if let Some(value) = &self.max_calendars { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxCalendars, 1)); + } + } + if let Some(value) = &self.max_events { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxEvents, 1)); + } + } + if let Some(value) = &self.max_participant_identities { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::MaxParticipantIdentities, + 1, + )); + } + } + if let Some(value) = &self.max_event_notifications { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::MaxEventNotifications, + 1, + )); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Calendar { + fn pickle(&self, out: &mut Vec) { + self.default_display_name.pickle(out); + self.default_href_name.pickle(out); + self.max_attendees.pickle(out); + self.max_recurrence_expansions.pickle(out); + self.max_i_calendar_size.pickle(out); + self.max_calendars.pickle(out); + self.max_events.pickle(out); + self.max_participant_identities.pickle(out); + self.max_event_notifications.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.default_display_name = Pickle::unpickle(stream)?; + this.default_href_name = Pickle::unpickle(stream)?; + this.max_attendees = Pickle::unpickle(stream)?; + this.max_recurrence_expansions = Pickle::unpickle(stream)?; + this.max_i_calendar_size = Pickle::unpickle(stream)?; + this.max_calendars = Pickle::unpickle(stream)?; + this.max_events = Pickle::unpickle(stream)?; + this.max_participant_identities = Pickle::unpickle(stream)?; + this.max_event_notifications = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Calendar { + fn default() -> Self { + Self { + default_display_name: Some("Stalwart Calendar".to_string()), + default_href_name: Some("default".to_string()), + max_attendees: 20u64, + max_recurrence_expansions: 3000u64, + max_i_calendar_size: 524288, + max_calendars: Some(250u64), + max_events: Default::default(), + max_participant_identities: Some(100u64), + max_event_notifications: Default::default(), + } + } +} + +impl IntoValue for Calendar { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked( + Property::DefaultDisplayName, + self.default_display_name.into_value(), + ); + map.insert_unchecked( + Property::DefaultHrefName, + self.default_href_name.into_value(), + ); + map.insert_unchecked(Property::MaxAttendees, self.max_attendees.into_value()); + map.insert_unchecked( + Property::MaxRecurrenceExpansions, + self.max_recurrence_expansions.into_value(), + ); + map.insert_unchecked( + Property::MaxICalendarSize, + self.max_i_calendar_size.into_value(), + ); + map.insert_unchecked(Property::MaxCalendars, self.max_calendars.into_value()); + map.insert_unchecked(Property::MaxEvents, self.max_events.into_value()); + map.insert_unchecked( + Property::MaxParticipantIdentities, + self.max_participant_identities.into_value(), + ); + map.insert_unchecked( + Property::MaxEventNotifications, + self.max_event_notifications.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Calendar { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DefaultDisplayName) => self + .default_display_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DefaultHrefName) => self + .default_href_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MaxAttendees) => self.max_attendees.patch(pointer, value), + Some(Property::MaxRecurrenceExpansions) => { + self.max_recurrence_expansions.patch(pointer, value) + } + Some(Property::MaxICalendarSize) => self.max_i_calendar_size.patch(pointer, value), + Some(Property::MaxCalendars) => self.max_calendars.patch(pointer, value), + Some(Property::MaxEvents) => self.max_events.patch(pointer, value), + Some(Property::MaxParticipantIdentities) => { + self.max_participant_identities.patch(pointer, value) + } + Some(Property::MaxEventNotifications) => { + self.max_event_notifications.patch(pointer, value) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for CalendarAlarm { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::CalendarAlarm; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.from_email { + if value.is_empty() { + errors.push(ValidationError::required(Property::FromEmail)); + } + } + let value = &self.from_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::FromName)); + } + if let Some(value) = &self.template { + if value.is_empty() { + errors.push(ValidationError::required(Property::Template)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for CalendarAlarm { + fn pickle(&self, out: &mut Vec) { + self.allow_external_rcpts.pickle(out); + self.enable.pickle(out); + self.from_email.pickle(out); + self.from_name.pickle(out); + self.min_trigger_interval.pickle(out); + self.template.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_external_rcpts = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.from_email = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.min_trigger_interval = Pickle::unpickle(stream)?; + this.template = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CalendarAlarm { + fn default() -> Self { + Self { + allow_external_rcpts: false, + enable: true, + from_email: Default::default(), + from_name: "Stalwart Calendar".to_string(), + min_trigger_interval: Duration::from_millis(3600000), + template: Default::default(), + } + } +} + +impl IntoValue for CalendarAlarm { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked( + Property::AllowExternalRcpts, + self.allow_external_rcpts.into_value(), + ); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::FromEmail, self.from_email.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked( + Property::MinTriggerInterval, + self.min_trigger_interval.into_value(), + ); + map.insert_unchecked(Property::Template, self.template.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CalendarAlarm { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowExternalRcpts) => self.allow_external_rcpts.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::FromEmail) => self + .from_email + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::FromName) => self + .from_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MinTriggerInterval) => self.min_trigger_interval.patch(pointer, value), + Some(Property::Template) => self.template.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for CalendarScheduling { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::CalendarScheduling; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.http_rsvp_url { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpRsvpUrl)); + } + } + let value = &self.itip_max_size; + if *value < 100 { + errors.push(ValidationError::min_value(Property::ItipMaxSize, 100)); + } + let value = &self.max_recipients; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRecipients, 1)); + } + if let Some(value) = &self.email_template { + if value.is_empty() { + errors.push(ValidationError::required(Property::EmailTemplate)); + } + } + if let Some(value) = &self.http_rsvp_template { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpRsvpTemplate)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for CalendarScheduling { + fn pickle(&self, out: &mut Vec) { + self.enable.pickle(out); + self.http_rsvp_enable.pickle(out); + self.http_rsvp_link_expiry.pickle(out); + self.http_rsvp_url.pickle(out); + self.auto_add_invitations.pickle(out); + self.itip_max_size.pickle(out); + self.max_recipients.pickle(out); + self.email_template.pickle(out); + self.http_rsvp_template.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable = Pickle::unpickle(stream)?; + this.http_rsvp_enable = Pickle::unpickle(stream)?; + this.http_rsvp_link_expiry = Pickle::unpickle(stream)?; + this.http_rsvp_url = Pickle::unpickle(stream)?; + this.auto_add_invitations = Pickle::unpickle(stream)?; + this.itip_max_size = Pickle::unpickle(stream)?; + this.max_recipients = Pickle::unpickle(stream)?; + this.email_template = Pickle::unpickle(stream)?; + this.http_rsvp_template = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CalendarScheduling { + fn default() -> Self { + Self { + enable: true, + http_rsvp_enable: true, + http_rsvp_link_expiry: Duration::from_millis(7776000000), + http_rsvp_url: Default::default(), + auto_add_invitations: false, + itip_max_size: 524288, + max_recipients: 100u64, + email_template: Default::default(), + http_rsvp_template: Default::default(), + } + } +} + +impl IntoValue for CalendarScheduling { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::HttpRsvpEnable, self.http_rsvp_enable.into_value()); + map.insert_unchecked( + Property::HttpRsvpLinkExpiry, + self.http_rsvp_link_expiry.into_value(), + ); + map.insert_unchecked(Property::HttpRsvpUrl, self.http_rsvp_url.into_value()); + map.insert_unchecked( + Property::AutoAddInvitations, + self.auto_add_invitations.into_value(), + ); + map.insert_unchecked(Property::ItipMaxSize, self.itip_max_size.into_value()); + map.insert_unchecked(Property::MaxRecipients, self.max_recipients.into_value()); + map.insert_unchecked(Property::EmailTemplate, self.email_template.into_value()); + map.insert_unchecked( + Property::HttpRsvpTemplate, + self.http_rsvp_template.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CalendarScheduling { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::HttpRsvpEnable) => self.http_rsvp_enable.patch(pointer, value), + Some(Property::HttpRsvpLinkExpiry) => self.http_rsvp_link_expiry.patch(pointer, value), + Some(Property::HttpRsvpUrl) => self + .http_rsvp_url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AutoAddInvitations) => self.auto_add_invitations.patch(pointer, value), + Some(Property::ItipMaxSize) => self.itip_max_size.patch(pointer, value), + Some(Property::MaxRecipients) => self.max_recipients.patch(pointer, value), + Some(Property::EmailTemplate) => self.email_template.patch(pointer, value), + Some(Property::HttpRsvpTemplate) => self.http_rsvp_template.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Certificate { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Certificate; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.certificate; + value.validate(errors); + let value = &self.private_key; + value.validate(errors); + let value = &self.subject_alternative_names; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::SubjectAlternativeNames)); + } + } + let value = &self.not_valid_after; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NotValidAfter, value)); + } + let value = &self.not_valid_before; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NotValidBefore, value)); + } + let value = &self.issuer; + if value.is_empty() { + errors.push(ValidationError::required(Property::Issuer)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + for value in self.subject_alternative_names.iter() { + i.text(Property::SubjectAlternativeNames, value); + } + } +} + +impl Pickle for Certificate { + fn pickle(&self, out: &mut Vec) { + self.certificate.pickle(out); + self.private_key.pickle(out); + self.subject_alternative_names.pickle(out); + self.not_valid_after.pickle(out); + self.not_valid_before.pickle(out); + self.issuer.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.certificate = Pickle::unpickle(stream)?; + this.private_key = Pickle::unpickle(stream)?; + this.subject_alternative_names = Pickle::unpickle(stream)?; + this.not_valid_after = Pickle::unpickle(stream)?; + this.not_valid_before = Pickle::unpickle(stream)?; + this.issuer = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Certificate { + fn default() -> Self { + Self { + certificate: Default::default(), + private_key: Default::default(), + subject_alternative_names: Default::default(), + not_valid_after: Default::default(), + not_valid_before: Default::default(), + issuer: Default::default(), + } + } +} + +impl IntoValue for Certificate { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Certificate, self.certificate.into_value()); + map.insert_unchecked(Property::PrivateKey, self.private_key.into_value()); + map.insert_unchecked( + Property::SubjectAlternativeNames, + self.subject_alternative_names.into_value(), + ); + map.insert_unchecked(Property::NotValidAfter, self.not_valid_after.into_value()); + map.insert_unchecked(Property::NotValidBefore, self.not_valid_before.into_value()); + map.insert_unchecked(Property::Issuer, self.issuer.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Certificate { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Certificate) => self.certificate.patch(pointer, value), + Some(Property::PrivateKey) => self.private_key.patch(pointer, value), + Some(Property::SubjectAlternativeNames) => pointer.assert_server_set(), + Some(Property::NotValidAfter) => pointer.assert_server_set(), + Some(Property::NotValidBefore) => pointer.assert_server_set(), + Some(Property::Issuer) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl CertificateManagement { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + CertificateManagement::Manual => true, + CertificateManagement::Automatic(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + CertificateManagement::Manual => {} + CertificateManagement::Automatic(object) => { + object.index(i); + } + } + } +} + +impl Default for CertificateManagement { + fn default() -> Self { + CertificateManagement::Manual + } +} + +impl Pickle for CertificateManagement { + fn pickle(&self, out: &mut Vec) { + match self { + CertificateManagement::Manual => { + 0u16.pickle(out); + } + CertificateManagement::Automatic(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(CertificateManagement::Manual), + 1 => Pickle::unpickle(stream).map(CertificateManagement::Automatic), + _ => None, + } + } +} + +impl IntoValue for CertificateManagement { + fn into_value(self) -> JmapValue<'static> { + match self { + CertificateManagement::Manual => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into())); + JmapValue::Object(obj) + } + CertificateManagement::Automatic(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Automatic".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for CertificateManagement { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + CertificateManagementType::Manual => *self = CertificateManagement::Manual, + CertificateManagementType::Automatic => { + *self = CertificateManagement::Automatic(Default::default()) + } + } + } + match self { + CertificateManagement::Manual => pointer.assert_eof(), + CertificateManagement::Automatic(inner) => inner.patch(pointer, value), + } + } +} + +impl CertificateManagement { + pub fn object_type(&self) -> CertificateManagementType { + match self { + CertificateManagement::Manual => CertificateManagementType::Manual, + CertificateManagement::Automatic(_) => CertificateManagementType::Automatic, + } + } +} + +impl CertificateManagementProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.acme_provider_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AcmeProviderId)); + } + let value = &self.subject_alternative_names; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::SubjectAlternativeNames)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::AcmeProvider, self.acme_provider_id.into(), None); + } +} + +impl Pickle for CertificateManagementProperties { + fn pickle(&self, out: &mut Vec) { + self.acme_provider_id.pickle(out); + self.subject_alternative_names.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.acme_provider_id = Pickle::unpickle(stream)?; + this.subject_alternative_names = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CertificateManagementProperties { + fn default() -> Self { + Self { + acme_provider_id: Default::default(), + subject_alternative_names: Default::default(), + } + } +} + +impl IntoValue for CertificateManagementProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::AcmeProviderId, self.acme_provider_id.into_value()); + map.insert_unchecked( + Property::SubjectAlternativeNames, + self.subject_alternative_names.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CertificateManagementProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AcmeProviderId) => self.acme_provider_id.patch(pointer, value), + Some(Property::SubjectAlternativeNames) => self + .subject_alternative_names + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ClusterListenerGroup { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + ClusterListenerGroup::EnableAll => true, + ClusterListenerGroup::DisableAll => true, + ClusterListenerGroup::EnableSome(inner) => inner.validate(errors), + ClusterListenerGroup::DisableSome(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + ClusterListenerGroup::EnableAll => {} + ClusterListenerGroup::DisableAll => {} + ClusterListenerGroup::EnableSome(object) => { + object.index(i); + } + ClusterListenerGroup::DisableSome(object) => { + object.index(i); + } + } + } +} + +impl Default for ClusterListenerGroup { + fn default() -> Self { + ClusterListenerGroup::EnableAll + } +} + +impl Pickle for ClusterListenerGroup { + fn pickle(&self, out: &mut Vec) { + match self { + ClusterListenerGroup::EnableAll => { + 0u16.pickle(out); + } + ClusterListenerGroup::DisableAll => { + 1u16.pickle(out); + } + ClusterListenerGroup::EnableSome(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + ClusterListenerGroup::DisableSome(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(ClusterListenerGroup::EnableAll), + 1 => Some(ClusterListenerGroup::DisableAll), + 2 => Pickle::unpickle(stream).map(ClusterListenerGroup::EnableSome), + 3 => Pickle::unpickle(stream).map(ClusterListenerGroup::DisableSome), + _ => None, + } + } +} + +impl IntoValue for ClusterListenerGroup { + fn into_value(self) -> JmapValue<'static> { + match self { + ClusterListenerGroup::EnableAll => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EnableAll".into())); + JmapValue::Object(obj) + } + ClusterListenerGroup::DisableAll => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DisableAll".into())); + JmapValue::Object(obj) + } + ClusterListenerGroup::EnableSome(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnableSome".into())); + obj + } + ClusterListenerGroup::DisableSome(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DisableSome".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for ClusterListenerGroup { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + ClusterListenerGroupType::EnableAll => *self = ClusterListenerGroup::EnableAll, + ClusterListenerGroupType::DisableAll => *self = ClusterListenerGroup::DisableAll, + ClusterListenerGroupType::EnableSome => { + *self = ClusterListenerGroup::EnableSome(Default::default()) + } + ClusterListenerGroupType::DisableSome => { + *self = ClusterListenerGroup::DisableSome(Default::default()) + } + } + } + match self { + ClusterListenerGroup::EnableAll => pointer.assert_eof(), + ClusterListenerGroup::DisableAll => pointer.assert_eof(), + ClusterListenerGroup::EnableSome(inner) => inner.patch(pointer, value), + ClusterListenerGroup::DisableSome(inner) => inner.patch(pointer, value), + } + } +} + +impl ClusterListenerGroup { + pub fn object_type(&self) -> ClusterListenerGroupType { + match self { + ClusterListenerGroup::EnableAll => ClusterListenerGroupType::EnableAll, + ClusterListenerGroup::DisableAll => ClusterListenerGroupType::DisableAll, + ClusterListenerGroup::EnableSome(_) => ClusterListenerGroupType::EnableSome, + ClusterListenerGroup::DisableSome(_) => ClusterListenerGroupType::DisableSome, + } + } +} + +impl ClusterListenerGroupProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.listener_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::ListenerIds)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + for id in self.listener_ids.iter() { + i.foreign_key(ObjectType::NetworkListener, Some(*id), None); + } + } +} + +impl Pickle for ClusterListenerGroupProperties { + fn pickle(&self, out: &mut Vec) { + self.listener_ids.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.listener_ids = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ClusterListenerGroupProperties { + fn default() -> Self { + Self { + listener_ids: Default::default(), + } + } +} + +impl IntoValue for ClusterListenerGroupProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::ListenerIds, self.listener_ids.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ClusterListenerGroupProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ListenerIds) => self.listener_ids.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ClusterNode { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ClusterNode; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.hostname; + if value.is_empty() { + errors.push(ValidationError::required(Property::Hostname)); + } + let value = &self.last_renewal; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::LastRenewal, value)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for ClusterNode { + fn pickle(&self, out: &mut Vec) { + self.node_id.pickle(out); + self.hostname.pickle(out); + self.last_renewal.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.node_id = Pickle::unpickle(stream)?; + this.hostname = Pickle::unpickle(stream)?; + this.last_renewal = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ClusterNode { + fn default() -> Self { + Self { + node_id: 1u64, + hostname: Default::default(), + last_renewal: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for ClusterNode { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::NodeId, self.node_id.into_value()); + map.insert_unchecked(Property::Hostname, self.hostname.into_value()); + map.insert_unchecked(Property::LastRenewal, self.last_renewal.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ClusterNode { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::NodeId) => self.node_id.patch(pointer, value), + Some(Property::Hostname) => self.hostname.patch(pointer, value), + Some(Property::LastRenewal) => self.last_renewal.patch(pointer, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ClusterRole { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ClusterRole; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.tasks; + value.validate(errors); + let value = &self.listeners; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + self.listeners.index(i); + } +} + +impl Pickle for ClusterRole { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.tasks.pickle(out); + self.listeners.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.tasks = Pickle::unpickle(stream)?; + this.listeners = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ClusterRole { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + tasks: Default::default(), + listeners: Default::default(), + } + } +} + +impl IntoValue for ClusterRole { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Tasks, self.tasks.into_value()); + map.insert_unchecked(Property::Listeners, self.listeners.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ClusterRole { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Tasks) => self.tasks.patch(pointer, value), + Some(Property::Listeners) => self.listeners.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ClusterTaskGroup { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + ClusterTaskGroup::EnableAll => true, + ClusterTaskGroup::DisableAll => true, + ClusterTaskGroup::EnableSome(inner) => inner.validate(errors), + ClusterTaskGroup::DisableSome(inner) => inner.validate(errors), + } + } +} + +impl Default for ClusterTaskGroup { + fn default() -> Self { + ClusterTaskGroup::EnableAll + } +} + +impl Pickle for ClusterTaskGroup { + fn pickle(&self, out: &mut Vec) { + match self { + ClusterTaskGroup::EnableAll => { + 0u16.pickle(out); + } + ClusterTaskGroup::DisableAll => { + 1u16.pickle(out); + } + ClusterTaskGroup::EnableSome(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + ClusterTaskGroup::DisableSome(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(ClusterTaskGroup::EnableAll), + 1 => Some(ClusterTaskGroup::DisableAll), + 2 => Pickle::unpickle(stream).map(ClusterTaskGroup::EnableSome), + 3 => Pickle::unpickle(stream).map(ClusterTaskGroup::DisableSome), + _ => None, + } + } +} + +impl IntoValue for ClusterTaskGroup { + fn into_value(self) -> JmapValue<'static> { + match self { + ClusterTaskGroup::EnableAll => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EnableAll".into())); + JmapValue::Object(obj) + } + ClusterTaskGroup::DisableAll => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DisableAll".into())); + JmapValue::Object(obj) + } + ClusterTaskGroup::EnableSome(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnableSome".into())); + obj + } + ClusterTaskGroup::DisableSome(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DisableSome".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for ClusterTaskGroup { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + ClusterTaskGroupType::EnableAll => *self = ClusterTaskGroup::EnableAll, + ClusterTaskGroupType::DisableAll => *self = ClusterTaskGroup::DisableAll, + ClusterTaskGroupType::EnableSome => { + *self = ClusterTaskGroup::EnableSome(Default::default()) + } + ClusterTaskGroupType::DisableSome => { + *self = ClusterTaskGroup::DisableSome(Default::default()) + } + } + } + match self { + ClusterTaskGroup::EnableAll => pointer.assert_eof(), + ClusterTaskGroup::DisableAll => pointer.assert_eof(), + ClusterTaskGroup::EnableSome(inner) => inner.patch(pointer, value), + ClusterTaskGroup::DisableSome(inner) => inner.patch(pointer, value), + } + } +} + +impl ClusterTaskGroup { + pub fn object_type(&self) -> ClusterTaskGroupType { + match self { + ClusterTaskGroup::EnableAll => ClusterTaskGroupType::EnableAll, + ClusterTaskGroup::DisableAll => ClusterTaskGroupType::DisableAll, + ClusterTaskGroup::EnableSome(_) => ClusterTaskGroupType::EnableSome, + ClusterTaskGroup::DisableSome(_) => ClusterTaskGroupType::DisableSome, + } + } +} + +impl ClusterTaskGroupProperties { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for ClusterTaskGroupProperties { + fn pickle(&self, out: &mut Vec) { + self.task_types.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.task_types = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ClusterTaskGroupProperties { + fn default() -> Self { + Self { + task_types: Default::default(), + } + } +} + +impl IntoValue for ClusterTaskGroupProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::TaskTypes, self.task_types.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ClusterTaskGroupProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::TaskTypes) => self.task_types.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Coordinator { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Coordinator; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Coordinator::Disabled => true, + Coordinator::Default => true, + Coordinator::Kafka(inner) => inner.validate(errors), + Coordinator::Nats(inner) => inner.validate(errors), + Coordinator::Zenoh(inner) => inner.validate(errors), + Coordinator::Redis(inner) => inner.validate(errors), + Coordinator::RedisCluster(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for Coordinator { + fn default() -> Self { + Coordinator::Disabled + } +} + +impl Pickle for Coordinator { + fn pickle(&self, out: &mut Vec) { + match self { + Coordinator::Disabled => { + 0u16.pickle(out); + } + Coordinator::Default => { + 1u16.pickle(out); + } + Coordinator::Kafka(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + Coordinator::Nats(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + Coordinator::Zenoh(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + Coordinator::Redis(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + Coordinator::RedisCluster(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(Coordinator::Disabled), + 1 => Some(Coordinator::Default), + 2 => Pickle::unpickle(stream).map(Coordinator::Kafka), + 3 => Pickle::unpickle(stream).map(Coordinator::Nats), + 4 => Pickle::unpickle(stream).map(Coordinator::Zenoh), + 5 => Pickle::unpickle(stream).map(Coordinator::Redis), + 6 => Pickle::unpickle(stream).map(Coordinator::RedisCluster), + _ => None, + } + } +} + +impl IntoValue for Coordinator { + fn into_value(self) -> JmapValue<'static> { + match self { + Coordinator::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + Coordinator::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + Coordinator::Kafka(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Kafka".into())); + obj + } + Coordinator::Nats(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Nats".into())); + obj + } + Coordinator::Zenoh(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Zenoh".into())); + obj + } + Coordinator::Redis(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Redis".into())); + obj + } + Coordinator::RedisCluster(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Coordinator { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + CoordinatorType::Disabled => *self = Coordinator::Disabled, + CoordinatorType::Default => *self = Coordinator::Default, + CoordinatorType::Kafka => *self = Coordinator::Kafka(Default::default()), + CoordinatorType::Nats => *self = Coordinator::Nats(Default::default()), + CoordinatorType::Zenoh => *self = Coordinator::Zenoh(Default::default()), + CoordinatorType::Redis => *self = Coordinator::Redis(Default::default()), + CoordinatorType::RedisCluster => { + *self = Coordinator::RedisCluster(Default::default()) + } + } + } + match self { + Coordinator::Disabled => pointer.assert_eof(), + Coordinator::Default => pointer.assert_eof(), + Coordinator::Kafka(inner) => inner.patch(pointer, value), + Coordinator::Nats(inner) => inner.patch(pointer, value), + Coordinator::Zenoh(inner) => inner.patch(pointer, value), + Coordinator::Redis(inner) => inner.patch(pointer, value), + Coordinator::RedisCluster(inner) => inner.patch(pointer, value), + } + } +} + +impl Coordinator { + pub fn object_type(&self) -> CoordinatorType { + match self { + Coordinator::Disabled => CoordinatorType::Disabled, + Coordinator::Default => CoordinatorType::Default, + Coordinator::Kafka(_) => CoordinatorType::Kafka, + Coordinator::Nats(_) => CoordinatorType::Nats, + Coordinator::Zenoh(_) => CoordinatorType::Zenoh, + Coordinator::Redis(_) => CoordinatorType::Redis, + Coordinator::RedisCluster(_) => CoordinatorType::RedisCluster, + } + } +} + +impl Credential { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Credential::Password(inner) => inner.validate(errors), + Credential::AppPassword(inner) => inner.validate(errors), + Credential::ApiKey(inner) => inner.validate(errors), + } + } +} + +impl Default for Credential { + fn default() -> Self { + Credential::Password(Default::default()) + } +} + +impl Pickle for Credential { + fn pickle(&self, out: &mut Vec) { + match self { + Credential::Password(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Credential::AppPassword(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Credential::ApiKey(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Credential::Password), + 1 => Pickle::unpickle(stream).map(Credential::AppPassword), + 2 => Pickle::unpickle(stream).map(Credential::ApiKey), + _ => None, + } + } +} + +impl IntoValue for Credential { + fn into_value(self) -> JmapValue<'static> { + match self { + Credential::Password(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Password".into())); + obj + } + Credential::AppPassword(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("AppPassword".into())); + obj + } + Credential::ApiKey(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("ApiKey".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Credential { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + CredentialType::Password => *self = Credential::Password(Default::default()), + CredentialType::AppPassword => *self = Credential::AppPassword(Default::default()), + CredentialType::ApiKey => *self = Credential::ApiKey(Default::default()), + } + } + match self { + Credential::Password(inner) => inner.patch(pointer, value), + Credential::AppPassword(inner) => inner.patch(pointer, value), + Credential::ApiKey(inner) => inner.patch(pointer, value), + } + } +} + +impl Credential { + pub fn object_type(&self) -> CredentialType { + match self { + Credential::Password(_) => CredentialType::Password, + Credential::AppPassword(_) => CredentialType::AppPassword, + Credential::ApiKey(_) => CredentialType::ApiKey, + } + } +} + +impl CredentialPermissions { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + CredentialPermissions::Inherit => true, + CredentialPermissions::Disable(inner) => inner.validate(errors), + CredentialPermissions::Replace(inner) => inner.validate(errors), + } + } +} + +impl Default for CredentialPermissions { + fn default() -> Self { + CredentialPermissions::Inherit + } +} + +impl Pickle for CredentialPermissions { + fn pickle(&self, out: &mut Vec) { + match self { + CredentialPermissions::Inherit => { + 0u16.pickle(out); + } + CredentialPermissions::Disable(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + CredentialPermissions::Replace(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(CredentialPermissions::Inherit), + 1 => Pickle::unpickle(stream).map(CredentialPermissions::Disable), + 2 => Pickle::unpickle(stream).map(CredentialPermissions::Replace), + _ => None, + } + } +} + +impl IntoValue for CredentialPermissions { + fn into_value(self) -> JmapValue<'static> { + match self { + CredentialPermissions::Inherit => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Inherit".into())); + JmapValue::Object(obj) + } + CredentialPermissions::Disable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Disable".into())); + obj + } + CredentialPermissions::Replace(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Replace".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for CredentialPermissions { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + CredentialPermissionsType::Inherit => *self = CredentialPermissions::Inherit, + CredentialPermissionsType::Disable => { + *self = CredentialPermissions::Disable(Default::default()) + } + CredentialPermissionsType::Replace => { + *self = CredentialPermissions::Replace(Default::default()) + } + } + } + match self { + CredentialPermissions::Inherit => pointer.assert_eof(), + CredentialPermissions::Disable(inner) => inner.patch(pointer, value), + CredentialPermissions::Replace(inner) => inner.patch(pointer, value), + } + } +} + +impl CredentialPermissions { + pub fn object_type(&self) -> CredentialPermissionsType { + match self { + CredentialPermissions::Inherit => CredentialPermissionsType::Inherit, + CredentialPermissions::Disable(_) => CredentialPermissionsType::Disable, + CredentialPermissions::Replace(_) => CredentialPermissionsType::Replace, + } + } +} + +impl CredentialPermissionsList { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for CredentialPermissionsList { + fn pickle(&self, out: &mut Vec) { + self.permissions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.permissions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CredentialPermissionsList { + fn default() -> Self { + Self { + permissions: Default::default(), + } + } +} + +impl IntoValue for CredentialPermissionsList { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CredentialPermissionsList { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Cron { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Cron::Daily(inner) => inner.validate(errors), + Cron::Weekly(inner) => inner.validate(errors), + Cron::Hourly(inner) => inner.validate(errors), + } + } +} + +impl Default for Cron { + fn default() -> Self { + Cron::Daily(Default::default()) + } +} + +impl Pickle for Cron { + fn pickle(&self, out: &mut Vec) { + match self { + Cron::Daily(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Cron::Weekly(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Cron::Hourly(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Cron::Daily), + 1 => Pickle::unpickle(stream).map(Cron::Weekly), + 2 => Pickle::unpickle(stream).map(Cron::Hourly), + _ => None, + } + } +} + +impl IntoValue for Cron { + fn into_value(self) -> JmapValue<'static> { + match self { + Cron::Daily(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Daily".into())); + obj + } + Cron::Weekly(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Weekly".into())); + obj + } + Cron::Hourly(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Hourly".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Cron { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + CronType::Daily => *self = Cron::Daily(Default::default()), + CronType::Weekly => *self = Cron::Weekly(Default::default()), + CronType::Hourly => *self = Cron::Hourly(Default::default()), + } + } + match self { + Cron::Daily(inner) => inner.patch(pointer, value), + Cron::Weekly(inner) => inner.patch(pointer, value), + Cron::Hourly(inner) => inner.patch(pointer, value), + } + } +} + +impl Cron { + pub fn object_type(&self) -> CronType { + match self { + Cron::Daily(_) => CronType::Daily, + Cron::Weekly(_) => CronType::Weekly, + Cron::Hourly(_) => CronType::Hourly, + } + } +} + +impl CronDaily { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.hour; + if *value > 23 { + errors.push(ValidationError::max_value(Property::Hour, 23)); + } + let value = &self.minute; + if *value > 59 { + errors.push(ValidationError::max_value(Property::Minute, 59)); + } + errors.len() == neb + } +} + +impl Pickle for CronDaily { + fn pickle(&self, out: &mut Vec) { + self.hour.pickle(out); + self.minute.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.hour = Pickle::unpickle(stream)?; + this.minute = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CronDaily { + fn default() -> Self { + Self { + hour: 0u64, + minute: 0u64, + } + } +} + +impl IntoValue for CronDaily { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Hour, self.hour.into_value()); + map.insert_unchecked(Property::Minute, self.minute.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CronDaily { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Hour) => self.hour.patch(pointer, value), + Some(Property::Minute) => self.minute.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl CronHourly { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.minute; + if *value > 59 { + errors.push(ValidationError::max_value(Property::Minute, 59)); + } + errors.len() == neb + } +} + +impl Pickle for CronHourly { + fn pickle(&self, out: &mut Vec) { + self.minute.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.minute = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CronHourly { + fn default() -> Self { + Self { minute: 0u64 } + } +} + +impl IntoValue for CronHourly { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Minute, self.minute.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CronHourly { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Minute) => self.minute.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl CronWeekly { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.day; + if *value > 6 { + errors.push(ValidationError::max_value(Property::Day, 6)); + } + let value = &self.hour; + if *value > 23 { + errors.push(ValidationError::max_value(Property::Hour, 23)); + } + let value = &self.minute; + if *value > 59 { + errors.push(ValidationError::max_value(Property::Minute, 59)); + } + errors.len() == neb + } +} + +impl Pickle for CronWeekly { + fn pickle(&self, out: &mut Vec) { + self.day.pickle(out); + self.hour.pickle(out); + self.minute.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.day = Pickle::unpickle(stream)?; + this.hour = Pickle::unpickle(stream)?; + this.minute = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CronWeekly { + fn default() -> Self { + Self { + day: 0u64, + hour: 0u64, + minute: 0u64, + } + } +} + +impl IntoValue for CronWeekly { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Day, self.day.into_value()); + map.insert_unchecked(Property::Hour, self.hour.into_value()); + map.insert_unchecked(Property::Minute, self.minute.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CronWeekly { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Day) => self.day.patch(pointer, value), + Some(Property::Hour) => self.hour.patch(pointer, value), + Some(Property::Minute) => self.minute.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl CustomRoles { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::RoleIds)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + for id in self.role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + } +} + +impl Pickle for CustomRoles { + fn pickle(&self, out: &mut Vec) { + self.role_ids.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.role_ids = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for CustomRoles { + fn default() -> Self { + Self { + role_ids: Default::default(), + } + } +} + +impl IntoValue for CustomRoles { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::RoleIds, self.role_ids.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for CustomRoles { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::RoleIds) => self.role_ids.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DataRetention { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DataRetention; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.expunge_schedule; + value.validate(errors); + let value = &self.data_cleanup_schedule; + value.validate(errors); + let value = &self.blob_cleanup_schedule; + value.validate(errors); + let value = &self.metrics_collection_interval; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for DataRetention { + fn pickle(&self, out: &mut Vec) { + self.expunge_trash_after.pickle(out); + self.expunge_submissions_after.pickle(out); + self.expunge_share_notify_after.pickle(out); + self.expunge_scheduling_inbox_after.pickle(out); + self.expunge_schedule.pickle(out); + self.data_cleanup_schedule.pickle(out); + self.blob_cleanup_schedule.pickle(out); + self.max_changes_history.pickle(out); + self.archive_deleted_items_for.pickle(out); + self.archive_deleted_accounts_for.pickle(out); + self.hold_mta_reports_for.pickle(out); + self.hold_traces_for.pickle(out); + self.hold_metrics_for.pickle(out); + self.metrics_collection_interval.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.expunge_trash_after = Pickle::unpickle(stream)?; + this.expunge_submissions_after = Pickle::unpickle(stream)?; + this.expunge_share_notify_after = Pickle::unpickle(stream)?; + this.expunge_scheduling_inbox_after = Pickle::unpickle(stream)?; + this.expunge_schedule = Pickle::unpickle(stream)?; + this.data_cleanup_schedule = Pickle::unpickle(stream)?; + this.blob_cleanup_schedule = Pickle::unpickle(stream)?; + this.max_changes_history = Pickle::unpickle(stream)?; + this.archive_deleted_items_for = Pickle::unpickle(stream)?; + this.archive_deleted_accounts_for = Pickle::unpickle(stream)?; + this.hold_mta_reports_for = Pickle::unpickle(stream)?; + this.hold_traces_for = Pickle::unpickle(stream)?; + this.hold_metrics_for = Pickle::unpickle(stream)?; + this.metrics_collection_interval = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DataRetention { + fn default() -> Self { + Self { + expunge_trash_after: Some(Duration::from_millis(2592000000)), + expunge_submissions_after: Some(Duration::from_millis(259200000)), + expunge_share_notify_after: Some(Duration::from_millis(2592000000)), + expunge_scheduling_inbox_after: Some(Duration::from_millis(2592000000)), + expunge_schedule: Cron::Daily(CronDaily { + hour: 0u64, + minute: 0u64, + }), + data_cleanup_schedule: Cron::Daily(CronDaily { + hour: 2u64, + minute: 0u64, + }), + blob_cleanup_schedule: Cron::Daily(CronDaily { + hour: 4u64, + minute: 0u64, + }), + max_changes_history: Some(10000u64), + archive_deleted_items_for: Default::default(), + archive_deleted_accounts_for: Default::default(), + hold_mta_reports_for: Some(Duration::from_millis(2592000000)), + hold_traces_for: Some(Duration::from_millis(2592000000)), + hold_metrics_for: Some(Duration::from_millis(7776000000)), + metrics_collection_interval: Cron::Hourly(CronHourly { minute: 0u64 }), + } + } +} + +impl IntoValue for DataRetention { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked( + Property::ExpungeTrashAfter, + self.expunge_trash_after.into_value(), + ); + map.insert_unchecked( + Property::ExpungeSubmissionsAfter, + self.expunge_submissions_after.into_value(), + ); + map.insert_unchecked( + Property::ExpungeShareNotifyAfter, + self.expunge_share_notify_after.into_value(), + ); + map.insert_unchecked( + Property::ExpungeSchedulingInboxAfter, + self.expunge_scheduling_inbox_after.into_value(), + ); + map.insert_unchecked( + Property::ExpungeSchedule, + self.expunge_schedule.into_value(), + ); + map.insert_unchecked( + Property::DataCleanupSchedule, + self.data_cleanup_schedule.into_value(), + ); + map.insert_unchecked( + Property::BlobCleanupSchedule, + self.blob_cleanup_schedule.into_value(), + ); + map.insert_unchecked( + Property::MaxChangesHistory, + self.max_changes_history.into_value(), + ); + map.insert_unchecked( + Property::ArchiveDeletedItemsFor, + self.archive_deleted_items_for.into_value(), + ); + map.insert_unchecked( + Property::ArchiveDeletedAccountsFor, + self.archive_deleted_accounts_for.into_value(), + ); + map.insert_unchecked( + Property::HoldMtaReportsFor, + self.hold_mta_reports_for.into_value(), + ); + map.insert_unchecked(Property::HoldTracesFor, self.hold_traces_for.into_value()); + map.insert_unchecked(Property::HoldMetricsFor, self.hold_metrics_for.into_value()); + map.insert_unchecked( + Property::MetricsCollectionInterval, + self.metrics_collection_interval.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DataRetention { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ExpungeTrashAfter) => self.expunge_trash_after.patch(pointer, value), + Some(Property::ExpungeSubmissionsAfter) => { + self.expunge_submissions_after.patch(pointer, value) + } + Some(Property::ExpungeShareNotifyAfter) => { + self.expunge_share_notify_after.patch(pointer, value) + } + Some(Property::ExpungeSchedulingInboxAfter) => { + self.expunge_scheduling_inbox_after.patch(pointer, value) + } + Some(Property::ExpungeSchedule) => self.expunge_schedule.patch(pointer, value), + Some(Property::DataCleanupSchedule) => self.data_cleanup_schedule.patch(pointer, value), + Some(Property::BlobCleanupSchedule) => self.blob_cleanup_schedule.patch(pointer, value), + Some(Property::MaxChangesHistory) => self.max_changes_history.patch(pointer, value), + Some(Property::ArchiveDeletedItemsFor) => { + self.archive_deleted_items_for.patch(pointer, value) + } + Some(Property::ArchiveDeletedAccountsFor) => { + self.archive_deleted_accounts_for.patch(pointer, value) + } + Some(Property::HoldMtaReportsFor) => self.hold_mta_reports_for.patch(pointer, value), + Some(Property::HoldTracesFor) => self.hold_traces_for.patch(pointer, value), + Some(Property::HoldMetricsFor) => self.hold_metrics_for.patch(pointer, value), + Some(Property::MetricsCollectionInterval) => { + self.metrics_collection_interval.patch(pointer, value) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DataStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DataStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DataStore::RocksDb(inner) => inner.validate(errors), + DataStore::Sqlite(inner) => inner.validate(errors), + DataStore::FoundationDb(inner) => inner.validate(errors), + DataStore::PostgreSql(inner) => inner.validate(errors), + DataStore::MySql(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for DataStore { + fn default() -> Self { + DataStore::RocksDb(Default::default()) + } +} + +impl Pickle for DataStore { + fn pickle(&self, out: &mut Vec) { + match self { + DataStore::RocksDb(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + DataStore::Sqlite(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DataStore::FoundationDb(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DataStore::PostgreSql(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + DataStore::MySql(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(DataStore::RocksDb), + 1 => Pickle::unpickle(stream).map(DataStore::Sqlite), + 2 => Pickle::unpickle(stream).map(DataStore::FoundationDb), + 3 => Pickle::unpickle(stream).map(DataStore::PostgreSql), + 4 => Pickle::unpickle(stream).map(DataStore::MySql), + _ => None, + } + } +} + +impl IntoValue for DataStore { + fn into_value(self) -> JmapValue<'static> { + match self { + DataStore::RocksDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RocksDb".into())); + obj + } + DataStore::Sqlite(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into())); + obj + } + DataStore::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + DataStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + DataStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DataStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DataStoreType::RocksDb => *self = DataStore::RocksDb(Default::default()), + DataStoreType::Sqlite => *self = DataStore::Sqlite(Default::default()), + DataStoreType::FoundationDb => *self = DataStore::FoundationDb(Default::default()), + DataStoreType::PostgreSql => *self = DataStore::PostgreSql(Default::default()), + DataStoreType::MySql => *self = DataStore::MySql(Default::default()), + } + } + match self { + DataStore::RocksDb(inner) => inner.patch(pointer, value), + DataStore::Sqlite(inner) => inner.patch(pointer, value), + DataStore::FoundationDb(inner) => inner.patch(pointer, value), + DataStore::PostgreSql(inner) => inner.patch(pointer, value), + DataStore::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl DataStore { + pub fn object_type(&self) -> DataStoreType { + match self { + DataStore::RocksDb(_) => DataStoreType::RocksDb, + DataStore::Sqlite(_) => DataStoreType::Sqlite, + DataStore::FoundationDb(_) => DataStoreType::FoundationDb, + DataStore::PostgreSql(_) => DataStoreType::PostgreSql, + DataStore::MySql(_) => DataStoreType::MySql, + } + } +} + +impl DeliveryError { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.error_message { + if value.is_empty() { + errors.push(ValidationError::required(Property::ErrorMessage)); + } + } + if let Some(value) = &self.error_command { + if value.is_empty() { + errors.push(ValidationError::required(Property::ErrorCommand)); + } + } + if let Some(value) = &self.response_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseHostname)); + } + } + if let Some(value) = &self.response_code { + if *value < 100 { + errors.push(ValidationError::min_value(Property::ResponseCode, 100)); + } + if *value > 599 { + errors.push(ValidationError::max_value(Property::ResponseCode, 599)); + } + } + if let Some(value) = &self.response_enhanced { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseEnhanced)); + } + } + if let Some(value) = &self.response_message { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseMessage)); + } + } + errors.len() == neb + } +} + +impl Pickle for DeliveryError { + fn pickle(&self, out: &mut Vec) { + self.error_type.pickle(out); + self.error_message.pickle(out); + self.error_command.pickle(out); + self.response_hostname.pickle(out); + self.response_code.pickle(out); + self.response_enhanced.pickle(out); + self.response_message.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.error_type = Pickle::unpickle(stream)?; + this.error_message = Pickle::unpickle(stream)?; + this.error_command = Pickle::unpickle(stream)?; + this.response_hostname = Pickle::unpickle(stream)?; + this.response_code = Pickle::unpickle(stream)?; + this.response_enhanced = Pickle::unpickle(stream)?; + this.response_message = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DeliveryError { + fn default() -> Self { + Self { + error_type: Default::default(), + error_message: Default::default(), + error_command: Default::default(), + response_hostname: Default::default(), + response_code: Default::default(), + response_enhanced: Default::default(), + response_message: Default::default(), + } + } +} + +impl IntoValue for DeliveryError { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::ErrorType, self.error_type.into_value()); + map.insert_unchecked(Property::ErrorMessage, self.error_message.into_value()); + map.insert_unchecked(Property::ErrorCommand, self.error_command.into_value()); + map.insert_unchecked( + Property::ResponseHostname, + self.response_hostname.into_value(), + ); + map.insert_unchecked(Property::ResponseCode, self.response_code.into_value()); + map.insert_unchecked( + Property::ResponseEnhanced, + self.response_enhanced.into_value(), + ); + map.insert_unchecked( + Property::ResponseMessage, + self.response_message.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DeliveryError { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ErrorType) => self.error_type.patch(pointer, value), + Some(Property::ErrorMessage) => self.error_message.patch(pointer, value), + Some(Property::ErrorCommand) => self.error_command.patch(pointer, value), + Some(Property::ResponseHostname) => self.response_hostname.patch(pointer, value), + Some(Property::ResponseCode) => self.response_code.patch(pointer, value), + Some(Property::ResponseEnhanced) => self.response_enhanced.patch(pointer, value), + Some(Property::ResponseMessage) => self.response_message.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Directory { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Directory; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Directory::Ldap(inner) => inner.validate(errors), + Directory::Sql(inner) => inner.validate(errors), + Directory::Oidc(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + Directory::Ldap(object) => { + object.index(i); + } + Directory::Sql(object) => { + object.index(i); + } + Directory::Oidc(object) => { + object.index(i); + } + } + } +} + +impl Default for Directory { + fn default() -> Self { + Directory::Ldap(Default::default()) + } +} + +impl Pickle for Directory { + fn pickle(&self, out: &mut Vec) { + match self { + Directory::Ldap(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Directory::Sql(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Directory::Oidc(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Directory::Ldap), + 1 => Pickle::unpickle(stream).map(Directory::Sql), + 2 => Pickle::unpickle(stream).map(Directory::Oidc), + _ => None, + } + } +} + +impl IntoValue for Directory { + fn into_value(self) -> JmapValue<'static> { + match self { + Directory::Ldap(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ldap".into())); + obj + } + Directory::Sql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sql".into())); + obj + } + Directory::Oidc(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Oidc".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Directory { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DirectoryType::Ldap => *self = Directory::Ldap(Default::default()), + DirectoryType::Sql => *self = Directory::Sql(Default::default()), + DirectoryType::Oidc => *self = Directory::Oidc(Default::default()), + } + } + match self { + Directory::Ldap(inner) => inner.patch(pointer, value), + Directory::Sql(inner) => inner.patch(pointer, value), + Directory::Oidc(inner) => inner.patch(pointer, value), + } + } +} + +impl Directory { + pub fn object_type(&self) -> DirectoryType { + match self { + Directory::Ldap(_) => DirectoryType::Ldap, + Directory::Sql(_) => DirectoryType::Sql, + Directory::Oidc(_) => DirectoryType::Oidc, + } + } +} + +impl DirectoryBootstrap { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DirectoryBootstrap::Internal => true, + DirectoryBootstrap::Ldap(inner) => inner.validate(errors), + DirectoryBootstrap::Sql(inner) => inner.validate(errors), + DirectoryBootstrap::Oidc(inner) => inner.validate(errors), + } + } +} + +impl Default for DirectoryBootstrap { + fn default() -> Self { + DirectoryBootstrap::Internal + } +} + +impl Pickle for DirectoryBootstrap { + fn pickle(&self, out: &mut Vec) { + match self { + DirectoryBootstrap::Internal => { + 0u16.pickle(out); + } + DirectoryBootstrap::Ldap(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DirectoryBootstrap::Sql(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DirectoryBootstrap::Oidc(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(DirectoryBootstrap::Internal), + 1 => Pickle::unpickle(stream).map(DirectoryBootstrap::Ldap), + 2 => Pickle::unpickle(stream).map(DirectoryBootstrap::Sql), + 3 => Pickle::unpickle(stream).map(DirectoryBootstrap::Oidc), + _ => None, + } + } +} + +impl IntoValue for DirectoryBootstrap { + fn into_value(self) -> JmapValue<'static> { + match self { + DirectoryBootstrap::Internal => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Internal".into())); + JmapValue::Object(obj) + } + DirectoryBootstrap::Ldap(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ldap".into())); + obj + } + DirectoryBootstrap::Sql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sql".into())); + obj + } + DirectoryBootstrap::Oidc(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Oidc".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DirectoryBootstrap { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DirectoryBootstrapType::Internal => *self = DirectoryBootstrap::Internal, + DirectoryBootstrapType::Ldap => { + *self = DirectoryBootstrap::Ldap(Default::default()) + } + DirectoryBootstrapType::Sql => *self = DirectoryBootstrap::Sql(Default::default()), + DirectoryBootstrapType::Oidc => { + *self = DirectoryBootstrap::Oidc(Default::default()) + } + } + } + match self { + DirectoryBootstrap::Internal => pointer.assert_eof(), + DirectoryBootstrap::Ldap(inner) => inner.patch(pointer, value), + DirectoryBootstrap::Sql(inner) => inner.patch(pointer, value), + DirectoryBootstrap::Oidc(inner) => inner.patch(pointer, value), + } + } +} + +impl DirectoryBootstrap { + pub fn object_type(&self) -> DirectoryBootstrapType { + match self { + DirectoryBootstrap::Internal => DirectoryBootstrapType::Internal, + DirectoryBootstrap::Ldap(_) => DirectoryBootstrapType::Ldap, + DirectoryBootstrap::Sql(_) => DirectoryBootstrapType::Sql, + DirectoryBootstrap::Oidc(_) => DirectoryBootstrapType::Oidc, + } + } +} + +impl Dkim1Signature { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.auid { + if value.is_empty() { + errors.push(ValidationError::required(Property::Auid)); + } + } + let value = &self.headers; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Headers)); + } + } + let value = &self.private_key; + value.validate(errors); + if let Some(value) = &self.third_party { + if value.is_empty() { + errors.push(ValidationError::required(Property::ThirdParty)); + } + } + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.selector; + if value.is_empty() { + errors.push(ValidationError::required(Property::Selector)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.next_transition_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NextTransitionAt, value)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + i.search(Property::DomainId, &self.domain_id); + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for Dkim1Signature { + fn pickle(&self, out: &mut Vec) { + self.auid.pickle(out); + self.canonicalization.pickle(out); + self.expire.pickle(out); + self.headers.pickle(out); + self.private_key.pickle(out); + self.report.pickle(out); + self.third_party.pickle(out); + self.third_party_hash.pickle(out); + self.domain_id.pickle(out); + self.member_tenant_id.pickle(out); + self.selector.pickle(out); + self.created_at.pickle(out); + self.next_transition_at.pickle(out); + self.stage.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.auid = Pickle::unpickle(stream)?; + this.canonicalization = Pickle::unpickle(stream)?; + this.expire = Pickle::unpickle(stream)?; + this.headers = Pickle::unpickle(stream)?; + this.private_key = Pickle::unpickle(stream)?; + this.report = Pickle::unpickle(stream)?; + this.third_party = Pickle::unpickle(stream)?; + this.third_party_hash = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.selector = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.next_transition_at = Pickle::unpickle(stream)?; + this.stage = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Dkim1Signature { + fn default() -> Self { + Self { + auid: Default::default(), + canonicalization: DkimCanonicalization::RelaxedRelaxed, + expire: Default::default(), + headers: Map::new(vec![ + "From".to_string(), + "To".to_string(), + "Date".to_string(), + "Subject".to_string(), + "Message-ID".to_string(), + ]), + private_key: Default::default(), + report: true, + third_party: Default::default(), + third_party_hash: Default::default(), + domain_id: Default::default(), + member_tenant_id: Default::default(), + selector: Default::default(), + created_at: Default::default(), + next_transition_at: Default::default(), + stage: DkimRotationStage::Active, + } + } +} + +impl IntoValue for Dkim1Signature { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked(Property::Auid, self.auid.into_value()); + map.insert_unchecked( + Property::Canonicalization, + self.canonicalization.into_value(), + ); + map.insert_unchecked(Property::Expire, self.expire.into_value()); + map.insert_unchecked(Property::Headers, self.headers.into_value()); + map.insert_unchecked(Property::PrivateKey, self.private_key.into_value()); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::ThirdParty, self.third_party.into_value()); + map.insert_unchecked(Property::ThirdPartyHash, self.third_party_hash.into_value()); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Selector, self.selector.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked( + Property::NextTransitionAt, + self.next_transition_at.into_value(), + ); + map.insert_unchecked(Property::Stage, self.stage.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Dkim1Signature { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Auid) => self + .auid + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Canonicalization) => self.canonicalization.patch(pointer, value), + Some(Property::Expire) => self.expire.patch(pointer, value), + Some(Property::Headers) => self + .headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PrivateKey) => self.private_key.patch(pointer, value), + Some(Property::PublicKey) => pointer.assert_server_set(), + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::ThirdParty) => self + .third_party + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ThirdPartyHash) => self.third_party_hash.patch(pointer, value), + Some(Property::DomainId) => self.domain_id.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Selector) => self + .selector + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::NextTransitionAt) => self.next_transition_at.patch(pointer, value), + Some(Property::Stage) => self.stage.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DkimManagement { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DkimManagement::Automatic(inner) => inner.validate(errors), + DkimManagement::Manual => true, + } + } +} + +impl Default for DkimManagement { + fn default() -> Self { + DkimManagement::Automatic(Default::default()) + } +} + +impl Pickle for DkimManagement { + fn pickle(&self, out: &mut Vec) { + match self { + DkimManagement::Automatic(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + DkimManagement::Manual => { + 1u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(DkimManagement::Automatic), + 1 => Some(DkimManagement::Manual), + _ => None, + } + } +} + +impl IntoValue for DkimManagement { + fn into_value(self) -> JmapValue<'static> { + match self { + DkimManagement::Automatic(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Automatic".into())); + obj + } + DkimManagement::Manual => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for DkimManagement { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DkimManagementType::Automatic => { + *self = DkimManagement::Automatic(Default::default()) + } + DkimManagementType::Manual => *self = DkimManagement::Manual, + } + } + match self { + DkimManagement::Automatic(inner) => inner.patch(pointer, value), + DkimManagement::Manual => pointer.assert_eof(), + } + } +} + +impl DkimManagement { + pub fn object_type(&self) -> DkimManagementType { + match self { + DkimManagement::Automatic(_) => DkimManagementType::Automatic, + DkimManagement::Manual => DkimManagementType::Manual, + } + } +} + +impl DkimManagementProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.selector_template; + if value.is_empty() { + errors.push(ValidationError::required(Property::SelectorTemplate)); + } + errors.len() == neb + } +} + +impl Pickle for DkimManagementProperties { + fn pickle(&self, out: &mut Vec) { + self.algorithms.pickle(out); + self.selector_template.pickle(out); + self.rotate_after.pickle(out); + self.retire_after.pickle(out); + self.delete_after.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.algorithms = Pickle::unpickle(stream)?; + this.selector_template = Pickle::unpickle(stream)?; + this.rotate_after = Pickle::unpickle(stream)?; + this.retire_after = Pickle::unpickle(stream)?; + this.delete_after = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DkimManagementProperties { + fn default() -> Self { + Self { + algorithms: Map::new(vec![ + DkimSignatureType::Dkim1Ed25519Sha256, + DkimSignatureType::Dkim1RsaSha256, + ]), + selector_template: "v{version}-{algorithm}-{date-%Y%m%d}".to_string(), + rotate_after: Duration::from_millis(7776000000), + retire_after: Duration::from_millis(604800000), + delete_after: Duration::from_millis(2592000000), + } + } +} + +impl IntoValue for DkimManagementProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Algorithms, self.algorithms.into_value()); + map.insert_unchecked( + Property::SelectorTemplate, + self.selector_template.into_value(), + ); + map.insert_unchecked(Property::RotateAfter, self.rotate_after.into_value()); + map.insert_unchecked(Property::RetireAfter, self.retire_after.into_value()); + map.insert_unchecked(Property::DeleteAfter, self.delete_after.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DkimManagementProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Algorithms) => self.algorithms.patch(pointer, value), + Some(Property::SelectorTemplate) => self + .selector_template + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::RotateAfter) => self.rotate_after.patch(pointer, value), + Some(Property::RetireAfter) => self.retire_after.patch(pointer, value), + Some(Property::DeleteAfter) => self.delete_after.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DkimReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DkimReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from_address; + value.validate(errors); + let value = &self.from_name; + value.validate(errors); + let value = &self.send_frequency; + value.validate(errors); + let value = &self.dkim_sign_domain; + value.validate(errors); + let value = &self.subject; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl DkimReportSettings { + pub fn ctx_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_address, + default: Some(Expression { + else_: "'noreply-dkim@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::FromAddress, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_name, + default: Some(Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }), + property: Property::FromName, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.send_frequency, + default: Some(Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }), + property: Property::SendFrequency, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_subject(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.subject, + default: Some(Expression { + else_: "'DKIM Authentication Failure Report'".to_string(), + ..Default::default() + }), + property: Property::Subject, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_from_address(), + self.ctx_from_name(), + self.ctx_send_frequency(), + self.ctx_dkim_sign_domain(), + self.ctx_subject(), + ] + } +} + +impl Pickle for DkimReportSettings { + fn pickle(&self, out: &mut Vec) { + self.from_address.pickle(out); + self.from_name.pickle(out); + self.send_frequency.pickle(out); + self.dkim_sign_domain.pickle(out); + self.subject.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from_address = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.send_frequency = Pickle::unpickle(stream)?; + this.dkim_sign_domain = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DkimReportSettings { + fn default() -> Self { + Self { + from_address: Expression { + else_: "'noreply-dkim@' + system('domain')".to_string(), + ..Default::default() + }, + from_name: Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }, + send_frequency: Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }, + dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + subject: Expression { + else_: "'DKIM Authentication Failure Report'".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for DkimReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::FromAddress, self.from_address.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value()); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DkimReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::FromAddress) => self.from_address.patch(pointer, value), + Some(Property::FromName) => self.from_name.patch(pointer, value), + Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value), + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DkimSignature { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DkimSignature; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DkimSignature::Dkim1Ed25519Sha256(inner) => inner.validate(errors), + DkimSignature::Dkim1RsaSha256(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + DkimSignature::Dkim1Ed25519Sha256(object) => { + object.index(i); + } + DkimSignature::Dkim1RsaSha256(object) => { + object.index(i); + } + } + } +} + +impl Default for DkimSignature { + fn default() -> Self { + DkimSignature::Dkim1Ed25519Sha256(Default::default()) + } +} + +impl Pickle for DkimSignature { + fn pickle(&self, out: &mut Vec) { + match self { + DkimSignature::Dkim1Ed25519Sha256(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + DkimSignature::Dkim1RsaSha256(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(DkimSignature::Dkim1Ed25519Sha256), + 1 => Pickle::unpickle(stream).map(DkimSignature::Dkim1RsaSha256), + _ => None, + } + } +} + +impl IntoValue for DkimSignature { + fn into_value(self) -> JmapValue<'static> { + match self { + DkimSignature::Dkim1Ed25519Sha256(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Dkim1Ed25519Sha256".into())); + obj + } + DkimSignature::Dkim1RsaSha256(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Dkim1RsaSha256".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DkimSignature { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DkimSignatureType::Dkim1Ed25519Sha256 => { + *self = DkimSignature::Dkim1Ed25519Sha256(Default::default()) + } + DkimSignatureType::Dkim1RsaSha256 => { + *self = DkimSignature::Dkim1RsaSha256(Default::default()) + } + } + } + match self { + DkimSignature::Dkim1Ed25519Sha256(inner) => inner.patch(pointer, value), + DkimSignature::Dkim1RsaSha256(inner) => inner.patch(pointer, value), + } + } +} + +impl DkimSignature { + pub fn object_type(&self) -> DkimSignatureType { + match self { + DkimSignature::Dkim1Ed25519Sha256(_) => DkimSignatureType::Dkim1Ed25519Sha256, + DkimSignature::Dkim1RsaSha256(_) => DkimSignatureType::Dkim1RsaSha256, + } + } +} + +impl DmarcDkimResult { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::Domain)); + } + let value = &self.selector; + if value.is_empty() { + errors.push(ValidationError::required(Property::Selector)); + } + if let Some(value) = &self.human_result { + if value.is_empty() { + errors.push(ValidationError::required(Property::HumanResult)); + } + } + errors.len() == neb + } +} + +impl Pickle for DmarcDkimResult { + fn pickle(&self, out: &mut Vec) { + self.domain.pickle(out); + self.selector.pickle(out); + self.result.pickle(out); + self.human_result.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.domain = Pickle::unpickle(stream)?; + this.selector = Pickle::unpickle(stream)?; + this.result = Pickle::unpickle(stream)?; + this.human_result = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcDkimResult { + fn default() -> Self { + Self { + domain: Default::default(), + selector: Default::default(), + result: Default::default(), + human_result: Default::default(), + } + } +} + +impl IntoValue for DmarcDkimResult { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Domain, self.domain.into_value()); + map.insert_unchecked(Property::Selector, self.selector.into_value()); + map.insert_unchecked(Property::Result, self.result.into_value()); + map.insert_unchecked(Property::HumanResult, self.human_result.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcDkimResult { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Domain) => self + .domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::Selector) => self.selector.patch(pointer, value), + Some(Property::Result) => self.result.patch(pointer, value), + Some(Property::HumanResult) => self.human_result.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcExtension { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.definition; + if value.is_empty() { + errors.push(ValidationError::required(Property::Definition)); + } + errors.len() == neb + } +} + +impl Pickle for DmarcExtension { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.definition.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.definition = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcExtension { + fn default() -> Self { + Self { + name: Default::default(), + definition: Default::default(), + } + } +} + +impl IntoValue for DmarcExtension { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Definition, self.definition.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcExtension { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer, value), + Some(Property::Definition) => self.definition.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DmarcExternalReport { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DmarcExternalReport; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.report; + value.validate(errors); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::To)); + } + } + let value = &self.received_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivedAt, value)); + } + let value = &self.expires_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + } +} + +impl Pickle for DmarcExternalReport { + fn pickle(&self, out: &mut Vec) { + self.report.pickle(out); + self.from.pickle(out); + self.subject.pickle(out); + self.to.pickle(out); + self.received_at.pickle(out); + self.expires_at.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.report = Pickle::unpickle(stream)?; + this.from = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.to = Pickle::unpickle(stream)?; + this.received_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcExternalReport { + fn default() -> Self { + Self { + report: Default::default(), + from: Default::default(), + subject: Default::default(), + to: Default::default(), + received_at: Default::default(), + expires_at: Default::default(), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for DmarcExternalReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::To, self.to.into_value()); + map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcExternalReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::From) => self + .from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::To) => self + .to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::ReceivedAt) => self.received_at.patch(pointer, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DmarcInternalReport { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DmarcInternalReport; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.rua; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Rua)); + } + } + let value = &self.report; + value.validate(errors); + let value = &self.domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::Domain)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.deliver_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DeliverAt, value)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for DmarcInternalReport { + fn pickle(&self, out: &mut Vec) { + self.rua.pickle(out); + self.policy_identifier.pickle(out); + self.report.pickle(out); + self.domain.pickle(out); + self.created_at.pickle(out); + self.deliver_at.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.rua = Pickle::unpickle(stream)?; + this.policy_identifier = Pickle::unpickle(stream)?; + this.report = Pickle::unpickle(stream)?; + this.domain = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.deliver_at = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcInternalReport { + fn default() -> Self { + Self { + rua: Default::default(), + policy_identifier: 0u64, + report: Default::default(), + domain: Default::default(), + created_at: Default::default(), + deliver_at: Default::default(), + } + } +} + +impl IntoValue for DmarcInternalReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Rua, self.rua.into_value()); + map.insert_unchecked( + Property::PolicyIdentifier, + self.policy_identifier.into_value(), + ); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::Domain, self.domain.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::DeliverAt, self.deliver_at.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcInternalReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Rua) => self + .rua + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::PolicyIdentifier) => self.policy_identifier.patch(pointer, value), + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::Domain) => self + .domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::CreatedAt) => self.created_at.patch(pointer, value), + Some(Property::DeliverAt) => self.deliver_at.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcPolicyOverrideReason { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.comment { + if value.is_empty() { + errors.push(ValidationError::required(Property::Comment)); + } + } + errors.len() == neb + } +} + +impl Pickle for DmarcPolicyOverrideReason { + fn pickle(&self, out: &mut Vec) { + self.override_type.pickle(out); + self.comment.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.override_type = Pickle::unpickle(stream)?; + this.comment = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcPolicyOverrideReason { + fn default() -> Self { + Self { + override_type: Default::default(), + comment: Default::default(), + } + } +} + +impl IntoValue for DmarcPolicyOverrideReason { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::OverrideType, self.override_type.into_value()); + map.insert_unchecked(Property::Comment, self.comment.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcPolicyOverrideReason { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::OverrideType) => self.override_type.patch(pointer, value), + Some(Property::Comment) => self.comment.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcReport { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.org_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::OrgName)); + } + let value = &self.email; + if value.is_empty() { + errors.push(ValidationError::required(Property::Email)); + } + if let Some(value) = &self.extra_contact_info { + if value.is_empty() { + errors.push(ValidationError::required(Property::ExtraContactInfo)); + } + } + let value = &self.report_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportId)); + } + let value = &self.date_range_begin; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DateRangeBegin, value)); + } + let value = &self.date_range_end; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DateRangeEnd, value)); + } + let value = &self.errors; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Errors)); + } + } + let value = &self.policy_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::PolicyDomain)); + } + if let Some(value) = &self.policy_version { + if value.is_empty() { + errors.push(ValidationError::required(Property::PolicyVersion)); + } + } + let value = &self.records; + for value in value.values() { + value.validate(errors); + } + let value = &self.extensions; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for DmarcReport { + fn pickle(&self, out: &mut Vec) { + self.version.pickle(out); + self.org_name.pickle(out); + self.email.pickle(out); + self.extra_contact_info.pickle(out); + self.report_id.pickle(out); + self.date_range_begin.pickle(out); + self.date_range_end.pickle(out); + self.errors.pickle(out); + self.policy_domain.pickle(out); + self.policy_version.pickle(out); + self.policy_adkim.pickle(out); + self.policy_aspf.pickle(out); + self.policy_disposition.pickle(out); + self.policy_subdomain_disposition.pickle(out); + self.policy_testing_mode.pickle(out); + self.policy_failure_reporting_options.pickle(out); + self.records.pickle(out); + self.extensions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.version = Pickle::unpickle(stream)?; + this.org_name = Pickle::unpickle(stream)?; + this.email = Pickle::unpickle(stream)?; + this.extra_contact_info = Pickle::unpickle(stream)?; + this.report_id = Pickle::unpickle(stream)?; + this.date_range_begin = Pickle::unpickle(stream)?; + this.date_range_end = Pickle::unpickle(stream)?; + this.errors = Pickle::unpickle(stream)?; + this.policy_domain = Pickle::unpickle(stream)?; + this.policy_version = Pickle::unpickle(stream)?; + this.policy_adkim = Pickle::unpickle(stream)?; + this.policy_aspf = Pickle::unpickle(stream)?; + this.policy_disposition = Pickle::unpickle(stream)?; + this.policy_subdomain_disposition = Pickle::unpickle(stream)?; + this.policy_testing_mode = Pickle::unpickle(stream)?; + this.policy_failure_reporting_options = Pickle::unpickle(stream)?; + this.records = Pickle::unpickle(stream)?; + this.extensions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcReport { + fn default() -> Self { + Self { + version: Float::new(1.0f64), + org_name: Default::default(), + email: Default::default(), + extra_contact_info: Default::default(), + report_id: Default::default(), + date_range_begin: Default::default(), + date_range_end: Default::default(), + errors: Default::default(), + policy_domain: Default::default(), + policy_version: Default::default(), + policy_adkim: Default::default(), + policy_aspf: Default::default(), + policy_disposition: Default::default(), + policy_subdomain_disposition: Default::default(), + policy_testing_mode: false, + policy_failure_reporting_options: Default::default(), + records: Default::default(), + extensions: Default::default(), + } + } +} + +impl IntoValue for DmarcReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(20); + map.insert_unchecked(Property::Version, self.version.into_value()); + map.insert_unchecked(Property::OrgName, self.org_name.into_value()); + map.insert_unchecked(Property::Email, self.email.into_value()); + map.insert_unchecked( + Property::ExtraContactInfo, + self.extra_contact_info.into_value(), + ); + map.insert_unchecked(Property::ReportId, self.report_id.into_value()); + map.insert_unchecked(Property::DateRangeBegin, self.date_range_begin.into_value()); + map.insert_unchecked(Property::DateRangeEnd, self.date_range_end.into_value()); + map.insert_unchecked(Property::Errors, self.errors.into_value()); + map.insert_unchecked(Property::PolicyDomain, self.policy_domain.into_value()); + map.insert_unchecked(Property::PolicyVersion, self.policy_version.into_value()); + map.insert_unchecked(Property::PolicyAdkim, self.policy_adkim.into_value()); + map.insert_unchecked(Property::PolicyAspf, self.policy_aspf.into_value()); + map.insert_unchecked( + Property::PolicyDisposition, + self.policy_disposition.into_value(), + ); + map.insert_unchecked( + Property::PolicySubdomainDisposition, + self.policy_subdomain_disposition.into_value(), + ); + map.insert_unchecked( + Property::PolicyTestingMode, + self.policy_testing_mode.into_value(), + ); + map.insert_unchecked( + Property::PolicyFailureReportingOptions, + self.policy_failure_reporting_options.into_value(), + ); + map.insert_unchecked(Property::Records, self.records.into_value()); + map.insert_unchecked(Property::Extensions, self.extensions.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Version) => self.version.patch(pointer, value), + Some(Property::OrgName) => self.org_name.patch(pointer, value), + Some(Property::Email) => self + .email + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::ExtraContactInfo) => self.extra_contact_info.patch(pointer, value), + Some(Property::ReportId) => self.report_id.patch(pointer, value), + Some(Property::DateRangeBegin) => self.date_range_begin.patch(pointer, value), + Some(Property::DateRangeEnd) => self.date_range_end.patch(pointer, value), + Some(Property::Errors) => self.errors.patch(pointer, value), + Some(Property::PolicyDomain) => self.policy_domain.patch(pointer, value), + Some(Property::PolicyVersion) => self.policy_version.patch(pointer, value), + Some(Property::PolicyAdkim) => self.policy_adkim.patch(pointer, value), + Some(Property::PolicyAspf) => self.policy_aspf.patch(pointer, value), + Some(Property::PolicyDisposition) => self.policy_disposition.patch(pointer, value), + Some(Property::PolicySubdomainDisposition) => { + self.policy_subdomain_disposition.patch(pointer, value) + } + Some(Property::PolicyTestingMode) => self.policy_testing_mode.patch(pointer, value), + Some(Property::PolicyFailureReportingOptions) => { + self.policy_failure_reporting_options.patch(pointer, value) + } + Some(Property::Records) => self.records.patch(pointer, value), + Some(Property::Extensions) => self.extensions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcReportRecord { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.source_ip { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::SourceIp, value)); + } + } + let value = &self.policy_override_reasons; + for value in value.values() { + value.validate(errors); + } + if let Some(value) = &self.envelope_to { + if value.is_empty() { + errors.push(ValidationError::required(Property::EnvelopeTo)); + } + } + let value = &self.envelope_from; + if value.is_empty() { + errors.push(ValidationError::required(Property::EnvelopeFrom)); + } + let value = &self.header_from; + if value.is_empty() { + errors.push(ValidationError::required(Property::HeaderFrom)); + } + let value = &self.dkim_results; + for value in value.values() { + value.validate(errors); + } + let value = &self.spf_results; + for value in value.values() { + value.validate(errors); + } + let value = &self.extensions; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for DmarcReportRecord { + fn pickle(&self, out: &mut Vec) { + self.source_ip.pickle(out); + self.count.pickle(out); + self.evaluated_disposition.pickle(out); + self.evaluated_dkim.pickle(out); + self.evaluated_spf.pickle(out); + self.policy_override_reasons.pickle(out); + self.envelope_to.pickle(out); + self.envelope_from.pickle(out); + self.header_from.pickle(out); + self.dkim_results.pickle(out); + self.spf_results.pickle(out); + self.extensions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.source_ip = Pickle::unpickle(stream)?; + this.count = Pickle::unpickle(stream)?; + this.evaluated_disposition = Pickle::unpickle(stream)?; + this.evaluated_dkim = Pickle::unpickle(stream)?; + this.evaluated_spf = Pickle::unpickle(stream)?; + this.policy_override_reasons = Pickle::unpickle(stream)?; + this.envelope_to = Pickle::unpickle(stream)?; + this.envelope_from = Pickle::unpickle(stream)?; + this.header_from = Pickle::unpickle(stream)?; + this.dkim_results = Pickle::unpickle(stream)?; + this.spf_results = Pickle::unpickle(stream)?; + this.extensions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcReportRecord { + fn default() -> Self { + Self { + source_ip: Default::default(), + count: 0u64, + evaluated_disposition: Default::default(), + evaluated_dkim: Default::default(), + evaluated_spf: Default::default(), + policy_override_reasons: Default::default(), + envelope_to: Default::default(), + envelope_from: Default::default(), + header_from: Default::default(), + dkim_results: Default::default(), + spf_results: Default::default(), + extensions: Default::default(), + } + } +} + +impl IntoValue for DmarcReportRecord { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::SourceIp, self.source_ip.into_value()); + map.insert_unchecked(Property::Count, self.count.into_value()); + map.insert_unchecked( + Property::EvaluatedDisposition, + self.evaluated_disposition.into_value(), + ); + map.insert_unchecked(Property::EvaluatedDkim, self.evaluated_dkim.into_value()); + map.insert_unchecked(Property::EvaluatedSpf, self.evaluated_spf.into_value()); + map.insert_unchecked( + Property::PolicyOverrideReasons, + self.policy_override_reasons.into_value(), + ); + map.insert_unchecked(Property::EnvelopeTo, self.envelope_to.into_value()); + map.insert_unchecked(Property::EnvelopeFrom, self.envelope_from.into_value()); + map.insert_unchecked(Property::HeaderFrom, self.header_from.into_value()); + map.insert_unchecked(Property::DkimResults, self.dkim_results.into_value()); + map.insert_unchecked(Property::SpfResults, self.spf_results.into_value()); + map.insert_unchecked(Property::Extensions, self.extensions.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcReportRecord { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::SourceIp) => self.source_ip.patch(pointer, value), + Some(Property::Count) => self.count.patch(pointer, value), + Some(Property::EvaluatedDisposition) => { + self.evaluated_disposition.patch(pointer, value) + } + Some(Property::EvaluatedDkim) => self.evaluated_dkim.patch(pointer, value), + Some(Property::EvaluatedSpf) => self.evaluated_spf.patch(pointer, value), + Some(Property::PolicyOverrideReasons) => { + self.policy_override_reasons.patch(pointer, value) + } + Some(Property::EnvelopeTo) => self.envelope_to.patch(pointer, value), + Some(Property::EnvelopeFrom) => self.envelope_from.patch(pointer, value), + Some(Property::HeaderFrom) => self.header_from.patch(pointer, value), + Some(Property::DkimResults) => self.dkim_results.patch(pointer, value), + Some(Property::SpfResults) => self.spf_results.patch(pointer, value), + Some(Property::Extensions) => self.extensions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DmarcReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DmarcReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.aggregate_contact_info; + value.validate(errors); + let value = &self.aggregate_from_address; + value.validate(errors); + let value = &self.aggregate_from_name; + value.validate(errors); + let value = &self.aggregate_max_report_size; + value.validate(errors); + let value = &self.aggregate_org_name; + value.validate(errors); + let value = &self.aggregate_send_frequency; + value.validate(errors); + let value = &self.aggregate_dkim_sign_domain; + value.validate(errors); + let value = &self.aggregate_subject; + value.validate(errors); + let value = &self.failure_from_address; + value.validate(errors); + let value = &self.failure_from_name; + value.validate(errors); + let value = &self.failure_send_frequency; + value.validate(errors); + let value = &self.failure_dkim_sign_domain; + value.validate(errors); + let value = &self.failure_subject; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl DmarcReportSettings { + pub fn ctx_aggregate_contact_info(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_contact_info, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::AggregateContactInfo, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_from_address, + default: Some(Expression { + else_: "'noreply-dmarc@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::AggregateFromAddress, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_from_name, + default: Some(Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }), + property: Property::AggregateFromName, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_max_report_size(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_max_report_size, + default: Some(Expression { + else_: "5242880".to_string(), + ..Default::default() + }), + property: Property::AggregateMaxReportSize, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_org_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_org_name, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::AggregateOrgName, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_send_frequency(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_send_frequency, + default: Some(Expression { + else_: "daily".to_string(), + ..Default::default() + }), + property: Property::AggregateSendFrequency, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: MTA_AGGREGATE_CONSTANT, + } + } + + pub fn ctx_aggregate_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::AggregateDkimSignDomain, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_aggregate_subject(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.aggregate_subject, + default: Some(Expression { + else_: "'DMARC Aggregate Report'".to_string(), + ..Default::default() + }), + property: Property::AggregateSubject, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_failure_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.failure_from_address, + default: Some(Expression { + else_: "'noreply-dmarc@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::FailureFromAddress, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_failure_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.failure_from_name, + default: Some(Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }), + property: Property::FailureFromName, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_failure_send_frequency(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.failure_send_frequency, + default: Some(Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }), + property: Property::FailureSendFrequency, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_failure_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.failure_dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::FailureDkimSignDomain, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_failure_subject(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.failure_subject, + default: Some(Expression { + else_: "'DMARC Authentication Failure Report'".to_string(), + ..Default::default() + }), + property: Property::FailureSubject, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_aggregate_contact_info(), + self.ctx_aggregate_from_address(), + self.ctx_aggregate_from_name(), + self.ctx_aggregate_max_report_size(), + self.ctx_aggregate_org_name(), + self.ctx_aggregate_send_frequency(), + self.ctx_aggregate_dkim_sign_domain(), + self.ctx_aggregate_subject(), + self.ctx_failure_from_address(), + self.ctx_failure_from_name(), + self.ctx_failure_send_frequency(), + self.ctx_failure_dkim_sign_domain(), + self.ctx_failure_subject(), + ] + } +} + +impl Pickle for DmarcReportSettings { + fn pickle(&self, out: &mut Vec) { + self.aggregate_contact_info.pickle(out); + self.aggregate_from_address.pickle(out); + self.aggregate_from_name.pickle(out); + self.aggregate_max_report_size.pickle(out); + self.aggregate_org_name.pickle(out); + self.aggregate_send_frequency.pickle(out); + self.aggregate_dkim_sign_domain.pickle(out); + self.aggregate_subject.pickle(out); + self.failure_from_address.pickle(out); + self.failure_from_name.pickle(out); + self.failure_send_frequency.pickle(out); + self.failure_dkim_sign_domain.pickle(out); + self.failure_subject.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.aggregate_contact_info = Pickle::unpickle(stream)?; + this.aggregate_from_address = Pickle::unpickle(stream)?; + this.aggregate_from_name = Pickle::unpickle(stream)?; + this.aggregate_max_report_size = Pickle::unpickle(stream)?; + this.aggregate_org_name = Pickle::unpickle(stream)?; + this.aggregate_send_frequency = Pickle::unpickle(stream)?; + this.aggregate_dkim_sign_domain = Pickle::unpickle(stream)?; + this.aggregate_subject = Pickle::unpickle(stream)?; + this.failure_from_address = Pickle::unpickle(stream)?; + this.failure_from_name = Pickle::unpickle(stream)?; + this.failure_send_frequency = Pickle::unpickle(stream)?; + this.failure_dkim_sign_domain = Pickle::unpickle(stream)?; + this.failure_subject = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcReportSettings { + fn default() -> Self { + Self { + aggregate_contact_info: Expression { + else_: "false".to_string(), + ..Default::default() + }, + aggregate_from_address: Expression { + else_: "'noreply-dmarc@' + system('domain')".to_string(), + ..Default::default() + }, + aggregate_from_name: Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }, + aggregate_max_report_size: Expression { + else_: "5242880".to_string(), + ..Default::default() + }, + aggregate_org_name: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + aggregate_send_frequency: Expression { + else_: "daily".to_string(), + ..Default::default() + }, + aggregate_dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + aggregate_subject: Expression { + else_: "'DMARC Aggregate Report'".to_string(), + ..Default::default() + }, + failure_from_address: Expression { + else_: "'noreply-dmarc@' + system('domain')".to_string(), + ..Default::default() + }, + failure_from_name: Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }, + failure_send_frequency: Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }, + failure_dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + failure_subject: Expression { + else_: "'DMARC Authentication Failure Report'".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for DmarcReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked( + Property::AggregateContactInfo, + self.aggregate_contact_info.into_value(), + ); + map.insert_unchecked( + Property::AggregateFromAddress, + self.aggregate_from_address.into_value(), + ); + map.insert_unchecked( + Property::AggregateFromName, + self.aggregate_from_name.into_value(), + ); + map.insert_unchecked( + Property::AggregateMaxReportSize, + self.aggregate_max_report_size.into_value(), + ); + map.insert_unchecked( + Property::AggregateOrgName, + self.aggregate_org_name.into_value(), + ); + map.insert_unchecked( + Property::AggregateSendFrequency, + self.aggregate_send_frequency.into_value(), + ); + map.insert_unchecked( + Property::AggregateDkimSignDomain, + self.aggregate_dkim_sign_domain.into_value(), + ); + map.insert_unchecked( + Property::AggregateSubject, + self.aggregate_subject.into_value(), + ); + map.insert_unchecked( + Property::FailureFromAddress, + self.failure_from_address.into_value(), + ); + map.insert_unchecked( + Property::FailureFromName, + self.failure_from_name.into_value(), + ); + map.insert_unchecked( + Property::FailureSendFrequency, + self.failure_send_frequency.into_value(), + ); + map.insert_unchecked( + Property::FailureDkimSignDomain, + self.failure_dkim_sign_domain.into_value(), + ); + map.insert_unchecked(Property::FailureSubject, self.failure_subject.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AggregateContactInfo) => { + self.aggregate_contact_info.patch(pointer, value) + } + Some(Property::AggregateFromAddress) => { + self.aggregate_from_address.patch(pointer, value) + } + Some(Property::AggregateFromName) => self.aggregate_from_name.patch(pointer, value), + Some(Property::AggregateMaxReportSize) => { + self.aggregate_max_report_size.patch(pointer, value) + } + Some(Property::AggregateOrgName) => self.aggregate_org_name.patch(pointer, value), + Some(Property::AggregateSendFrequency) => { + self.aggregate_send_frequency.patch(pointer, value) + } + Some(Property::AggregateDkimSignDomain) => { + self.aggregate_dkim_sign_domain.patch(pointer, value) + } + Some(Property::AggregateSubject) => self.aggregate_subject.patch(pointer, value), + Some(Property::FailureFromAddress) => self.failure_from_address.patch(pointer, value), + Some(Property::FailureFromName) => self.failure_from_name.patch(pointer, value), + Some(Property::FailureSendFrequency) => { + self.failure_send_frequency.patch(pointer, value) + } + Some(Property::FailureDkimSignDomain) => { + self.failure_dkim_sign_domain.patch(pointer, value) + } + Some(Property::FailureSubject) => self.failure_subject.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcSpfResult { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::Domain)); + } + if let Some(value) = &self.human_result { + if value.is_empty() { + errors.push(ValidationError::required(Property::HumanResult)); + } + } + errors.len() == neb + } +} + +impl Pickle for DmarcSpfResult { + fn pickle(&self, out: &mut Vec) { + self.domain.pickle(out); + self.scope.pickle(out); + self.result.pickle(out); + self.human_result.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.domain = Pickle::unpickle(stream)?; + this.scope = Pickle::unpickle(stream)?; + this.result = Pickle::unpickle(stream)?; + this.human_result = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcSpfResult { + fn default() -> Self { + Self { + domain: Default::default(), + scope: Default::default(), + result: Default::default(), + human_result: Default::default(), + } + } +} + +impl IntoValue for DmarcSpfResult { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Domain, self.domain.into_value()); + map.insert_unchecked(Property::Scope, self.scope.into_value()); + map.insert_unchecked(Property::Result, self.result.into_value()); + map.insert_unchecked(Property::HumanResult, self.human_result.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcSpfResult { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Domain) => self + .domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::Scope) => self.scope.patch(pointer, value), + Some(Property::Result) => self.result.patch(pointer, value), + Some(Property::HumanResult) => self.human_result.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcTroubleshoot { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.remote_ip; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::RemoteIp, value)); + } + let value = &self.ehlo_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::EhloDomain)); + } + let value = &self.mail_from; + if value.is_empty() { + errors.push(ValidationError::required(Property::MailFrom)); + } + if let Some(value) = &self.message { + if value.is_empty() { + errors.push(ValidationError::required(Property::Message)); + } + } + let value = &self.spf_ehlo_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::SpfEhloDomain)); + } + let value = &self.spf_ehlo_result; + value.validate(errors); + let value = &self.spf_mail_from_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::SpfMailFromDomain)); + } + let value = &self.spf_mail_from_result; + value.validate(errors); + let value = &self.ip_rev_result; + value.validate(errors); + let value = &self.ip_rev_ptr; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::IpRevPtr)); + } + } + let value = &self.dkim_results; + for value in value.values() { + value.validate(errors); + } + let value = &self.arc_result; + value.validate(errors); + let value = &self.dmarc_result; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for DmarcTroubleshoot { + fn pickle(&self, out: &mut Vec) { + self.remote_ip.pickle(out); + self.ehlo_domain.pickle(out); + self.mail_from.pickle(out); + self.message.pickle(out); + self.spf_ehlo_domain.pickle(out); + self.spf_ehlo_result.pickle(out); + self.spf_mail_from_domain.pickle(out); + self.spf_mail_from_result.pickle(out); + self.ip_rev_result.pickle(out); + self.ip_rev_ptr.pickle(out); + self.dkim_results.pickle(out); + self.dkim_pass.pickle(out); + self.arc_result.pickle(out); + self.dmarc_result.pickle(out); + self.dmarc_pass.pickle(out); + self.dmarc_policy.pickle(out); + self.elapsed.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.remote_ip = Pickle::unpickle(stream)?; + this.ehlo_domain = Pickle::unpickle(stream)?; + this.mail_from = Pickle::unpickle(stream)?; + this.message = Pickle::unpickle(stream)?; + this.spf_ehlo_domain = Pickle::unpickle(stream)?; + this.spf_ehlo_result = Pickle::unpickle(stream)?; + this.spf_mail_from_domain = Pickle::unpickle(stream)?; + this.spf_mail_from_result = Pickle::unpickle(stream)?; + this.ip_rev_result = Pickle::unpickle(stream)?; + this.ip_rev_ptr = Pickle::unpickle(stream)?; + this.dkim_results = Pickle::unpickle(stream)?; + this.dkim_pass = Pickle::unpickle(stream)?; + this.arc_result = Pickle::unpickle(stream)?; + this.dmarc_result = Pickle::unpickle(stream)?; + this.dmarc_pass = Pickle::unpickle(stream)?; + this.dmarc_policy = Pickle::unpickle(stream)?; + this.elapsed = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcTroubleshoot { + fn default() -> Self { + Self { + remote_ip: Default::default(), + ehlo_domain: Default::default(), + mail_from: Default::default(), + message: Default::default(), + spf_ehlo_domain: Default::default(), + spf_ehlo_result: Default::default(), + spf_mail_from_domain: Default::default(), + spf_mail_from_result: Default::default(), + ip_rev_result: Default::default(), + ip_rev_ptr: Default::default(), + dkim_results: Default::default(), + dkim_pass: false, + arc_result: Default::default(), + dmarc_result: Default::default(), + dmarc_pass: false, + dmarc_policy: Default::default(), + elapsed: Duration::from_millis(0), + } + } +} + +impl IntoValue for DmarcTroubleshoot { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(19); + map.insert_unchecked(Property::RemoteIp, self.remote_ip.into_value()); + map.insert_unchecked(Property::EhloDomain, self.ehlo_domain.into_value()); + map.insert_unchecked(Property::MailFrom, self.mail_from.into_value()); + map.insert_unchecked(Property::Message, self.message.into_value()); + map.insert_unchecked(Property::SpfEhloDomain, self.spf_ehlo_domain.into_value()); + map.insert_unchecked(Property::SpfEhloResult, self.spf_ehlo_result.into_value()); + map.insert_unchecked( + Property::SpfMailFromDomain, + self.spf_mail_from_domain.into_value(), + ); + map.insert_unchecked( + Property::SpfMailFromResult, + self.spf_mail_from_result.into_value(), + ); + map.insert_unchecked(Property::IpRevResult, self.ip_rev_result.into_value()); + map.insert_unchecked(Property::IpRevPtr, self.ip_rev_ptr.into_value()); + map.insert_unchecked(Property::DkimResults, self.dkim_results.into_value()); + map.insert_unchecked(Property::DkimPass, self.dkim_pass.into_value()); + map.insert_unchecked(Property::ArcResult, self.arc_result.into_value()); + map.insert_unchecked(Property::DmarcResult, self.dmarc_result.into_value()); + map.insert_unchecked(Property::DmarcPass, self.dmarc_pass.into_value()); + map.insert_unchecked(Property::DmarcPolicy, self.dmarc_policy.into_value()); + map.insert_unchecked(Property::Elapsed, self.elapsed.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcTroubleshoot { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::RemoteIp) => self.remote_ip.patch(pointer, value), + Some(Property::EhloDomain) => self.ehlo_domain.patch(pointer, value), + Some(Property::MailFrom) => self + .mail_from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Message) => self.message.patch(pointer, value), + Some(Property::SpfEhloDomain) => self.spf_ehlo_domain.patch(pointer, value), + Some(Property::SpfEhloResult) => pointer.assert_server_set(), + Some(Property::SpfMailFromDomain) => self.spf_mail_from_domain.patch(pointer, value), + Some(Property::SpfMailFromResult) => pointer.assert_server_set(), + Some(Property::IpRevResult) => pointer.assert_server_set(), + Some(Property::IpRevPtr) => pointer.assert_server_set(), + Some(Property::DkimResults) => pointer.assert_server_set(), + Some(Property::DkimPass) => pointer.assert_server_set(), + Some(Property::ArcResult) => pointer.assert_server_set(), + Some(Property::DmarcResult) => pointer.assert_server_set(), + Some(Property::DmarcPass) => pointer.assert_server_set(), + Some(Property::DmarcPolicy) => pointer.assert_server_set(), + Some(Property::Elapsed) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DmarcTroubleshootAuthResult { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DmarcTroubleshootAuthResult::Pass => true, + DmarcTroubleshootAuthResult::Fail(inner) => inner.validate(errors), + DmarcTroubleshootAuthResult::SoftFail(inner) => inner.validate(errors), + DmarcTroubleshootAuthResult::TempError(inner) => inner.validate(errors), + DmarcTroubleshootAuthResult::PermError(inner) => inner.validate(errors), + DmarcTroubleshootAuthResult::Neutral(inner) => inner.validate(errors), + DmarcTroubleshootAuthResult::None => true, + } + } +} + +impl Default for DmarcTroubleshootAuthResult { + fn default() -> Self { + DmarcTroubleshootAuthResult::Pass + } +} + +impl Pickle for DmarcTroubleshootAuthResult { + fn pickle(&self, out: &mut Vec) { + match self { + DmarcTroubleshootAuthResult::Pass => { + 0u16.pickle(out); + } + DmarcTroubleshootAuthResult::Fail(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DmarcTroubleshootAuthResult::SoftFail(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DmarcTroubleshootAuthResult::TempError(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + DmarcTroubleshootAuthResult::PermError(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + DmarcTroubleshootAuthResult::Neutral(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + DmarcTroubleshootAuthResult::None => { + 6u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(DmarcTroubleshootAuthResult::Pass), + 1 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::Fail), + 2 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::SoftFail), + 3 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::TempError), + 4 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::PermError), + 5 => Pickle::unpickle(stream).map(DmarcTroubleshootAuthResult::Neutral), + 6 => Some(DmarcTroubleshootAuthResult::None), + _ => None, + } + } +} + +impl IntoValue for DmarcTroubleshootAuthResult { + fn into_value(self) -> JmapValue<'static> { + match self { + DmarcTroubleshootAuthResult::Pass => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Pass".into())); + JmapValue::Object(obj) + } + DmarcTroubleshootAuthResult::Fail(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Fail".into())); + obj + } + DmarcTroubleshootAuthResult::SoftFail(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("SoftFail".into())); + obj + } + DmarcTroubleshootAuthResult::TempError(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("TempError".into())); + obj + } + DmarcTroubleshootAuthResult::PermError(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PermError".into())); + obj + } + DmarcTroubleshootAuthResult::Neutral(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Neutral".into())); + obj + } + DmarcTroubleshootAuthResult::None => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("None".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for DmarcTroubleshootAuthResult { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DmarcTroubleshootAuthResultType::Pass => *self = DmarcTroubleshootAuthResult::Pass, + DmarcTroubleshootAuthResultType::Fail => { + *self = DmarcTroubleshootAuthResult::Fail(Default::default()) + } + DmarcTroubleshootAuthResultType::SoftFail => { + *self = DmarcTroubleshootAuthResult::SoftFail(Default::default()) + } + DmarcTroubleshootAuthResultType::TempError => { + *self = DmarcTroubleshootAuthResult::TempError(Default::default()) + } + DmarcTroubleshootAuthResultType::PermError => { + *self = DmarcTroubleshootAuthResult::PermError(Default::default()) + } + DmarcTroubleshootAuthResultType::Neutral => { + *self = DmarcTroubleshootAuthResult::Neutral(Default::default()) + } + DmarcTroubleshootAuthResultType::None => *self = DmarcTroubleshootAuthResult::None, + } + } + match self { + DmarcTroubleshootAuthResult::Pass => pointer.assert_eof(), + DmarcTroubleshootAuthResult::Fail(inner) => inner.patch(pointer, value), + DmarcTroubleshootAuthResult::SoftFail(inner) => inner.patch(pointer, value), + DmarcTroubleshootAuthResult::TempError(inner) => inner.patch(pointer, value), + DmarcTroubleshootAuthResult::PermError(inner) => inner.patch(pointer, value), + DmarcTroubleshootAuthResult::Neutral(inner) => inner.patch(pointer, value), + DmarcTroubleshootAuthResult::None => pointer.assert_eof(), + } + } +} + +impl DmarcTroubleshootAuthResult { + pub fn object_type(&self) -> DmarcTroubleshootAuthResultType { + match self { + DmarcTroubleshootAuthResult::Pass => DmarcTroubleshootAuthResultType::Pass, + DmarcTroubleshootAuthResult::Fail(_) => DmarcTroubleshootAuthResultType::Fail, + DmarcTroubleshootAuthResult::SoftFail(_) => DmarcTroubleshootAuthResultType::SoftFail, + DmarcTroubleshootAuthResult::TempError(_) => DmarcTroubleshootAuthResultType::TempError, + DmarcTroubleshootAuthResult::PermError(_) => DmarcTroubleshootAuthResultType::PermError, + DmarcTroubleshootAuthResult::Neutral(_) => DmarcTroubleshootAuthResultType::Neutral, + DmarcTroubleshootAuthResult::None => DmarcTroubleshootAuthResultType::None, + } + } +} + +impl DmarcTroubleshootDetails { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.details { + if value.is_empty() { + errors.push(ValidationError::required(Property::Details)); + } + } + errors.len() == neb + } +} + +impl Pickle for DmarcTroubleshootDetails { + fn pickle(&self, out: &mut Vec) { + self.details.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.details = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DmarcTroubleshootDetails { + fn default() -> Self { + Self { + details: Default::default(), + } + } +} + +impl IntoValue for DmarcTroubleshootDetails { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Details, self.details.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DmarcTroubleshootDetails { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Details) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsCustomResolver { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.address; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Address, value)); + } + let value = &self.port; + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + errors.len() == neb + } +} + +impl Pickle for DnsCustomResolver { + fn pickle(&self, out: &mut Vec) { + self.protocol.pickle(out); + self.address.pickle(out); + self.port.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.protocol = Pickle::unpickle(stream)?; + this.address = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsCustomResolver { + fn default() -> Self { + Self { + protocol: DnsResolverProtocol::Udp, + address: IpAddr::from_str("127.0.0.1").unwrap(), + port: 53u64, + } + } +} + +impl IntoValue for DnsCustomResolver { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Protocol, self.protocol.into_value()); + map.insert_unchecked(Property::Address, self.address.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsCustomResolver { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Protocol) => self.protocol.patch(pointer, value), + Some(Property::Address) => self + .address + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsManagement { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DnsManagement::Manual => true, + DnsManagement::Automatic(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + DnsManagement::Manual => {} + DnsManagement::Automatic(object) => { + object.index(i); + } + } + } +} + +impl Default for DnsManagement { + fn default() -> Self { + DnsManagement::Manual + } +} + +impl Pickle for DnsManagement { + fn pickle(&self, out: &mut Vec) { + match self { + DnsManagement::Manual => { + 0u16.pickle(out); + } + DnsManagement::Automatic(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(DnsManagement::Manual), + 1 => Pickle::unpickle(stream).map(DnsManagement::Automatic), + _ => None, + } + } +} + +impl IntoValue for DnsManagement { + fn into_value(self) -> JmapValue<'static> { + match self { + DnsManagement::Manual => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into())); + JmapValue::Object(obj) + } + DnsManagement::Automatic(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Automatic".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DnsManagement { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DnsManagementType::Manual => *self = DnsManagement::Manual, + DnsManagementType::Automatic => { + *self = DnsManagement::Automatic(Default::default()) + } + } + } + match self { + DnsManagement::Manual => pointer.assert_eof(), + DnsManagement::Automatic(inner) => inner.patch(pointer, value), + } + } +} + +impl DnsManagement { + pub fn object_type(&self) -> DnsManagementType { + match self { + DnsManagement::Manual => DnsManagementType::Manual, + DnsManagement::Automatic(_) => DnsManagementType::Automatic, + } + } +} + +impl DnsManagementProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.dns_server_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DnsServerId)); + } + if let Some(value) = &self.origin { + if value.is_empty() { + errors.push(ValidationError::required(Property::Origin)); + } + } + let value = &self.publish_records; + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::PublishRecords, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::DnsServer, self.dns_server_id.into(), None); + } +} + +impl Pickle for DnsManagementProperties { + fn pickle(&self, out: &mut Vec) { + self.dns_server_id.pickle(out); + self.origin.pickle(out); + self.publish_records.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.dns_server_id = Pickle::unpickle(stream)?; + this.origin = Pickle::unpickle(stream)?; + this.publish_records = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsManagementProperties { + fn default() -> Self { + Self { + dns_server_id: Default::default(), + origin: Default::default(), + publish_records: Map::new(vec![ + DnsRecordType::Dkim, + DnsRecordType::Spf, + DnsRecordType::Mx, + DnsRecordType::Dmarc, + DnsRecordType::Srv, + DnsRecordType::MtaSts, + DnsRecordType::TlsRpt, + DnsRecordType::Caa, + DnsRecordType::AutoConfig, + DnsRecordType::AutoConfigLegacy, + DnsRecordType::AutoDiscover, + ]), + } + } +} + +impl IntoValue for DnsManagementProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::DnsServerId, self.dns_server_id.into_value()); + map.insert_unchecked(Property::Origin, self.origin.into_value()); + map.insert_unchecked(Property::PublishRecords, self.publish_records.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsManagementProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DnsServerId) => self.dns_server_id.patch(pointer, value), + Some(Property::Origin) => self + .origin + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PublishRecords) => self.publish_records.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DnsResolver { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DnsResolver; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DnsResolver::System(inner) => inner.validate(errors), + DnsResolver::Custom(inner) => inner.validate(errors), + DnsResolver::Cloudflare(inner) => inner.validate(errors), + DnsResolver::Quad9(inner) => inner.validate(errors), + DnsResolver::Google(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for DnsResolver { + fn default() -> Self { + DnsResolver::System(Default::default()) + } +} + +impl Pickle for DnsResolver { + fn pickle(&self, out: &mut Vec) { + match self { + DnsResolver::System(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + DnsResolver::Custom(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DnsResolver::Cloudflare(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DnsResolver::Quad9(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + DnsResolver::Google(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(DnsResolver::System), + 1 => Pickle::unpickle(stream).map(DnsResolver::Custom), + 2 => Pickle::unpickle(stream).map(DnsResolver::Cloudflare), + 3 => Pickle::unpickle(stream).map(DnsResolver::Quad9), + 4 => Pickle::unpickle(stream).map(DnsResolver::Google), + _ => None, + } + } +} + +impl IntoValue for DnsResolver { + fn into_value(self) -> JmapValue<'static> { + match self { + DnsResolver::System(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("System".into())); + obj + } + DnsResolver::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + DnsResolver::Cloudflare(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into())); + obj + } + DnsResolver::Quad9(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Quad9".into())); + obj + } + DnsResolver::Google(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Google".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DnsResolver { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DnsResolverType::System => *self = DnsResolver::System(Default::default()), + DnsResolverType::Custom => *self = DnsResolver::Custom(Default::default()), + DnsResolverType::Cloudflare => *self = DnsResolver::Cloudflare(Default::default()), + DnsResolverType::Quad9 => *self = DnsResolver::Quad9(Default::default()), + DnsResolverType::Google => *self = DnsResolver::Google(Default::default()), + } + } + match self { + DnsResolver::System(inner) => inner.patch(pointer, value), + DnsResolver::Custom(inner) => inner.patch(pointer, value), + DnsResolver::Cloudflare(inner) => inner.patch(pointer, value), + DnsResolver::Quad9(inner) => inner.patch(pointer, value), + DnsResolver::Google(inner) => inner.patch(pointer, value), + } + } +} + +impl DnsResolver { + pub fn object_type(&self) -> DnsResolverType { + match self { + DnsResolver::System(_) => DnsResolverType::System, + DnsResolver::Custom(_) => DnsResolverType::Custom, + DnsResolver::Cloudflare(_) => DnsResolverType::Cloudflare, + DnsResolver::Quad9(_) => DnsResolverType::Quad9, + DnsResolver::Google(_) => DnsResolverType::Google, + } + } +} + +impl DnsResolverCommon { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for DnsResolverCommon { + fn pickle(&self, out: &mut Vec) { + self.attempts.pickle(out); + self.concurrency.pickle(out); + self.enable_edns.pickle(out); + self.preserve_intermediates.pickle(out); + self.timeout.pickle(out); + self.tcp_on_error.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.attempts = Pickle::unpickle(stream)?; + this.concurrency = Pickle::unpickle(stream)?; + this.enable_edns = Pickle::unpickle(stream)?; + this.preserve_intermediates = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.tcp_on_error = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsResolverCommon { + fn default() -> Self { + Self { + attempts: 2u64, + concurrency: 2u64, + enable_edns: true, + preserve_intermediates: true, + timeout: Duration::from_millis(5000), + tcp_on_error: true, + } + } +} + +impl IntoValue for DnsResolverCommon { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Attempts, self.attempts.into_value()); + map.insert_unchecked(Property::Concurrency, self.concurrency.into_value()); + map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value()); + map.insert_unchecked( + Property::PreserveIntermediates, + self.preserve_intermediates.into_value(), + ); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsResolverCommon { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Attempts) => self.attempts.patch(pointer, value), + Some(Property::Concurrency) => self.concurrency.patch(pointer, value), + Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value), + Some(Property::PreserveIntermediates) => { + self.preserve_intermediates.patch(pointer, value) + } + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsResolverCustom { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.servers; + for value in value.values() { + value.validate(errors); + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Servers, 1)); + } + errors.len() == neb + } +} + +impl Pickle for DnsResolverCustom { + fn pickle(&self, out: &mut Vec) { + self.servers.pickle(out); + self.attempts.pickle(out); + self.concurrency.pickle(out); + self.enable_edns.pickle(out); + self.preserve_intermediates.pickle(out); + self.timeout.pickle(out); + self.tcp_on_error.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.servers = Pickle::unpickle(stream)?; + this.attempts = Pickle::unpickle(stream)?; + this.concurrency = Pickle::unpickle(stream)?; + this.enable_edns = Pickle::unpickle(stream)?; + this.preserve_intermediates = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.tcp_on_error = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsResolverCustom { + fn default() -> Self { + Self { + servers: Default::default(), + attempts: 2u64, + concurrency: 2u64, + enable_edns: true, + preserve_intermediates: true, + timeout: Duration::from_millis(5000), + tcp_on_error: true, + } + } +} + +impl IntoValue for DnsResolverCustom { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Servers, self.servers.into_value()); + map.insert_unchecked(Property::Attempts, self.attempts.into_value()); + map.insert_unchecked(Property::Concurrency, self.concurrency.into_value()); + map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value()); + map.insert_unchecked( + Property::PreserveIntermediates, + self.preserve_intermediates.into_value(), + ); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsResolverCustom { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Servers) => self.servers.patch(pointer, value), + Some(Property::Attempts) => self.attempts.patch(pointer, value), + Some(Property::Concurrency) => self.concurrency.patch(pointer, value), + Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value), + Some(Property::PreserveIntermediates) => { + self.preserve_intermediates.patch(pointer, value) + } + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsResolverTls { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for DnsResolverTls { + fn pickle(&self, out: &mut Vec) { + self.use_tls.pickle(out); + self.attempts.pickle(out); + self.concurrency.pickle(out); + self.enable_edns.pickle(out); + self.preserve_intermediates.pickle(out); + self.timeout.pickle(out); + self.tcp_on_error.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.use_tls = Pickle::unpickle(stream)?; + this.attempts = Pickle::unpickle(stream)?; + this.concurrency = Pickle::unpickle(stream)?; + this.enable_edns = Pickle::unpickle(stream)?; + this.preserve_intermediates = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.tcp_on_error = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsResolverTls { + fn default() -> Self { + Self { + use_tls: true, + attempts: 2u64, + concurrency: 2u64, + enable_edns: true, + preserve_intermediates: true, + timeout: Duration::from_millis(5000), + tcp_on_error: true, + } + } +} + +impl IntoValue for DnsResolverTls { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked(Property::Attempts, self.attempts.into_value()); + map.insert_unchecked(Property::Concurrency, self.concurrency.into_value()); + map.insert_unchecked(Property::EnableEdns, self.enable_edns.into_value()); + map.insert_unchecked( + Property::PreserveIntermediates, + self.preserve_intermediates.into_value(), + ); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::TcpOnError, self.tcp_on_error.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsResolverTls { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::Attempts) => self.attempts.patch(pointer, value), + Some(Property::Concurrency) => self.concurrency.patch(pointer, value), + Some(Property::EnableEdns) => self.enable_edns.patch(pointer, value), + Some(Property::PreserveIntermediates) => { + self.preserve_intermediates.patch(pointer, value) + } + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::TcpOnError) => self.tcp_on_error.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DnsServer { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DnsServer; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DnsServer::Tsig(inner) => inner.validate(errors), + DnsServer::Sig0(inner) => inner.validate(errors), + DnsServer::Cloudflare(inner) => inner.validate(errors), + DnsServer::DigitalOcean(inner) => inner.validate(errors), + DnsServer::DeSEC(inner) => inner.validate(errors), + DnsServer::Ovh(inner) => inner.validate(errors), + DnsServer::Bunny(inner) => inner.validate(errors), + DnsServer::Porkbun(inner) => inner.validate(errors), + DnsServer::Dnsimple(inner) => inner.validate(errors), + DnsServer::Spaceship(inner) => inner.validate(errors), + DnsServer::Route53(inner) => inner.validate(errors), + DnsServer::GoogleCloudDns(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + DnsServer::Tsig(object) => { + object.index(i); + } + DnsServer::Sig0(object) => { + object.index(i); + } + DnsServer::Cloudflare(object) => { + object.index(i); + } + DnsServer::DigitalOcean(object) => { + object.index(i); + } + DnsServer::DeSEC(object) => { + object.index(i); + } + DnsServer::Ovh(object) => { + object.index(i); + } + DnsServer::Bunny(object) => { + object.index(i); + } + DnsServer::Porkbun(object) => { + object.index(i); + } + DnsServer::Dnsimple(object) => { + object.index(i); + } + DnsServer::Spaceship(object) => { + object.index(i); + } + DnsServer::Route53(object) => { + object.index(i); + } + DnsServer::GoogleCloudDns(object) => { + object.index(i); + } + } + } +} + +impl Default for DnsServer { + fn default() -> Self { + DnsServer::Tsig(Default::default()) + } +} + +impl Pickle for DnsServer { + fn pickle(&self, out: &mut Vec) { + match self { + DnsServer::Tsig(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + DnsServer::Sig0(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DnsServer::Cloudflare(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DnsServer::DigitalOcean(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + DnsServer::DeSEC(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + DnsServer::Ovh(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + DnsServer::Bunny(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + DnsServer::Porkbun(inner) => { + 7u16.pickle(out); + inner.pickle(out); + } + DnsServer::Dnsimple(inner) => { + 8u16.pickle(out); + inner.pickle(out); + } + DnsServer::Spaceship(inner) => { + 9u16.pickle(out); + inner.pickle(out); + } + DnsServer::Route53(inner) => { + 10u16.pickle(out); + inner.pickle(out); + } + DnsServer::GoogleCloudDns(inner) => { + 11u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(DnsServer::Tsig), + 1 => Pickle::unpickle(stream).map(DnsServer::Sig0), + 2 => Pickle::unpickle(stream).map(DnsServer::Cloudflare), + 3 => Pickle::unpickle(stream).map(DnsServer::DigitalOcean), + 4 => Pickle::unpickle(stream).map(DnsServer::DeSEC), + 5 => Pickle::unpickle(stream).map(DnsServer::Ovh), + 6 => Pickle::unpickle(stream).map(DnsServer::Bunny), + 7 => Pickle::unpickle(stream).map(DnsServer::Porkbun), + 8 => Pickle::unpickle(stream).map(DnsServer::Dnsimple), + 9 => Pickle::unpickle(stream).map(DnsServer::Spaceship), + 10 => Pickle::unpickle(stream).map(DnsServer::Route53), + 11 => Pickle::unpickle(stream).map(DnsServer::GoogleCloudDns), + _ => None, + } + } +} + +impl IntoValue for DnsServer { + fn into_value(self) -> JmapValue<'static> { + match self { + DnsServer::Tsig(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Tsig".into())); + obj + } + DnsServer::Sig0(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sig0".into())); + obj + } + DnsServer::Cloudflare(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into())); + obj + } + DnsServer::DigitalOcean(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DigitalOcean".into())); + obj + } + DnsServer::DeSEC(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DeSEC".into())); + obj + } + DnsServer::Ovh(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ovh".into())); + obj + } + DnsServer::Bunny(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Bunny".into())); + obj + } + DnsServer::Porkbun(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Porkbun".into())); + obj + } + DnsServer::Dnsimple(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Dnsimple".into())); + obj + } + DnsServer::Spaceship(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Spaceship".into())); + obj + } + DnsServer::Route53(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Route53".into())); + obj + } + DnsServer::GoogleCloudDns(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("GoogleCloudDns".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DnsServer { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DnsServerType::Tsig => *self = DnsServer::Tsig(Default::default()), + DnsServerType::Sig0 => *self = DnsServer::Sig0(Default::default()), + DnsServerType::Cloudflare => *self = DnsServer::Cloudflare(Default::default()), + DnsServerType::DigitalOcean => *self = DnsServer::DigitalOcean(Default::default()), + DnsServerType::DeSEC => *self = DnsServer::DeSEC(Default::default()), + DnsServerType::Ovh => *self = DnsServer::Ovh(Default::default()), + DnsServerType::Bunny => *self = DnsServer::Bunny(Default::default()), + DnsServerType::Porkbun => *self = DnsServer::Porkbun(Default::default()), + DnsServerType::Dnsimple => *self = DnsServer::Dnsimple(Default::default()), + DnsServerType::Spaceship => *self = DnsServer::Spaceship(Default::default()), + DnsServerType::Route53 => *self = DnsServer::Route53(Default::default()), + DnsServerType::GoogleCloudDns => { + *self = DnsServer::GoogleCloudDns(Default::default()) + } + } + } + match self { + DnsServer::Tsig(inner) => inner.patch(pointer, value), + DnsServer::Sig0(inner) => inner.patch(pointer, value), + DnsServer::Cloudflare(inner) => inner.patch(pointer, value), + DnsServer::DigitalOcean(inner) => inner.patch(pointer, value), + DnsServer::DeSEC(inner) => inner.patch(pointer, value), + DnsServer::Ovh(inner) => inner.patch(pointer, value), + DnsServer::Bunny(inner) => inner.patch(pointer, value), + DnsServer::Porkbun(inner) => inner.patch(pointer, value), + DnsServer::Dnsimple(inner) => inner.patch(pointer, value), + DnsServer::Spaceship(inner) => inner.patch(pointer, value), + DnsServer::Route53(inner) => inner.patch(pointer, value), + DnsServer::GoogleCloudDns(inner) => inner.patch(pointer, value), + } + } +} + +impl DnsServer { + pub fn object_type(&self) -> DnsServerType { + match self { + DnsServer::Tsig(_) => DnsServerType::Tsig, + DnsServer::Sig0(_) => DnsServerType::Sig0, + DnsServer::Cloudflare(_) => DnsServerType::Cloudflare, + DnsServer::DigitalOcean(_) => DnsServerType::DigitalOcean, + DnsServer::DeSEC(_) => DnsServerType::DeSEC, + DnsServer::Ovh(_) => DnsServerType::Ovh, + DnsServer::Bunny(_) => DnsServerType::Bunny, + DnsServer::Porkbun(_) => DnsServerType::Porkbun, + DnsServer::Dnsimple(_) => DnsServerType::Dnsimple, + DnsServer::Spaceship(_) => DnsServerType::Spaceship, + DnsServer::Route53(_) => DnsServerType::Route53, + DnsServer::GoogleCloudDns(_) => DnsServerType::GoogleCloudDns, + } + } +} + +impl DnsServerBootstrap { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + DnsServerBootstrap::Manual => true, + DnsServerBootstrap::Tsig(inner) => inner.validate(errors), + DnsServerBootstrap::Sig0(inner) => inner.validate(errors), + DnsServerBootstrap::Cloudflare(inner) => inner.validate(errors), + DnsServerBootstrap::DigitalOcean(inner) => inner.validate(errors), + DnsServerBootstrap::DeSEC(inner) => inner.validate(errors), + DnsServerBootstrap::Ovh(inner) => inner.validate(errors), + DnsServerBootstrap::Bunny(inner) => inner.validate(errors), + DnsServerBootstrap::Porkbun(inner) => inner.validate(errors), + DnsServerBootstrap::Dnsimple(inner) => inner.validate(errors), + DnsServerBootstrap::Spaceship(inner) => inner.validate(errors), + DnsServerBootstrap::Route53(inner) => inner.validate(errors), + DnsServerBootstrap::GoogleCloudDns(inner) => inner.validate(errors), + } + } +} + +impl Default for DnsServerBootstrap { + fn default() -> Self { + DnsServerBootstrap::Manual + } +} + +impl Pickle for DnsServerBootstrap { + fn pickle(&self, out: &mut Vec) { + match self { + DnsServerBootstrap::Manual => { + 0u16.pickle(out); + } + DnsServerBootstrap::Tsig(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Sig0(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Cloudflare(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::DigitalOcean(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::DeSEC(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Ovh(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Bunny(inner) => { + 7u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Porkbun(inner) => { + 8u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Dnsimple(inner) => { + 9u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Spaceship(inner) => { + 10u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::Route53(inner) => { + 11u16.pickle(out); + inner.pickle(out); + } + DnsServerBootstrap::GoogleCloudDns(inner) => { + 12u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(DnsServerBootstrap::Manual), + 1 => Pickle::unpickle(stream).map(DnsServerBootstrap::Tsig), + 2 => Pickle::unpickle(stream).map(DnsServerBootstrap::Sig0), + 3 => Pickle::unpickle(stream).map(DnsServerBootstrap::Cloudflare), + 4 => Pickle::unpickle(stream).map(DnsServerBootstrap::DigitalOcean), + 5 => Pickle::unpickle(stream).map(DnsServerBootstrap::DeSEC), + 6 => Pickle::unpickle(stream).map(DnsServerBootstrap::Ovh), + 7 => Pickle::unpickle(stream).map(DnsServerBootstrap::Bunny), + 8 => Pickle::unpickle(stream).map(DnsServerBootstrap::Porkbun), + 9 => Pickle::unpickle(stream).map(DnsServerBootstrap::Dnsimple), + 10 => Pickle::unpickle(stream).map(DnsServerBootstrap::Spaceship), + 11 => Pickle::unpickle(stream).map(DnsServerBootstrap::Route53), + 12 => Pickle::unpickle(stream).map(DnsServerBootstrap::GoogleCloudDns), + _ => None, + } + } +} + +impl IntoValue for DnsServerBootstrap { + fn into_value(self) -> JmapValue<'static> { + match self { + DnsServerBootstrap::Manual => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Manual".into())); + JmapValue::Object(obj) + } + DnsServerBootstrap::Tsig(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Tsig".into())); + obj + } + DnsServerBootstrap::Sig0(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sig0".into())); + obj + } + DnsServerBootstrap::Cloudflare(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Cloudflare".into())); + obj + } + DnsServerBootstrap::DigitalOcean(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DigitalOcean".into())); + obj + } + DnsServerBootstrap::DeSEC(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DeSEC".into())); + obj + } + DnsServerBootstrap::Ovh(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ovh".into())); + obj + } + DnsServerBootstrap::Bunny(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Bunny".into())); + obj + } + DnsServerBootstrap::Porkbun(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Porkbun".into())); + obj + } + DnsServerBootstrap::Dnsimple(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Dnsimple".into())); + obj + } + DnsServerBootstrap::Spaceship(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Spaceship".into())); + obj + } + DnsServerBootstrap::Route53(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Route53".into())); + obj + } + DnsServerBootstrap::GoogleCloudDns(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("GoogleCloudDns".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for DnsServerBootstrap { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + DnsServerBootstrapType::Manual => *self = DnsServerBootstrap::Manual, + DnsServerBootstrapType::Tsig => { + *self = DnsServerBootstrap::Tsig(Default::default()) + } + DnsServerBootstrapType::Sig0 => { + *self = DnsServerBootstrap::Sig0(Default::default()) + } + DnsServerBootstrapType::Cloudflare => { + *self = DnsServerBootstrap::Cloudflare(Default::default()) + } + DnsServerBootstrapType::DigitalOcean => { + *self = DnsServerBootstrap::DigitalOcean(Default::default()) + } + DnsServerBootstrapType::DeSEC => { + *self = DnsServerBootstrap::DeSEC(Default::default()) + } + DnsServerBootstrapType::Ovh => *self = DnsServerBootstrap::Ovh(Default::default()), + DnsServerBootstrapType::Bunny => { + *self = DnsServerBootstrap::Bunny(Default::default()) + } + DnsServerBootstrapType::Porkbun => { + *self = DnsServerBootstrap::Porkbun(Default::default()) + } + DnsServerBootstrapType::Dnsimple => { + *self = DnsServerBootstrap::Dnsimple(Default::default()) + } + DnsServerBootstrapType::Spaceship => { + *self = DnsServerBootstrap::Spaceship(Default::default()) + } + DnsServerBootstrapType::Route53 => { + *self = DnsServerBootstrap::Route53(Default::default()) + } + DnsServerBootstrapType::GoogleCloudDns => { + *self = DnsServerBootstrap::GoogleCloudDns(Default::default()) + } + } + } + match self { + DnsServerBootstrap::Manual => pointer.assert_eof(), + DnsServerBootstrap::Tsig(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Sig0(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Cloudflare(inner) => inner.patch(pointer, value), + DnsServerBootstrap::DigitalOcean(inner) => inner.patch(pointer, value), + DnsServerBootstrap::DeSEC(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Ovh(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Bunny(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Porkbun(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Dnsimple(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Spaceship(inner) => inner.patch(pointer, value), + DnsServerBootstrap::Route53(inner) => inner.patch(pointer, value), + DnsServerBootstrap::GoogleCloudDns(inner) => inner.patch(pointer, value), + } + } +} + +impl DnsServerBootstrap { + pub fn object_type(&self) -> DnsServerBootstrapType { + match self { + DnsServerBootstrap::Manual => DnsServerBootstrapType::Manual, + DnsServerBootstrap::Tsig(_) => DnsServerBootstrapType::Tsig, + DnsServerBootstrap::Sig0(_) => DnsServerBootstrapType::Sig0, + DnsServerBootstrap::Cloudflare(_) => DnsServerBootstrapType::Cloudflare, + DnsServerBootstrap::DigitalOcean(_) => DnsServerBootstrapType::DigitalOcean, + DnsServerBootstrap::DeSEC(_) => DnsServerBootstrapType::DeSEC, + DnsServerBootstrap::Ovh(_) => DnsServerBootstrapType::Ovh, + DnsServerBootstrap::Bunny(_) => DnsServerBootstrapType::Bunny, + DnsServerBootstrap::Porkbun(_) => DnsServerBootstrapType::Porkbun, + DnsServerBootstrap::Dnsimple(_) => DnsServerBootstrapType::Dnsimple, + DnsServerBootstrap::Spaceship(_) => DnsServerBootstrapType::Spaceship, + DnsServerBootstrap::Route53(_) => DnsServerBootstrapType::Route53, + DnsServerBootstrap::GoogleCloudDns(_) => DnsServerBootstrapType::GoogleCloudDns, + } + } +} + +impl DnsServerCloud { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.secret; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerCloud { + fn pickle(&self, out: &mut Vec) { + self.secret.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.secret = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerCloud { + fn default() -> Self { + Self { + secret: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerCloud { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerCloud { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerCloudflare { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.email { + if value.is_empty() { + errors.push(ValidationError::required(Property::Email)); + } + } + let value = &self.secret; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerCloudflare { + fn pickle(&self, out: &mut Vec) { + self.email.pickle(out); + self.secret.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.email = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerCloudflare { + fn default() -> Self { + Self { + email: Default::default(), + secret: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerCloudflare { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Email, self.email.into_value()); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerCloudflare { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Email) => self + .email + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerDnsimple { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.auth_token; + value.validate(errors); + let value = &self.account_identifier; + if value.is_empty() { + errors.push(ValidationError::required(Property::AccountIdentifier)); + } + let value = &self.secret; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerDnsimple { + fn pickle(&self, out: &mut Vec) { + self.auth_token.pickle(out); + self.account_identifier.pickle(out); + self.secret.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.auth_token = Pickle::unpickle(stream)?; + this.account_identifier = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerDnsimple { + fn default() -> Self { + Self { + auth_token: Default::default(), + account_identifier: Default::default(), + secret: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerDnsimple { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::AuthToken, self.auth_token.into_value()); + map.insert_unchecked( + Property::AccountIdentifier, + self.account_identifier.into_value(), + ); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerDnsimple { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AuthToken) => self.auth_token.patch(pointer, value), + Some(Property::AccountIdentifier) => self + .account_identifier + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerGoogleCloudDns { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.service_account_json; + value.validate(errors); + let value = &self.project_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::ProjectId)); + } + if let Some(value) = &self.managed_zone { + if value.is_empty() { + errors.push(ValidationError::required(Property::ManagedZone)); + } + } + if let Some(value) = &self.impersonate_service_account { + if value.is_empty() { + errors.push(ValidationError::required( + Property::ImpersonateServiceAccount, + )); + } + } + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerGoogleCloudDns { + fn pickle(&self, out: &mut Vec) { + self.service_account_json.pickle(out); + self.project_id.pickle(out); + self.managed_zone.pickle(out); + self.private_zone.pickle(out); + self.impersonate_service_account.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.service_account_json = Pickle::unpickle(stream)?; + this.project_id = Pickle::unpickle(stream)?; + this.managed_zone = Pickle::unpickle(stream)?; + this.private_zone = Pickle::unpickle(stream)?; + this.impersonate_service_account = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerGoogleCloudDns { + fn default() -> Self { + Self { + service_account_json: Default::default(), + project_id: Default::default(), + managed_zone: Default::default(), + private_zone: false, + impersonate_service_account: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerGoogleCloudDns { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked( + Property::ServiceAccountJson, + self.service_account_json.into_value(), + ); + map.insert_unchecked(Property::ProjectId, self.project_id.into_value()); + map.insert_unchecked(Property::ManagedZone, self.managed_zone.into_value()); + map.insert_unchecked(Property::PrivateZone, self.private_zone.into_value()); + map.insert_unchecked( + Property::ImpersonateServiceAccount, + self.impersonate_service_account.into_value(), + ); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerGoogleCloudDns { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ServiceAccountJson) => self.service_account_json.patch(pointer, value), + Some(Property::ProjectId) => self + .project_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ManagedZone) => self + .managed_zone + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PrivateZone) => self.private_zone.patch(pointer, value), + Some(Property::ImpersonateServiceAccount) => self + .impersonate_service_account + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerOvh { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.application_key; + if value.is_empty() { + errors.push(ValidationError::required(Property::ApplicationKey)); + } + let value = &self.application_secret; + value.validate(errors); + let value = &self.consumer_key; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerOvh { + fn pickle(&self, out: &mut Vec) { + self.application_key.pickle(out); + self.application_secret.pickle(out); + self.consumer_key.pickle(out); + self.ovh_endpoint.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.application_key = Pickle::unpickle(stream)?; + this.application_secret = Pickle::unpickle(stream)?; + this.consumer_key = Pickle::unpickle(stream)?; + this.ovh_endpoint = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerOvh { + fn default() -> Self { + Self { + application_key: Default::default(), + application_secret: Default::default(), + consumer_key: Default::default(), + ovh_endpoint: OvhEndpoint::OvhEu, + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerOvh { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::ApplicationKey, self.application_key.into_value()); + map.insert_unchecked( + Property::ApplicationSecret, + self.application_secret.into_value(), + ); + map.insert_unchecked(Property::ConsumerKey, self.consumer_key.into_value()); + map.insert_unchecked(Property::OvhEndpoint, self.ovh_endpoint.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerOvh { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ApplicationKey) => self + .application_key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ApplicationSecret) => self.application_secret.patch(pointer, value), + Some(Property::ConsumerKey) => self.consumer_key.patch(pointer, value), + Some(Property::OvhEndpoint) => self.ovh_endpoint.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerPorkbun { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.api_key; + if value.is_empty() { + errors.push(ValidationError::required(Property::ApiKey)); + } + let value = &self.secret_api_key; + value.validate(errors); + let value = &self.secret; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerPorkbun { + fn pickle(&self, out: &mut Vec) { + self.api_key.pickle(out); + self.secret_api_key.pickle(out); + self.secret.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.api_key = Pickle::unpickle(stream)?; + this.secret_api_key = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerPorkbun { + fn default() -> Self { + Self { + api_key: Default::default(), + secret_api_key: Default::default(), + secret: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerPorkbun { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::ApiKey, self.api_key.into_value()); + map.insert_unchecked(Property::SecretApiKey, self.secret_api_key.into_value()); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerPorkbun { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ApiKey) => self + .api_key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::SecretApiKey) => self.secret_api_key.patch(pointer, value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerRoute53 { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.access_key_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::AccessKeyId)); + } + let value = &self.secret_access_key; + value.validate(errors); + let value = &self.session_token; + value.validate(errors); + let value = &self.region; + if value.is_empty() { + errors.push(ValidationError::required(Property::Region)); + } + if let Some(value) = &self.hosted_zone_id { + if value.is_empty() { + errors.push(ValidationError::required(Property::HostedZoneId)); + } + } + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerRoute53 { + fn pickle(&self, out: &mut Vec) { + self.access_key_id.pickle(out); + self.secret_access_key.pickle(out); + self.session_token.pickle(out); + self.region.pickle(out); + self.hosted_zone_id.pickle(out); + self.private_zone_only.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.access_key_id = Pickle::unpickle(stream)?; + this.secret_access_key = Pickle::unpickle(stream)?; + this.session_token = Pickle::unpickle(stream)?; + this.region = Pickle::unpickle(stream)?; + this.hosted_zone_id = Pickle::unpickle(stream)?; + this.private_zone_only = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerRoute53 { + fn default() -> Self { + Self { + access_key_id: Default::default(), + secret_access_key: Default::default(), + session_token: Default::default(), + region: "us-east-1".to_string(), + hosted_zone_id: Default::default(), + private_zone_only: false, + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerRoute53 { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked(Property::AccessKeyId, self.access_key_id.into_value()); + map.insert_unchecked( + Property::SecretAccessKey, + self.secret_access_key.into_value(), + ); + map.insert_unchecked(Property::SessionToken, self.session_token.into_value()); + map.insert_unchecked(Property::Region, self.region.into_value()); + map.insert_unchecked(Property::HostedZoneId, self.hosted_zone_id.into_value()); + map.insert_unchecked( + Property::PrivateZoneOnly, + self.private_zone_only.into_value(), + ); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerRoute53 { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccessKeyId) => self + .access_key_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::SecretAccessKey) => self.secret_access_key.patch(pointer, value), + Some(Property::SessionToken) => self.session_token.patch(pointer, value), + Some(Property::Region) => self + .region + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::HostedZoneId) => self + .hosted_zone_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PrivateZoneOnly) => self.private_zone_only.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerSig0 { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.host; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Host, value)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.public_key; + if value.is_empty() { + errors.push(ValidationError::required(Property::PublicKey)); + } + let value = &self.key; + value.validate(errors); + let value = &self.signer_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::SignerName)); + } + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerSig0 { + fn pickle(&self, out: &mut Vec) { + self.host.pickle(out); + self.port.pickle(out); + self.public_key.pickle(out); + self.key.pickle(out); + self.signer_name.pickle(out); + self.protocol.pickle(out); + self.sig0_algorithm.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.public_key = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.signer_name = Pickle::unpickle(stream)?; + this.protocol = Pickle::unpickle(stream)?; + this.sig0_algorithm = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerSig0 { + fn default() -> Self { + Self { + host: Default::default(), + port: 53u64, + public_key: Default::default(), + key: Default::default(), + signer_name: Default::default(), + protocol: IpProtocol::Udp, + sig0_algorithm: Sig0Algorithm::Ed25519, + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerSig0 { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::PublicKey, self.public_key.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::SignerName, self.signer_name.into_value()); + map.insert_unchecked(Property::Protocol, self.protocol.into_value()); + map.insert_unchecked(Property::Sig0Algorithm, self.sig0_algorithm.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerSig0 { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::PublicKey) => self + .public_key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::SignerName) => self + .signer_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Protocol) => self.protocol.patch(pointer, value), + Some(Property::Sig0Algorithm) => self.sig0_algorithm.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerSpaceship { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.api_key; + if value.is_empty() { + errors.push(ValidationError::required(Property::ApiKey)); + } + let value = &self.secret; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerSpaceship { + fn pickle(&self, out: &mut Vec) { + self.api_key.pickle(out); + self.secret.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.api_key = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerSpaceship { + fn default() -> Self { + Self { + api_key: Default::default(), + secret: Default::default(), + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerSpaceship { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::ApiKey, self.api_key.into_value()); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerSpaceship { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ApiKey) => self + .api_key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl DnsServerTsig { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.host; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Host, value)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.key_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::KeyName)); + } + let value = &self.key; + value.validate(errors); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for DnsServerTsig { + fn pickle(&self, out: &mut Vec) { + self.host.pickle(out); + self.port.pickle(out); + self.key_name.pickle(out); + self.key.pickle(out); + self.protocol.pickle(out); + self.tsig_algorithm.pickle(out); + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.timeout.pickle(out); + self.ttl.pickle(out); + self.polling_interval.pickle(out); + self.propagation_timeout.pickle(out); + self.propagation_delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.key_name = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.protocol = Pickle::unpickle(stream)?; + this.tsig_algorithm = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.ttl = Pickle::unpickle(stream)?; + this.polling_interval = Pickle::unpickle(stream)?; + this.propagation_timeout = Pickle::unpickle(stream)?; + this.propagation_delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DnsServerTsig { + fn default() -> Self { + Self { + host: Default::default(), + port: 53u64, + key_name: Default::default(), + key: Default::default(), + protocol: IpProtocol::Udp, + tsig_algorithm: TsigAlgorithm::HmacSha512, + description: Default::default(), + member_tenant_id: Default::default(), + timeout: Duration::from_millis(30000), + ttl: Duration::from_millis(300000), + polling_interval: Duration::from_millis(15000), + propagation_timeout: Duration::from_millis(60000), + propagation_delay: Default::default(), + } + } +} + +impl IntoValue for DnsServerTsig { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::KeyName, self.key_name.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Protocol, self.protocol.into_value()); + map.insert_unchecked(Property::TsigAlgorithm, self.tsig_algorithm.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Ttl, self.ttl.into_value()); + map.insert_unchecked( + Property::PollingInterval, + self.polling_interval.into_value(), + ); + map.insert_unchecked( + Property::PropagationTimeout, + self.propagation_timeout.into_value(), + ); + map.insert_unchecked( + Property::PropagationDelay, + self.propagation_delay.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DnsServerTsig { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::KeyName) => self + .key_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Protocol) => self.protocol.patch(pointer, value), + Some(Property::TsigAlgorithm) => self.tsig_algorithm.patch(pointer, value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Ttl) => self.ttl.patch(pointer, value), + Some(Property::PollingInterval) => self.polling_interval.patch(pointer, value), + Some(Property::PropagationTimeout) => self.propagation_timeout.patch(pointer, value), + Some(Property::PropagationDelay) => self.propagation_delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Domain { + const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Domain; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.aliases; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Aliases)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + if let Some(value) = &self.logo { + if value.is_empty() { + errors.push(ValidationError::required(Property::Logo)); + } + } + let value = &self.certificate_management; + value.validate(errors); + let value = &self.dkim_management; + value.validate(errors); + let value = &self.dns_management; + value.validate(errors); + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + if let Some(value) = &self.directory_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DirectoryId)); + } + } + if let Some(value) = &self.catch_all_address { + if value.is_empty() { + errors.push(ValidationError::required(Property::CatchAllAddress)); + } + } + let value = &self.sub_addressing; + value.validate(errors); + if let Some(value) = &self.report_address_uri { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportAddressUri)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + i.text(Property::Text, &self.name); + for value in self.aliases.iter() { + i.text(Property::Text, value); + } + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + self.certificate_management.index(i); + self.dns_management.index(i); + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + i.foreign_key(ObjectType::Directory, self.directory_id, None); + } +} + +impl Pickle for Domain { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.aliases.pickle(out); + self.is_enabled.pickle(out); + self.created_at.pickle(out); + self.description.pickle(out); + self.logo.pickle(out); + self.certificate_management.pickle(out); + self.dkim_management.pickle(out); + self.dns_management.pickle(out); + self.member_tenant_id.pickle(out); + self.directory_id.pickle(out); + self.catch_all_address.pickle(out); + self.sub_addressing.pickle(out); + self.allow_relaying.pickle(out); + self.report_address_uri.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.aliases = Pickle::unpickle(stream)?; + this.is_enabled = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.logo = Pickle::unpickle(stream)?; + this.certificate_management = Pickle::unpickle(stream)?; + this.dkim_management = Pickle::unpickle(stream)?; + this.dns_management = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.directory_id = Pickle::unpickle(stream)?; + this.catch_all_address = Pickle::unpickle(stream)?; + this.sub_addressing = Pickle::unpickle(stream)?; + this.allow_relaying = Pickle::unpickle(stream)?; + this.report_address_uri = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Domain { + fn default() -> Self { + Self { + name: Default::default(), + aliases: Default::default(), + is_enabled: true, + created_at: Default::default(), + description: Default::default(), + logo: Default::default(), + certificate_management: Default::default(), + dkim_management: Default::default(), + dns_management: Default::default(), + member_tenant_id: Default::default(), + directory_id: Default::default(), + catch_all_address: Default::default(), + sub_addressing: Default::default(), + allow_relaying: false, + report_address_uri: Some("mailto:postmaster".to_string()), + } + } +} + +impl IntoValue for Domain { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(17); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Aliases, self.aliases.into_value()); + map.insert_unchecked(Property::IsEnabled, self.is_enabled.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Logo, self.logo.into_value()); + map.insert_unchecked( + Property::CertificateManagement, + self.certificate_management.into_value(), + ); + map.insert_unchecked(Property::DkimManagement, self.dkim_management.into_value()); + map.insert_unchecked(Property::DnsManagement, self.dns_management.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::DirectoryId, self.directory_id.into_value()); + map.insert_unchecked( + Property::CatchAllAddress, + self.catch_all_address.into_value(), + ); + map.insert_unchecked(Property::SubAddressing, self.sub_addressing.into_value()); + map.insert_unchecked(Property::AllowRelaying, self.allow_relaying.into_value()); + map.insert_unchecked( + Property::ReportAddressUri, + self.report_address_uri.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Domain { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self + .name + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::Aliases) => self + .aliases + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::IsEnabled) => self.is_enabled.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Logo) => self.logo.patch(pointer, value), + Some(Property::CertificateManagement) => { + self.certificate_management.patch(pointer, value) + } + Some(Property::DkimManagement) => self.dkim_management.patch(pointer, value), + Some(Property::DnsManagement) => self.dns_management.patch(pointer, value), + Some(Property::DnsZoneFile) => pointer.assert_server_set(), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::DirectoryId) => self.directory_id.patch(pointer, value), + Some(Property::CatchAllAddress) => self + .catch_all_address + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::SubAddressing) => self.sub_addressing.patch(pointer, value), + Some(Property::AllowRelaying) => self.allow_relaying.patch(pointer, value), + Some(Property::ReportAddressUri) => self + .report_address_uri + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for DsnReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::DsnReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from_address; + value.validate(errors); + let value = &self.from_name; + value.validate(errors); + let value = &self.dkim_sign_domain; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl DsnReportSettings { + pub fn ctx_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_address, + default: Some(Expression { + else_: "'MAILER-DAEMON@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::FromAddress, + allowed_variables: MTA_QUEUE_SENDER_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_name, + default: Some(Expression { + else_: "'Mail Delivery Subsystem'".to_string(), + ..Default::default() + }), + property: Property::FromName, + allowed_variables: MTA_QUEUE_SENDER_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_QUEUE_SENDER_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_from_address(), + self.ctx_from_name(), + self.ctx_dkim_sign_domain(), + ] + } +} + +impl Pickle for DsnReportSettings { + fn pickle(&self, out: &mut Vec) { + self.from_address.pickle(out); + self.from_name.pickle(out); + self.dkim_sign_domain.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from_address = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.dkim_sign_domain = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for DsnReportSettings { + fn default() -> Self { + Self { + from_address: Expression { + else_: "'MAILER-DAEMON@' + system('domain')".to_string(), + ..Default::default() + }, + from_name: Expression { + else_: "'Mail Delivery Subsystem'".to_string(), + ..Default::default() + }, + dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for DsnReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::FromAddress, self.from_address.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for DsnReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::FromAddress) => self.from_address.patch(pointer, value), + Some(Property::FromName) => self.from_name.patch(pointer, value), + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ElasticSearchStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.num_replicas; + if *value > 2048 { + errors.push(ValidationError::max_value(Property::NumReplicas, 2048)); + } + let value = &self.num_shards; + if *value > 1048576 { + errors.push(ValidationError::max_value(Property::NumShards, 1048576)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::NumShards, 1)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for ElasticSearchStore { + fn pickle(&self, out: &mut Vec) { + self.url.pickle(out); + self.num_replicas.pickle(out); + self.num_shards.pickle(out); + self.include_source.pickle(out); + self.timeout.pickle(out); + self.allow_invalid_certs.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.url = Pickle::unpickle(stream)?; + this.num_replicas = Pickle::unpickle(stream)?; + this.num_shards = Pickle::unpickle(stream)?; + this.include_source = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ElasticSearchStore { + fn default() -> Self { + Self { + url: Default::default(), + num_replicas: 0u64, + num_shards: 3u64, + include_source: false, + timeout: Duration::from_millis(30000), + allow_invalid_certs: false, + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for ElasticSearchStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::NumReplicas, self.num_replicas.into_value()); + map.insert_unchecked(Property::NumShards, self.num_shards.into_value()); + map.insert_unchecked(Property::IncludeSource, self.include_source.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ElasticSearchStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::NumReplicas) => self.num_replicas.patch(pointer, value), + Some(Property::NumShards) => self.num_shards.patch(pointer, value), + Some(Property::IncludeSource) => self.include_source.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Email { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Email; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_attachment_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAttachmentSize, 1)); + } + let value = &self.max_message_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMessageSize, 1)); + } + let value = &self.max_mailbox_depth; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMailboxDepth, 1)); + } + let value = &self.max_mailbox_name_length; + if *value < 1 { + errors.push(ValidationError::min_value( + Property::MaxMailboxNameLength, + 1, + )); + } + let value = &self.default_folders; + for value in value.values() { + value.validate(errors); + } + if let Some(value) = &self.max_messages { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMessages, 1)); + } + } + if let Some(value) = &self.max_submissions { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxSubmissions, 1)); + } + } + if let Some(value) = &self.max_identities { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxIdentities, 1)); + } + } + if let Some(value) = &self.max_mailboxes { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMailboxes, 1)); + } + } + if let Some(value) = &self.max_masked_addresses { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMaskedAddresses, 1)); + } + } + if let Some(value) = &self.max_public_keys { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxPublicKeys, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Email { + fn pickle(&self, out: &mut Vec) { + self.max_attachment_size.pickle(out); + self.max_message_size.pickle(out); + self.max_mailbox_depth.pickle(out); + self.max_mailbox_name_length.pickle(out); + self.encrypt_on_append.pickle(out); + self.encrypt_at_rest.pickle(out); + self.compression_algorithm.pickle(out); + self.default_folders.pickle(out); + self.max_messages.pickle(out); + self.max_submissions.pickle(out); + self.max_identities.pickle(out); + self.max_mailboxes.pickle(out); + self.max_masked_addresses.pickle(out); + self.max_public_keys.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_attachment_size = Pickle::unpickle(stream)?; + this.max_message_size = Pickle::unpickle(stream)?; + this.max_mailbox_depth = Pickle::unpickle(stream)?; + this.max_mailbox_name_length = Pickle::unpickle(stream)?; + this.encrypt_on_append = Pickle::unpickle(stream)?; + this.encrypt_at_rest = Pickle::unpickle(stream)?; + this.compression_algorithm = Pickle::unpickle(stream)?; + this.default_folders = Pickle::unpickle(stream)?; + this.max_messages = Pickle::unpickle(stream)?; + this.max_submissions = Pickle::unpickle(stream)?; + this.max_identities = Pickle::unpickle(stream)?; + this.max_mailboxes = Pickle::unpickle(stream)?; + this.max_masked_addresses = Pickle::unpickle(stream)?; + this.max_public_keys = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Email { + fn default() -> Self { + Self { + max_attachment_size: 50000000u64, + max_message_size: 75000000u64, + max_mailbox_depth: 10u64, + max_mailbox_name_length: 255u64, + encrypt_on_append: false, + encrypt_at_rest: true, + compression_algorithm: CompressionAlgo::Lz4, + default_folders: Default::default(), + max_messages: Default::default(), + max_submissions: Some(500u64), + max_identities: Some(20u64), + max_mailboxes: Some(250u64), + max_masked_addresses: Some(5u64), + max_public_keys: Some(5u64), + } + } +} + +impl IntoValue for Email { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked( + Property::MaxAttachmentSize, + self.max_attachment_size.into_value(), + ); + map.insert_unchecked(Property::MaxMessageSize, self.max_message_size.into_value()); + map.insert_unchecked( + Property::MaxMailboxDepth, + self.max_mailbox_depth.into_value(), + ); + map.insert_unchecked( + Property::MaxMailboxNameLength, + self.max_mailbox_name_length.into_value(), + ); + map.insert_unchecked( + Property::EncryptOnAppend, + self.encrypt_on_append.into_value(), + ); + map.insert_unchecked(Property::EncryptAtRest, self.encrypt_at_rest.into_value()); + map.insert_unchecked( + Property::CompressionAlgorithm, + self.compression_algorithm.into_value(), + ); + map.insert_unchecked(Property::DefaultFolders, self.default_folders.into_value()); + map.insert_unchecked(Property::MaxMessages, self.max_messages.into_value()); + map.insert_unchecked(Property::MaxSubmissions, self.max_submissions.into_value()); + map.insert_unchecked(Property::MaxIdentities, self.max_identities.into_value()); + map.insert_unchecked(Property::MaxMailboxes, self.max_mailboxes.into_value()); + map.insert_unchecked( + Property::MaxMaskedAddresses, + self.max_masked_addresses.into_value(), + ); + map.insert_unchecked(Property::MaxPublicKeys, self.max_public_keys.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Email { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxAttachmentSize) => self.max_attachment_size.patch(pointer, value), + Some(Property::MaxMessageSize) => self.max_message_size.patch(pointer, value), + Some(Property::MaxMailboxDepth) => self.max_mailbox_depth.patch(pointer, value), + Some(Property::MaxMailboxNameLength) => { + self.max_mailbox_name_length.patch(pointer, value) + } + Some(Property::EncryptOnAppend) => self.encrypt_on_append.patch(pointer, value), + Some(Property::EncryptAtRest) => self.encrypt_at_rest.patch(pointer, value), + Some(Property::CompressionAlgorithm) => { + self.compression_algorithm.patch(pointer, value) + } + Some(Property::DefaultFolders) => self.default_folders.patch(pointer, value), + Some(Property::MaxMessages) => self.max_messages.patch(pointer, value), + Some(Property::MaxSubmissions) => self.max_submissions.patch(pointer, value), + Some(Property::MaxIdentities) => self.max_identities.patch(pointer, value), + Some(Property::MaxMailboxes) => self.max_mailboxes.patch(pointer, value), + Some(Property::MaxMaskedAddresses) => self.max_masked_addresses.patch(pointer, value), + Some(Property::MaxPublicKeys) => self.max_public_keys.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl EmailAlias { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Email, &self.name, &self.domain_id); + i.text(Property::Text, &self.name); + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + } +} + +impl Pickle for EmailAlias { + fn pickle(&self, out: &mut Vec) { + self.enabled.pickle(out); + self.name.pickle(out); + self.domain_id.pickle(out); + self.description.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enabled = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for EmailAlias { + fn default() -> Self { + Self { + enabled: true, + name: Default::default(), + domain_id: Default::default(), + description: Default::default(), + } + } +} + +impl IntoValue for EmailAlias { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Enabled, self.enabled.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for EmailAlias { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enabled) => self.enabled.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer.with_validators(&[StringValidator::EmailLocalPart]), + value, + ), + Some(Property::DomainId) => self.domain_id.patch(pointer, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl EmailFolder { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.aliases; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Aliases)); + } + } + errors.len() == neb + } +} + +impl Pickle for EmailFolder { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.create.pickle(out); + self.subscribe.pickle(out); + self.aliases.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.create = Pickle::unpickle(stream)?; + this.subscribe = Pickle::unpickle(stream)?; + this.aliases = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for EmailFolder { + fn default() -> Self { + Self { + name: Default::default(), + create: true, + subscribe: true, + aliases: Default::default(), + } + } +} + +impl IntoValue for EmailFolder { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Create, self.create.into_value()); + map.insert_unchecked(Property::Subscribe, self.subscribe.into_value()); + map.insert_unchecked(Property::Aliases, self.aliases.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for EmailFolder { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self + .name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Create) => self.create.patch(pointer, value), + Some(Property::Subscribe) => self.subscribe.patch(pointer, value), + Some(Property::Aliases) => self + .aliases + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl EncryptionAtRest { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + EncryptionAtRest::Disabled => true, + EncryptionAtRest::Aes128(inner) => inner.validate(errors), + EncryptionAtRest::Aes256(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + EncryptionAtRest::Disabled => {} + EncryptionAtRest::Aes128(object) => { + object.index(i); + } + EncryptionAtRest::Aes256(object) => { + object.index(i); + } + } + } +} + +impl Default for EncryptionAtRest { + fn default() -> Self { + EncryptionAtRest::Disabled + } +} + +impl Pickle for EncryptionAtRest { + fn pickle(&self, out: &mut Vec) { + match self { + EncryptionAtRest::Disabled => { + 0u16.pickle(out); + } + EncryptionAtRest::Aes128(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + EncryptionAtRest::Aes256(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(EncryptionAtRest::Disabled), + 1 => Pickle::unpickle(stream).map(EncryptionAtRest::Aes128), + 2 => Pickle::unpickle(stream).map(EncryptionAtRest::Aes256), + _ => None, + } + } +} + +impl IntoValue for EncryptionAtRest { + fn into_value(self) -> JmapValue<'static> { + match self { + EncryptionAtRest::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + EncryptionAtRest::Aes128(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Aes128".into())); + obj + } + EncryptionAtRest::Aes256(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Aes256".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for EncryptionAtRest { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + EncryptionAtRestType::Disabled => *self = EncryptionAtRest::Disabled, + EncryptionAtRestType::Aes128 => { + *self = EncryptionAtRest::Aes128(Default::default()) + } + EncryptionAtRestType::Aes256 => { + *self = EncryptionAtRest::Aes256(Default::default()) + } + } + } + match self { + EncryptionAtRest::Disabled => pointer.assert_eof(), + EncryptionAtRest::Aes128(inner) => inner.patch(pointer, value), + EncryptionAtRest::Aes256(inner) => inner.patch(pointer, value), + } + } +} + +impl EncryptionAtRest { + pub fn object_type(&self) -> EncryptionAtRestType { + match self { + EncryptionAtRest::Disabled => EncryptionAtRestType::Disabled, + EncryptionAtRest::Aes128(_) => EncryptionAtRestType::Aes128, + EncryptionAtRest::Aes256(_) => EncryptionAtRestType::Aes256, + } + } +} + +impl EncryptionSettings { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.public_key; + if !value.is_valid() { + errors.push(ValidationError::required(Property::PublicKey)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::PublicKey, self.public_key.into(), None); + } +} + +impl Pickle for EncryptionSettings { + fn pickle(&self, out: &mut Vec) { + self.public_key.pickle(out); + self.encrypt_on_append.pickle(out); + self.allow_spam_training.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.public_key = Pickle::unpickle(stream)?; + this.encrypt_on_append = Pickle::unpickle(stream)?; + this.allow_spam_training = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for EncryptionSettings { + fn default() -> Self { + Self { + public_key: Default::default(), + encrypt_on_append: false, + allow_spam_training: false, + } + } +} + +impl IntoValue for EncryptionSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::PublicKey, self.public_key.into_value()); + map.insert_unchecked( + Property::EncryptOnAppend, + self.encrypt_on_append.into_value(), + ); + map.insert_unchecked( + Property::AllowSpamTraining, + self.allow_spam_training.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for EncryptionSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::PublicKey) => self.public_key.patch(pointer, value), + Some(Property::EncryptOnAppend) => self.encrypt_on_append.patch(pointer, value), + Some(Property::AllowSpamTraining) => self.allow_spam_training.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Enterprise { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Enterprise; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.api_key; + value.validate(errors); + let value = &self.license_key; + value.validate(errors); + if let Some(value) = &self.logo_url { + if value.is_empty() { + errors.push(ValidationError::required(Property::LogoUrl)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Enterprise { + fn pickle(&self, out: &mut Vec) { + self.api_key.pickle(out); + self.license_key.pickle(out); + self.logo_url.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.api_key = Pickle::unpickle(stream)?; + this.license_key = Pickle::unpickle(stream)?; + this.logo_url = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Enterprise { + fn default() -> Self { + Self { + api_key: Default::default(), + license_key: Default::default(), + logo_url: Default::default(), + } + } +} + +impl IntoValue for Enterprise { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::ApiKey, self.api_key.into_value()); + map.insert_unchecked(Property::LicenseKey, self.license_key.into_value()); + map.insert_unchecked(Property::LogoUrl, self.logo_url.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Enterprise { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ApiKey) => self.api_key.patch(pointer, value), + Some(Property::LicenseKey) => self.license_key.patch(pointer, value), + Some(Property::LogoUrl) => self + .logo_url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for EventTracingLevel { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::EventTracingLevel; + + fn validate(&self, _: &mut Vec) -> bool { + true + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Event, &self.event); + } +} + +impl Pickle for EventTracingLevel { + fn pickle(&self, out: &mut Vec) { + self.event.pickle(out); + self.level.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.event = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for EventTracingLevel { + fn default() -> Self { + Self { + event: Default::default(), + level: TracingLevelOpt::Info, + } + } +} + +impl IntoValue for EventTracingLevel { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Event, self.event.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for EventTracingLevel { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Event) => self.event.patch(pointer.assert_read_only()?, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Expression { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.match_; + for value in value.values() { + value.validate(errors); + } + let value = &self.else_; + if value.is_empty() { + errors.push(ValidationError::required(Property::Else)); + } + errors.len() == neb + } +} + +impl Pickle for Expression { + fn pickle(&self, out: &mut Vec) { + self.match_.pickle(out); + self.else_.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.match_ = Pickle::unpickle(stream)?; + this.else_ = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Expression { + fn default() -> Self { + Self { + match_: Default::default(), + else_: Default::default(), + } + } +} + +impl IntoValue for Expression { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Match, self.match_.into_value()); + map.insert_unchecked(Property::Else, self.else_.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Expression { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Match) => self.match_.patch(pointer, value), + Some(Property::Else) => self.else_.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ExpressionMatch { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.if_; + if value.is_empty() { + errors.push(ValidationError::required(Property::If)); + } + let value = &self.then; + if value.is_empty() { + errors.push(ValidationError::required(Property::Then)); + } + errors.len() == neb + } +} + +impl Pickle for ExpressionMatch { + fn pickle(&self, out: &mut Vec) { + self.if_.pickle(out); + self.then.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.if_ = Pickle::unpickle(stream)?; + this.then = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ExpressionMatch { + fn default() -> Self { + Self { + if_: Default::default(), + then: Default::default(), + } + } +} + +impl IntoValue for ExpressionMatch { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::If, self.if_.into_value()); + map.insert_unchecked(Property::Then, self.then.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ExpressionMatch { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::If) => self.if_.patch(pointer, value), + Some(Property::Then) => self.then.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for FileStorage { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::FileStorage; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.max_files { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxFiles, 1)); + } + } + if let Some(value) = &self.max_folders { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxFolders, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for FileStorage { + fn pickle(&self, out: &mut Vec) { + self.max_size.pickle(out); + self.max_files.pickle(out); + self.max_folders.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_size = Pickle::unpickle(stream)?; + this.max_files = Pickle::unpickle(stream)?; + this.max_folders = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for FileStorage { + fn default() -> Self { + Self { + max_size: 26214400, + max_files: Default::default(), + max_folders: Default::default(), + } + } +} + +impl IntoValue for FileStorage { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::MaxSize, self.max_size.into_value()); + map.insert_unchecked(Property::MaxFiles, self.max_files.into_value()); + map.insert_unchecked(Property::MaxFolders, self.max_folders.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for FileStorage { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxSize) => self.max_size.patch(pointer, value), + Some(Property::MaxFiles) => self.max_files.patch(pointer, value), + Some(Property::MaxFolders) => self.max_folders.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl FileSystemStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.path; + if value.is_empty() { + errors.push(ValidationError::required(Property::Path)); + } + let value = &self.depth; + if *value > 5 { + errors.push(ValidationError::max_value(Property::Depth, 5)); + } + errors.len() == neb + } +} + +impl Pickle for FileSystemStore { + fn pickle(&self, out: &mut Vec) { + self.path.pickle(out); + self.depth.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.path = Pickle::unpickle(stream)?; + this.depth = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for FileSystemStore { + fn default() -> Self { + Self { + path: Default::default(), + depth: 2u64, + } + } +} + +impl IntoValue for FileSystemStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Path, self.path.into_value()); + map.insert_unchecked(Property::Depth, self.depth.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for FileSystemStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Path) => self + .path + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Depth) => self.depth.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl FoundationDbStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.cluster_file { + if value.is_empty() { + errors.push(ValidationError::required(Property::ClusterFile)); + } + } + if let Some(value) = &self.datacenter_id { + if value.is_empty() { + errors.push(ValidationError::required(Property::DatacenterId)); + } + } + if let Some(value) = &self.machine_id { + if value.is_empty() { + errors.push(ValidationError::required(Property::MachineId)); + } + } + if let Some(value) = &self.transaction_retry_limit { + if *value > 1000 { + errors.push(ValidationError::max_value( + Property::TransactionRetryLimit, + 1000, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value( + Property::TransactionRetryLimit, + 1, + )); + } + } + errors.len() == neb + } +} + +impl Pickle for FoundationDbStore { + fn pickle(&self, out: &mut Vec) { + self.cluster_file.pickle(out); + self.datacenter_id.pickle(out); + self.machine_id.pickle(out); + self.transaction_retry_delay.pickle(out); + self.transaction_retry_limit.pickle(out); + self.transaction_timeout.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.cluster_file = Pickle::unpickle(stream)?; + this.datacenter_id = Pickle::unpickle(stream)?; + this.machine_id = Pickle::unpickle(stream)?; + this.transaction_retry_delay = Pickle::unpickle(stream)?; + this.transaction_retry_limit = Pickle::unpickle(stream)?; + this.transaction_timeout = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for FoundationDbStore { + fn default() -> Self { + Self { + cluster_file: Default::default(), + datacenter_id: Default::default(), + machine_id: Default::default(), + transaction_retry_delay: Default::default(), + transaction_retry_limit: Default::default(), + transaction_timeout: Default::default(), + } + } +} + +impl IntoValue for FoundationDbStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::ClusterFile, self.cluster_file.into_value()); + map.insert_unchecked(Property::DatacenterId, self.datacenter_id.into_value()); + map.insert_unchecked(Property::MachineId, self.machine_id.into_value()); + map.insert_unchecked( + Property::TransactionRetryDelay, + self.transaction_retry_delay.into_value(), + ); + map.insert_unchecked( + Property::TransactionRetryLimit, + self.transaction_retry_limit.into_value(), + ); + map.insert_unchecked( + Property::TransactionTimeout, + self.transaction_timeout.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for FoundationDbStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ClusterFile) => self + .cluster_file + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DatacenterId) => self + .datacenter_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MachineId) => self + .machine_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::TransactionRetryDelay) => { + self.transaction_retry_delay.patch(pointer, value) + } + Some(Property::TransactionRetryLimit) => { + self.transaction_retry_limit.patch(pointer, value) + } + Some(Property::TransactionTimeout) => self.transaction_timeout.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl FtrlParameters { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.alpha; + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::Alpha, 0)); + } + let value = &self.beta; + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::Beta, 0)); + } + let value = &self.l1_ratio; + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::L1Ratio, 0)); + } + let value = &self.l2_ratio; + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::L2Ratio, 0)); + } + errors.len() == neb + } +} + +impl Pickle for FtrlParameters { + fn pickle(&self, out: &mut Vec) { + self.alpha.pickle(out); + self.beta.pickle(out); + self.num_features.pickle(out); + self.l1_ratio.pickle(out); + self.l2_ratio.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.alpha = Pickle::unpickle(stream)?; + this.beta = Pickle::unpickle(stream)?; + this.num_features = Pickle::unpickle(stream)?; + this.l1_ratio = Pickle::unpickle(stream)?; + this.l2_ratio = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for FtrlParameters { + fn default() -> Self { + Self { + alpha: Float::new(2.0f64), + beta: Float::new(1.0f64), + num_features: ModelSize::V20, + l1_ratio: Float::new(0.001f64), + l2_ratio: Float::new(0.0001f64), + } + } +} + +impl IntoValue for FtrlParameters { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Alpha, self.alpha.into_value()); + map.insert_unchecked(Property::Beta, self.beta.into_value()); + map.insert_unchecked(Property::NumFeatures, self.num_features.into_value()); + map.insert_unchecked(Property::L1Ratio, self.l1_ratio.into_value()); + map.insert_unchecked(Property::L2Ratio, self.l2_ratio.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for FtrlParameters { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Alpha) => self.alpha.patch(pointer, value), + Some(Property::Beta) => self.beta.patch(pointer, value), + Some(Property::NumFeatures) => self.num_features.patch(pointer, value), + Some(Property::L1Ratio) => self.l1_ratio.patch(pointer, value), + Some(Property::L2Ratio) => self.l2_ratio.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl GroupAccount { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.roles; + value.validate(errors); + let value = &self.permissions; + value.validate(errors); + let value = &self.aliases; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Email, &self.name, &self.domain_id); + i.text(Property::Text, &self.name); + i.search(Property::Name, &self.name); + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + i.search(Property::DomainId, &self.domain_id); + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + self.roles.index(i); + for item in self.aliases.values() { + item.index(i); + } + } +} + +impl Pickle for GroupAccount { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.domain_id.pickle(out); + self.description.pickle(out); + self.created_at.pickle(out); + self.member_tenant_id.pickle(out); + self.roles.pickle(out); + self.quotas.pickle(out); + self.permissions.pickle(out); + self.aliases.pickle(out); + self.locale.pickle(out); + self.time_zone.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.roles = Pickle::unpickle(stream)?; + this.quotas = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.aliases = Pickle::unpickle(stream)?; + this.locale = Pickle::unpickle(stream)?; + this.time_zone = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for GroupAccount { + fn default() -> Self { + Self { + name: Default::default(), + domain_id: Default::default(), + description: Default::default(), + created_at: Default::default(), + member_tenant_id: Default::default(), + roles: Default::default(), + quotas: Default::default(), + permissions: Default::default(), + aliases: Default::default(), + locale: Locale::EnUS, + time_zone: Default::default(), + } + } +} + +impl IntoValue for GroupAccount { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Roles, self.roles.into_value()); + map.insert_unchecked(Property::Quotas, self.quotas.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::Aliases, self.aliases.into_value()); + map.insert_unchecked(Property::Locale, self.locale.into_value()); + map.insert_unchecked(Property::TimeZone, self.time_zone.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for GroupAccount { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch( + pointer.with_validators(&[StringValidator::EmailLocalPart]), + value, + ), + Some(Property::DomainId) => self.domain_id.patch(pointer, value), + Some(Property::EmailAddress) => pointer.assert_server_set(), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Roles) => self.roles.patch(pointer, value), + Some(Property::Quotas) => self.quotas.patch(pointer, value), + Some(Property::UsedDiskQuota) => pointer.assert_server_set(), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::Aliases) => self.aliases.patch(pointer, value), + Some(Property::Locale) => self.locale.patch(pointer, value), + Some(Property::TimeZone) => self.time_zone.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Http { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Http; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.rate_limit_authenticated { + value.validate(errors); + } + if let Some(value) = &self.rate_limit_anonymous { + value.validate(errors); + } + let value = &self.allowed_endpoints; + value.validate(errors); + let value = &self.response_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseHeaders)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Http { + pub fn ctx_allowed_endpoints(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.allowed_endpoints, + default: Some(Expression { + else_: "200".to_string(), + ..Default::default() + }), + property: Property::AllowedEndpoints, + allowed_variables: HTTP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_allowed_endpoints()] + } +} + +impl Pickle for Http { + fn pickle(&self, out: &mut Vec) { + self.rate_limit_authenticated.pickle(out); + self.rate_limit_anonymous.pickle(out); + self.allowed_endpoints.pickle(out); + self.enable_hsts.pickle(out); + self.use_permissive_cors.pickle(out); + self.response_headers.pickle(out); + self.use_x_forwarded.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.rate_limit_authenticated = Pickle::unpickle(stream)?; + this.rate_limit_anonymous = Pickle::unpickle(stream)?; + this.allowed_endpoints = Pickle::unpickle(stream)?; + this.enable_hsts = Pickle::unpickle(stream)?; + this.use_permissive_cors = Pickle::unpickle(stream)?; + this.response_headers = Pickle::unpickle(stream)?; + this.use_x_forwarded = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Http { + fn default() -> Self { + Self { + rate_limit_authenticated: Some(Rate { + count: 1000u64, + period: Duration::from_millis(60000), + }), + rate_limit_anonymous: Some(Rate { + count: 100u64, + period: Duration::from_millis(60000), + }), + allowed_endpoints: Expression { + else_: "200".to_string(), + ..Default::default() + }, + enable_hsts: false, + use_permissive_cors: false, + response_headers: Default::default(), + use_x_forwarded: false, + } + } +} + +impl IntoValue for Http { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked( + Property::RateLimitAuthenticated, + self.rate_limit_authenticated.into_value(), + ); + map.insert_unchecked( + Property::RateLimitAnonymous, + self.rate_limit_anonymous.into_value(), + ); + map.insert_unchecked( + Property::AllowedEndpoints, + self.allowed_endpoints.into_value(), + ); + map.insert_unchecked(Property::EnableHsts, self.enable_hsts.into_value()); + map.insert_unchecked( + Property::UsePermissiveCors, + self.use_permissive_cors.into_value(), + ); + map.insert_unchecked( + Property::ResponseHeaders, + self.response_headers.into_value(), + ); + map.insert_unchecked(Property::UseXForwarded, self.use_x_forwarded.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Http { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::RateLimitAuthenticated) => { + self.rate_limit_authenticated.patch(pointer, value) + } + Some(Property::RateLimitAnonymous) => self.rate_limit_anonymous.patch(pointer, value), + Some(Property::AllowedEndpoints) => self.allowed_endpoints.patch(pointer, value), + Some(Property::EnableHsts) => self.enable_hsts.patch(pointer, value), + Some(Property::UsePermissiveCors) => self.use_permissive_cors.patch(pointer, value), + Some(Property::ResponseHeaders) => self + .response_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::UseXForwarded) => self.use_x_forwarded.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl HttpAuth { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + HttpAuth::Unauthenticated => true, + HttpAuth::Basic(inner) => inner.validate(errors), + HttpAuth::Bearer(inner) => inner.validate(errors), + } + } +} + +impl Default for HttpAuth { + fn default() -> Self { + HttpAuth::Unauthenticated + } +} + +impl Pickle for HttpAuth { + fn pickle(&self, out: &mut Vec) { + match self { + HttpAuth::Unauthenticated => { + 0u16.pickle(out); + } + HttpAuth::Basic(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + HttpAuth::Bearer(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(HttpAuth::Unauthenticated), + 1 => Pickle::unpickle(stream).map(HttpAuth::Basic), + 2 => Pickle::unpickle(stream).map(HttpAuth::Bearer), + _ => None, + } + } +} + +impl IntoValue for HttpAuth { + fn into_value(self) -> JmapValue<'static> { + match self { + HttpAuth::Unauthenticated => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Unauthenticated".into())); + JmapValue::Object(obj) + } + HttpAuth::Basic(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Basic".into())); + obj + } + HttpAuth::Bearer(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Bearer".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for HttpAuth { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + HttpAuthType::Unauthenticated => *self = HttpAuth::Unauthenticated, + HttpAuthType::Basic => *self = HttpAuth::Basic(Default::default()), + HttpAuthType::Bearer => *self = HttpAuth::Bearer(Default::default()), + } + } + match self { + HttpAuth::Unauthenticated => pointer.assert_eof(), + HttpAuth::Basic(inner) => inner.patch(pointer, value), + HttpAuth::Bearer(inner) => inner.patch(pointer, value), + } + } +} + +impl HttpAuth { + pub fn object_type(&self) -> HttpAuthType { + match self { + HttpAuth::Unauthenticated => HttpAuthType::Unauthenticated, + HttpAuth::Basic(_) => HttpAuthType::Basic, + HttpAuth::Bearer(_) => HttpAuthType::Bearer, + } + } +} + +impl HttpAuthBasic { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.username; + if value.is_empty() { + errors.push(ValidationError::required(Property::Username)); + } + let value = &self.secret; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for HttpAuthBasic { + fn pickle(&self, out: &mut Vec) { + self.username.pickle(out); + self.secret.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.username = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for HttpAuthBasic { + fn default() -> Self { + Self { + username: Default::default(), + secret: Default::default(), + } + } +} + +impl IntoValue for HttpAuthBasic { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Username, self.username.into_value()); + map.insert_unchecked(Property::Secret, self.secret.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for HttpAuthBasic { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Username) => self + .username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl HttpAuthBearer { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.bearer_token; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for HttpAuthBearer { + fn pickle(&self, out: &mut Vec) { + self.bearer_token.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.bearer_token = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for HttpAuthBearer { + fn default() -> Self { + Self { + bearer_token: Default::default(), + } + } +} + +impl IntoValue for HttpAuthBearer { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::BearerToken, self.bearer_token.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for HttpAuthBearer { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::BearerToken) => self.bearer_token.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for HttpForm { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::HttpForm; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.deliver_to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::DeliverTo)); + } + } + let value = &self.default_from_address; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultFromAddress)); + } + if let Some(value) = &self.field_email { + if value.is_empty() { + errors.push(ValidationError::required(Property::FieldEmail)); + } + } + if let Some(value) = &self.field_honey_pot { + if value.is_empty() { + errors.push(ValidationError::required(Property::FieldHoneyPot)); + } + } + let value = &self.default_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultName)); + } + if let Some(value) = &self.field_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::FieldName)); + } + } + if let Some(value) = &self.rate_limit { + value.validate(errors); + } + let value = &self.default_subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultSubject)); + } + if let Some(value) = &self.field_subject { + if value.is_empty() { + errors.push(ValidationError::required(Property::FieldSubject)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for HttpForm { + fn pickle(&self, out: &mut Vec) { + self.deliver_to.pickle(out); + self.default_from_address.pickle(out); + self.field_email.pickle(out); + self.enable.pickle(out); + self.field_honey_pot.pickle(out); + self.max_size.pickle(out); + self.default_name.pickle(out); + self.field_name.pickle(out); + self.rate_limit.pickle(out); + self.default_subject.pickle(out); + self.field_subject.pickle(out); + self.validate_domain.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.deliver_to = Pickle::unpickle(stream)?; + this.default_from_address = Pickle::unpickle(stream)?; + this.field_email = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.field_honey_pot = Pickle::unpickle(stream)?; + this.max_size = Pickle::unpickle(stream)?; + this.default_name = Pickle::unpickle(stream)?; + this.field_name = Pickle::unpickle(stream)?; + this.rate_limit = Pickle::unpickle(stream)?; + this.default_subject = Pickle::unpickle(stream)?; + this.field_subject = Pickle::unpickle(stream)?; + this.validate_domain = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for HttpForm { + fn default() -> Self { + Self { + deliver_to: Default::default(), + default_from_address: "postmaster@localhost".to_string(), + field_email: Default::default(), + enable: false, + field_honey_pot: Default::default(), + max_size: 102400, + default_name: "Anonymous".to_string(), + field_name: Default::default(), + rate_limit: Some(Rate { + count: 5u64, + period: Duration::from_millis(3600000), + }), + default_subject: "Contact form submission".to_string(), + field_subject: Default::default(), + validate_domain: true, + } + } +} + +impl IntoValue for HttpForm { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::DeliverTo, self.deliver_to.into_value()); + map.insert_unchecked( + Property::DefaultFromAddress, + self.default_from_address.into_value(), + ); + map.insert_unchecked(Property::FieldEmail, self.field_email.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::FieldHoneyPot, self.field_honey_pot.into_value()); + map.insert_unchecked(Property::MaxSize, self.max_size.into_value()); + map.insert_unchecked(Property::DefaultName, self.default_name.into_value()); + map.insert_unchecked(Property::FieldName, self.field_name.into_value()); + map.insert_unchecked(Property::RateLimit, self.rate_limit.into_value()); + map.insert_unchecked(Property::DefaultSubject, self.default_subject.into_value()); + map.insert_unchecked(Property::FieldSubject, self.field_subject.into_value()); + map.insert_unchecked(Property::ValidateDomain, self.validate_domain.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for HttpForm { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DeliverTo) => self + .deliver_to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::DefaultFromAddress) => self + .default_from_address + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::FieldEmail) => self + .field_email + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::FieldHoneyPot) => self + .field_honey_pot + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MaxSize) => self.max_size.patch(pointer, value), + Some(Property::DefaultName) => self + .default_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::FieldName) => self + .field_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::RateLimit) => self.rate_limit.patch(pointer, value), + Some(Property::DefaultSubject) => self + .default_subject + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::FieldSubject) => self + .field_subject + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ValidateDomain) => self.validate_domain.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for HttpLookup { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::HttpLookup; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.namespace; + if value.is_empty() { + errors.push(ValidationError::required(Property::Namespace)); + } + let value = &self.format; + value.validate(errors); + let value = &self.max_entries; + if *value > 1048576 { + errors.push(ValidationError::max_value(Property::MaxEntries, 1048576)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxEntries, 1)); + } + let value = &self.max_entry_size; + if *value > 1048576 { + errors.push(ValidationError::max_value(Property::MaxEntrySize, 1048576)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxEntrySize, 1)); + } + let value = &self.max_size; + if *value > 1073741824 { + errors.push(ValidationError::max_value(Property::MaxSize, 1073741824)); + } + if *value < 10 { + errors.push(ValidationError::min_value(Property::MaxSize, 10)); + } + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global(Property::Namespace, &self.namespace); + } +} + +impl Pickle for HttpLookup { + fn pickle(&self, out: &mut Vec) { + self.namespace.pickle(out); + self.enable.pickle(out); + self.format.pickle(out); + self.is_gzipped.pickle(out); + self.max_entries.pickle(out); + self.max_entry_size.pickle(out); + self.max_size.pickle(out); + self.refresh.pickle(out); + self.retry.pickle(out); + self.timeout.pickle(out); + self.url.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.namespace = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.format = Pickle::unpickle(stream)?; + this.is_gzipped = Pickle::unpickle(stream)?; + this.max_entries = Pickle::unpickle(stream)?; + this.max_entry_size = Pickle::unpickle(stream)?; + this.max_size = Pickle::unpickle(stream)?; + this.refresh = Pickle::unpickle(stream)?; + this.retry = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for HttpLookup { + fn default() -> Self { + Self { + namespace: Default::default(), + enable: true, + format: Default::default(), + is_gzipped: false, + max_entries: 100000u64, + max_entry_size: 512u64, + max_size: 104857600, + refresh: Duration::from_millis(43200000), + retry: Duration::from_millis(3600000), + timeout: Duration::from_millis(30000), + url: Default::default(), + } + } +} + +impl IntoValue for HttpLookup { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::Namespace, self.namespace.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Format, self.format.into_value()); + map.insert_unchecked(Property::IsGzipped, self.is_gzipped.into_value()); + map.insert_unchecked(Property::MaxEntries, self.max_entries.into_value()); + map.insert_unchecked(Property::MaxEntrySize, self.max_entry_size.into_value()); + map.insert_unchecked(Property::MaxSize, self.max_size.into_value()); + map.insert_unchecked(Property::Refresh, self.refresh.into_value()); + map.insert_unchecked(Property::Retry, self.retry.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for HttpLookup { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Namespace) => self.namespace.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Trim]), + value, + ), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Format) => self.format.patch(pointer, value), + Some(Property::IsGzipped) => self.is_gzipped.patch(pointer, value), + Some(Property::MaxEntries) => self.max_entries.patch(pointer, value), + Some(Property::MaxEntrySize) => self.max_entry_size.patch(pointer, value), + Some(Property::MaxSize) => self.max_size.patch(pointer, value), + Some(Property::Refresh) => self.refresh.patch(pointer, value), + Some(Property::Retry) => self.retry.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl HttpLookupCsv { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.separator; + if value.is_empty() { + errors.push(ValidationError::required(Property::Separator)); + } + errors.len() == neb + } +} + +impl Pickle for HttpLookupCsv { + fn pickle(&self, out: &mut Vec) { + self.index_key.pickle(out); + self.index_value.pickle(out); + self.separator.pickle(out); + self.skip_first.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.index_key = Pickle::unpickle(stream)?; + this.index_value = Pickle::unpickle(stream)?; + this.separator = Pickle::unpickle(stream)?; + this.skip_first = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for HttpLookupCsv { + fn default() -> Self { + Self { + index_key: 0u64, + index_value: Default::default(), + separator: ",".to_string(), + skip_first: false, + } + } +} + +impl IntoValue for HttpLookupCsv { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::IndexKey, self.index_key.into_value()); + map.insert_unchecked(Property::IndexValue, self.index_value.into_value()); + map.insert_unchecked(Property::Separator, self.separator.into_value()); + map.insert_unchecked(Property::SkipFirst, self.skip_first.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for HttpLookupCsv { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IndexKey) => self.index_key.patch(pointer, value), + Some(Property::IndexValue) => self.index_value.patch(pointer, value), + Some(Property::Separator) => self + .separator + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::SkipFirst) => self.skip_first.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl HttpLookupFormat { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + HttpLookupFormat::Csv(inner) => inner.validate(errors), + HttpLookupFormat::List => true, + } + } +} + +impl Default for HttpLookupFormat { + fn default() -> Self { + HttpLookupFormat::Csv(Default::default()) + } +} + +impl Pickle for HttpLookupFormat { + fn pickle(&self, out: &mut Vec) { + match self { + HttpLookupFormat::Csv(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + HttpLookupFormat::List => { + 1u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(HttpLookupFormat::Csv), + 1 => Some(HttpLookupFormat::List), + _ => None, + } + } +} + +impl IntoValue for HttpLookupFormat { + fn into_value(self) -> JmapValue<'static> { + match self { + HttpLookupFormat::Csv(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Csv".into())); + obj + } + HttpLookupFormat::List => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("List".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for HttpLookupFormat { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + HttpLookupFormatType::Csv => *self = HttpLookupFormat::Csv(Default::default()), + HttpLookupFormatType::List => *self = HttpLookupFormat::List, + } + } + match self { + HttpLookupFormat::Csv(inner) => inner.patch(pointer, value), + HttpLookupFormat::List => pointer.assert_eof(), + } + } +} + +impl HttpLookupFormat { + pub fn object_type(&self) -> HttpLookupFormatType { + match self { + HttpLookupFormat::Csv(_) => HttpLookupFormatType::Csv, + HttpLookupFormat::List => HttpLookupFormatType::List, + } + } +} + +impl ObjectImpl for Imap { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Imap; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_auth_failures; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAuthFailures, 1)); + } + if let Some(value) = &self.max_concurrent { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxConcurrent, 1)); + } + } + if let Some(value) = &self.max_request_rate { + value.validate(errors); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Imap { + fn pickle(&self, out: &mut Vec) { + self.allow_plain_text_auth.pickle(out); + self.max_auth_failures.pickle(out); + self.max_concurrent.pickle(out); + self.max_request_rate.pickle(out); + self.max_request_size.pickle(out); + self.timeout_anonymous.pickle(out); + self.timeout_authenticated.pickle(out); + self.timeout_idle.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_plain_text_auth = Pickle::unpickle(stream)?; + this.max_auth_failures = Pickle::unpickle(stream)?; + this.max_concurrent = Pickle::unpickle(stream)?; + this.max_request_rate = Pickle::unpickle(stream)?; + this.max_request_size = Pickle::unpickle(stream)?; + this.timeout_anonymous = Pickle::unpickle(stream)?; + this.timeout_authenticated = Pickle::unpickle(stream)?; + this.timeout_idle = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Imap { + fn default() -> Self { + Self { + allow_plain_text_auth: false, + max_auth_failures: 3u64, + max_concurrent: Some(6u64), + max_request_rate: Some(Rate { + count: 2000u64, + period: Duration::from_millis(60000), + }), + max_request_size: 52428800, + timeout_anonymous: Duration::from_millis(60000), + timeout_authenticated: Duration::from_millis(1800000), + timeout_idle: Duration::from_millis(1800000), + } + } +} + +impl IntoValue for Imap { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked( + Property::AllowPlainTextAuth, + self.allow_plain_text_auth.into_value(), + ); + map.insert_unchecked( + Property::MaxAuthFailures, + self.max_auth_failures.into_value(), + ); + map.insert_unchecked(Property::MaxConcurrent, self.max_concurrent.into_value()); + map.insert_unchecked(Property::MaxRequestRate, self.max_request_rate.into_value()); + map.insert_unchecked(Property::MaxRequestSize, self.max_request_size.into_value()); + map.insert_unchecked( + Property::TimeoutAnonymous, + self.timeout_anonymous.into_value(), + ); + map.insert_unchecked( + Property::TimeoutAuthenticated, + self.timeout_authenticated.into_value(), + ); + map.insert_unchecked(Property::TimeoutIdle, self.timeout_idle.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Imap { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowPlainTextAuth) => self.allow_plain_text_auth.patch(pointer, value), + Some(Property::MaxAuthFailures) => self.max_auth_failures.patch(pointer, value), + Some(Property::MaxConcurrent) => self.max_concurrent.patch(pointer, value), + Some(Property::MaxRequestRate) => self.max_request_rate.patch(pointer, value), + Some(Property::MaxRequestSize) => self.max_request_size.patch(pointer, value), + Some(Property::TimeoutAnonymous) => self.timeout_anonymous.patch(pointer, value), + Some(Property::TimeoutAuthenticated) => { + self.timeout_authenticated.patch(pointer, value) + } + Some(Property::TimeoutIdle) => self.timeout_idle.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for InMemoryStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::InMemoryStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + InMemoryStore::Default => true, + InMemoryStore::Sharded(inner) => inner.validate(errors), + InMemoryStore::Redis(inner) => inner.validate(errors), + InMemoryStore::RedisCluster(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for InMemoryStore { + fn default() -> Self { + InMemoryStore::Default + } +} + +impl Pickle for InMemoryStore { + fn pickle(&self, out: &mut Vec) { + match self { + InMemoryStore::Default => { + 0u16.pickle(out); + } + InMemoryStore::Sharded(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + InMemoryStore::Redis(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + InMemoryStore::RedisCluster(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(InMemoryStore::Default), + 1 => Pickle::unpickle(stream).map(InMemoryStore::Sharded), + 2 => Pickle::unpickle(stream).map(InMemoryStore::Redis), + 3 => Pickle::unpickle(stream).map(InMemoryStore::RedisCluster), + _ => None, + } + } +} + +impl IntoValue for InMemoryStore { + fn into_value(self) -> JmapValue<'static> { + match self { + InMemoryStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + InMemoryStore::Sharded(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sharded".into())); + obj + } + InMemoryStore::Redis(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Redis".into())); + obj + } + InMemoryStore::RedisCluster(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for InMemoryStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + InMemoryStoreType::Default => *self = InMemoryStore::Default, + InMemoryStoreType::Sharded => *self = InMemoryStore::Sharded(Default::default()), + InMemoryStoreType::Redis => *self = InMemoryStore::Redis(Default::default()), + InMemoryStoreType::RedisCluster => { + *self = InMemoryStore::RedisCluster(Default::default()) + } + } + } + match self { + InMemoryStore::Default => pointer.assert_eof(), + InMemoryStore::Sharded(inner) => inner.patch(pointer, value), + InMemoryStore::Redis(inner) => inner.patch(pointer, value), + InMemoryStore::RedisCluster(inner) => inner.patch(pointer, value), + } + } +} + +impl InMemoryStore { + pub fn object_type(&self) -> InMemoryStoreType { + match self { + InMemoryStore::Default => InMemoryStoreType::Default, + InMemoryStore::Sharded(_) => InMemoryStoreType::Sharded, + InMemoryStore::Redis(_) => InMemoryStoreType::Redis, + InMemoryStore::RedisCluster(_) => InMemoryStoreType::RedisCluster, + } + } +} + +impl InMemoryStoreBase { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + InMemoryStoreBase::Redis(inner) => inner.validate(errors), + InMemoryStoreBase::RedisCluster(inner) => inner.validate(errors), + } + } +} + +impl Default for InMemoryStoreBase { + fn default() -> Self { + InMemoryStoreBase::Redis(Default::default()) + } +} + +impl Pickle for InMemoryStoreBase { + fn pickle(&self, out: &mut Vec) { + match self { + InMemoryStoreBase::Redis(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + InMemoryStoreBase::RedisCluster(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(InMemoryStoreBase::Redis), + 1 => Pickle::unpickle(stream).map(InMemoryStoreBase::RedisCluster), + _ => None, + } + } +} + +impl IntoValue for InMemoryStoreBase { + fn into_value(self) -> JmapValue<'static> { + match self { + InMemoryStoreBase::Redis(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Redis".into())); + obj + } + InMemoryStoreBase::RedisCluster(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for InMemoryStoreBase { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + InMemoryStoreBaseType::Redis => { + *self = InMemoryStoreBase::Redis(Default::default()) + } + InMemoryStoreBaseType::RedisCluster => { + *self = InMemoryStoreBase::RedisCluster(Default::default()) + } + } + } + match self { + InMemoryStoreBase::Redis(inner) => inner.patch(pointer, value), + InMemoryStoreBase::RedisCluster(inner) => inner.patch(pointer, value), + } + } +} + +impl InMemoryStoreBase { + pub fn object_type(&self) -> InMemoryStoreBaseType { + match self { + InMemoryStoreBase::Redis(_) => InMemoryStoreBaseType::Redis, + InMemoryStoreBase::RedisCluster(_) => InMemoryStoreBaseType::RedisCluster, + } + } +} + +impl ObjectImpl for Jmap { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Jmap; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.parse_limit_event; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ParseLimitEvent, 1)); + } + let value = &self.parse_limit_contact; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ParseLimitContact, 1)); + } + let value = &self.parse_limit_email; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ParseLimitEmail, 1)); + } + let value = &self.changes_max_results; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ChangesMaxResults, 1)); + } + let value = &self.get_max_results; + if *value < 1 { + errors.push(ValidationError::min_value(Property::GetMaxResults, 1)); + } + let value = &self.query_max_results; + if *value < 1 { + errors.push(ValidationError::min_value(Property::QueryMaxResults, 1)); + } + let value = &self.max_method_calls; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMethodCalls, 1)); + } + if let Some(value) = &self.max_concurrent_requests { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::MaxConcurrentRequests, + 1, + )); + } + } + let value = &self.max_request_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRequestSize, 1)); + } + let value = &self.set_max_objects; + if *value < 1 { + errors.push(ValidationError::min_value(Property::SetMaxObjects, 1)); + } + let value = &self.snippet_max_results; + if *value < 1 { + errors.push(ValidationError::min_value(Property::SnippetMaxResults, 1)); + } + if let Some(value) = &self.max_concurrent_uploads { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::MaxConcurrentUploads, + 1, + )); + } + } + let value = &self.max_upload_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxUploadSize, 1)); + } + let value = &self.max_upload_count; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxUploadCount, 1)); + } + let value = &self.upload_quota; + if *value < 1 { + errors.push(ValidationError::min_value(Property::UploadQuota, 1)); + } + let value = &self.push_max_attempts; + if *value < 1 { + errors.push(ValidationError::min_value(Property::PushMaxAttempts, 1)); + } + let value = &self.push_shards_total; + if *value < 1 { + errors.push(ValidationError::min_value(Property::PushShardsTotal, 1)); + } + if let Some(value) = &self.max_subscriptions { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxSubscriptions, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Jmap { + fn pickle(&self, out: &mut Vec) { + self.parse_limit_event.pickle(out); + self.parse_limit_contact.pickle(out); + self.parse_limit_email.pickle(out); + self.changes_max_results.pickle(out); + self.get_max_results.pickle(out); + self.query_max_results.pickle(out); + self.max_method_calls.pickle(out); + self.max_concurrent_requests.pickle(out); + self.max_request_size.pickle(out); + self.set_max_objects.pickle(out); + self.snippet_max_results.pickle(out); + self.max_concurrent_uploads.pickle(out); + self.max_upload_size.pickle(out); + self.max_upload_count.pickle(out); + self.upload_quota.pickle(out); + self.upload_ttl.pickle(out); + self.event_source_throttle.pickle(out); + self.push_attempt_wait.pickle(out); + self.push_max_attempts.pickle(out); + self.push_retry_wait.pickle(out); + self.push_throttle.pickle(out); + self.push_request_timeout.pickle(out); + self.push_verify_timeout.pickle(out); + self.push_shards_total.pickle(out); + self.websocket_heartbeat.pickle(out); + self.websocket_throttle.pickle(out); + self.websocket_timeout.pickle(out); + self.max_subscriptions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.parse_limit_event = Pickle::unpickle(stream)?; + this.parse_limit_contact = Pickle::unpickle(stream)?; + this.parse_limit_email = Pickle::unpickle(stream)?; + this.changes_max_results = Pickle::unpickle(stream)?; + this.get_max_results = Pickle::unpickle(stream)?; + this.query_max_results = Pickle::unpickle(stream)?; + this.max_method_calls = Pickle::unpickle(stream)?; + this.max_concurrent_requests = Pickle::unpickle(stream)?; + this.max_request_size = Pickle::unpickle(stream)?; + this.set_max_objects = Pickle::unpickle(stream)?; + this.snippet_max_results = Pickle::unpickle(stream)?; + this.max_concurrent_uploads = Pickle::unpickle(stream)?; + this.max_upload_size = Pickle::unpickle(stream)?; + this.max_upload_count = Pickle::unpickle(stream)?; + this.upload_quota = Pickle::unpickle(stream)?; + this.upload_ttl = Pickle::unpickle(stream)?; + this.event_source_throttle = Pickle::unpickle(stream)?; + this.push_attempt_wait = Pickle::unpickle(stream)?; + this.push_max_attempts = Pickle::unpickle(stream)?; + this.push_retry_wait = Pickle::unpickle(stream)?; + this.push_throttle = Pickle::unpickle(stream)?; + this.push_request_timeout = Pickle::unpickle(stream)?; + this.push_verify_timeout = Pickle::unpickle(stream)?; + this.push_shards_total = Pickle::unpickle(stream)?; + this.websocket_heartbeat = Pickle::unpickle(stream)?; + this.websocket_throttle = Pickle::unpickle(stream)?; + this.websocket_timeout = Pickle::unpickle(stream)?; + this.max_subscriptions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Jmap { + fn default() -> Self { + Self { + parse_limit_event: 10u64, + parse_limit_contact: 10u64, + parse_limit_email: 10u64, + changes_max_results: 5000u64, + get_max_results: 500u64, + query_max_results: 5000u64, + max_method_calls: 16u64, + max_concurrent_requests: Some(4u64), + max_request_size: 10000000u64, + set_max_objects: 500u64, + snippet_max_results: 100u64, + max_concurrent_uploads: Some(4u64), + max_upload_size: 50000000u64, + max_upload_count: 1000u64, + upload_quota: 50000000u64, + upload_ttl: Duration::from_millis(3600000), + event_source_throttle: Duration::from_millis(1000), + push_attempt_wait: Duration::from_millis(60000), + push_max_attempts: 3u64, + push_retry_wait: Duration::from_millis(1000), + push_throttle: Duration::from_millis(1000), + push_request_timeout: Duration::from_millis(10000), + push_verify_timeout: Duration::from_millis(60000), + push_shards_total: 1u64, + websocket_heartbeat: Duration::from_millis(60000), + websocket_throttle: Duration::from_millis(1000), + websocket_timeout: Duration::from_millis(600000), + max_subscriptions: Some(15u64), + } + } +} + +impl IntoValue for Jmap { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(30); + map.insert_unchecked( + Property::ParseLimitEvent, + self.parse_limit_event.into_value(), + ); + map.insert_unchecked( + Property::ParseLimitContact, + self.parse_limit_contact.into_value(), + ); + map.insert_unchecked( + Property::ParseLimitEmail, + self.parse_limit_email.into_value(), + ); + map.insert_unchecked( + Property::ChangesMaxResults, + self.changes_max_results.into_value(), + ); + map.insert_unchecked(Property::GetMaxResults, self.get_max_results.into_value()); + map.insert_unchecked( + Property::QueryMaxResults, + self.query_max_results.into_value(), + ); + map.insert_unchecked(Property::MaxMethodCalls, self.max_method_calls.into_value()); + map.insert_unchecked( + Property::MaxConcurrentRequests, + self.max_concurrent_requests.into_value(), + ); + map.insert_unchecked(Property::MaxRequestSize, self.max_request_size.into_value()); + map.insert_unchecked(Property::SetMaxObjects, self.set_max_objects.into_value()); + map.insert_unchecked( + Property::SnippetMaxResults, + self.snippet_max_results.into_value(), + ); + map.insert_unchecked( + Property::MaxConcurrentUploads, + self.max_concurrent_uploads.into_value(), + ); + map.insert_unchecked(Property::MaxUploadSize, self.max_upload_size.into_value()); + map.insert_unchecked(Property::MaxUploadCount, self.max_upload_count.into_value()); + map.insert_unchecked(Property::UploadQuota, self.upload_quota.into_value()); + map.insert_unchecked(Property::UploadTtl, self.upload_ttl.into_value()); + map.insert_unchecked( + Property::EventSourceThrottle, + self.event_source_throttle.into_value(), + ); + map.insert_unchecked( + Property::PushAttemptWait, + self.push_attempt_wait.into_value(), + ); + map.insert_unchecked( + Property::PushMaxAttempts, + self.push_max_attempts.into_value(), + ); + map.insert_unchecked(Property::PushRetryWait, self.push_retry_wait.into_value()); + map.insert_unchecked(Property::PushThrottle, self.push_throttle.into_value()); + map.insert_unchecked( + Property::PushRequestTimeout, + self.push_request_timeout.into_value(), + ); + map.insert_unchecked( + Property::PushVerifyTimeout, + self.push_verify_timeout.into_value(), + ); + map.insert_unchecked( + Property::PushShardsTotal, + self.push_shards_total.into_value(), + ); + map.insert_unchecked( + Property::WebsocketHeartbeat, + self.websocket_heartbeat.into_value(), + ); + map.insert_unchecked( + Property::WebsocketThrottle, + self.websocket_throttle.into_value(), + ); + map.insert_unchecked( + Property::WebsocketTimeout, + self.websocket_timeout.into_value(), + ); + map.insert_unchecked( + Property::MaxSubscriptions, + self.max_subscriptions.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Jmap { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ParseLimitEvent) => self.parse_limit_event.patch(pointer, value), + Some(Property::ParseLimitContact) => self.parse_limit_contact.patch(pointer, value), + Some(Property::ParseLimitEmail) => self.parse_limit_email.patch(pointer, value), + Some(Property::ChangesMaxResults) => self.changes_max_results.patch(pointer, value), + Some(Property::GetMaxResults) => self.get_max_results.patch(pointer, value), + Some(Property::QueryMaxResults) => self.query_max_results.patch(pointer, value), + Some(Property::MaxMethodCalls) => self.max_method_calls.patch(pointer, value), + Some(Property::MaxConcurrentRequests) => { + self.max_concurrent_requests.patch(pointer, value) + } + Some(Property::MaxRequestSize) => self.max_request_size.patch(pointer, value), + Some(Property::SetMaxObjects) => self.set_max_objects.patch(pointer, value), + Some(Property::SnippetMaxResults) => self.snippet_max_results.patch(pointer, value), + Some(Property::MaxConcurrentUploads) => { + self.max_concurrent_uploads.patch(pointer, value) + } + Some(Property::MaxUploadSize) => self.max_upload_size.patch(pointer, value), + Some(Property::MaxUploadCount) => self.max_upload_count.patch(pointer, value), + Some(Property::UploadQuota) => self.upload_quota.patch(pointer, value), + Some(Property::UploadTtl) => self.upload_ttl.patch(pointer, value), + Some(Property::EventSourceThrottle) => self.event_source_throttle.patch(pointer, value), + Some(Property::PushAttemptWait) => self.push_attempt_wait.patch(pointer, value), + Some(Property::PushMaxAttempts) => self.push_max_attempts.patch(pointer, value), + Some(Property::PushRetryWait) => self.push_retry_wait.patch(pointer, value), + Some(Property::PushThrottle) => self.push_throttle.patch(pointer, value), + Some(Property::PushRequestTimeout) => self.push_request_timeout.patch(pointer, value), + Some(Property::PushVerifyTimeout) => self.push_verify_timeout.patch(pointer, value), + Some(Property::PushShardsTotal) => self.push_shards_total.patch(pointer, value), + Some(Property::WebsocketHeartbeat) => self.websocket_heartbeat.patch(pointer, value), + Some(Property::WebsocketThrottle) => self.websocket_throttle.patch(pointer, value), + Some(Property::WebsocketTimeout) => self.websocket_timeout.patch(pointer, value), + Some(Property::MaxSubscriptions) => self.max_subscriptions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl KafkaCoordinator { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.brokers; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Brokers)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Brokers, 1)); + } + let value = &self.group_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::GroupId)); + } + errors.len() == neb + } +} + +impl Pickle for KafkaCoordinator { + fn pickle(&self, out: &mut Vec) { + self.brokers.pickle(out); + self.group_id.pickle(out); + self.timeout_message.pickle(out); + self.timeout_session.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.brokers = Pickle::unpickle(stream)?; + this.group_id = Pickle::unpickle(stream)?; + this.timeout_message = Pickle::unpickle(stream)?; + this.timeout_session = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for KafkaCoordinator { + fn default() -> Self { + Self { + brokers: Default::default(), + group_id: Default::default(), + timeout_message: Duration::from_millis(5000), + timeout_session: Duration::from_millis(5000), + } + } +} + +impl IntoValue for KafkaCoordinator { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Brokers, self.brokers.into_value()); + map.insert_unchecked(Property::GroupId, self.group_id.into_value()); + map.insert_unchecked(Property::TimeoutMessage, self.timeout_message.into_value()); + map.insert_unchecked(Property::TimeoutSession, self.timeout_session.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for KafkaCoordinator { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Brokers) => self.brokers.patch(pointer, value), + Some(Property::GroupId) => self + .group_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::TimeoutMessage) => self.timeout_message.patch(pointer, value), + Some(Property::TimeoutSession) => self.timeout_session.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl LdapDirectory { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.base_dn; + if value.is_empty() { + errors.push(ValidationError::required(Property::BaseDn)); + } + if let Some(value) = &self.bind_dn { + if value.is_empty() { + errors.push(ValidationError::required(Property::BindDn)); + } + } + let value = &self.bind_secret; + value.validate(errors); + let value = &self.filter_login; + if value.is_empty() { + errors.push(ValidationError::required(Property::FilterLogin)); + } + let value = &self.filter_mailbox; + if value.is_empty() { + errors.push(ValidationError::required(Property::FilterMailbox)); + } + if let Some(value) = &self.filter_member_of { + if value.is_empty() { + errors.push(ValidationError::required(Property::FilterMemberOf)); + } + } + let value = &self.attr_class; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrClass)); + } + } + let value = &self.attr_description; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrDescription)); + } + } + let value = &self.attr_email; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrEmail)); + } + } + let value = &self.attr_email_alias; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrEmailAlias)); + } + } + let value = &self.attr_member_of; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrMemberOf)); + } + } + let value = &self.attr_secret; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrSecret)); + } + } + let value = &self.attr_secret_changed; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AttrSecretChanged)); + } + } + let value = &self.group_class; + if value.is_empty() { + errors.push(ValidationError::required(Property::GroupClass)); + } + let value = &self.pool_max_connections; + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for LdapDirectory { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.url.pickle(out); + self.timeout.pickle(out); + self.allow_invalid_certs.pickle(out); + self.use_tls.pickle(out); + self.base_dn.pickle(out); + self.bind_dn.pickle(out); + self.bind_secret.pickle(out); + self.bind_authentication.pickle(out); + self.filter_login.pickle(out); + self.filter_mailbox.pickle(out); + self.filter_member_of.pickle(out); + self.attr_class.pickle(out); + self.attr_description.pickle(out); + self.attr_email.pickle(out); + self.attr_email_alias.pickle(out); + self.attr_member_of.pickle(out); + self.attr_secret.pickle(out); + self.attr_secret_changed.pickle(out); + self.group_class.pickle(out); + self.pool_max_connections.pickle(out); + self.pool_timeout_create.pickle(out); + self.pool_timeout_recycle.pickle(out); + self.pool_timeout_wait.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.base_dn = Pickle::unpickle(stream)?; + this.bind_dn = Pickle::unpickle(stream)?; + this.bind_secret = Pickle::unpickle(stream)?; + this.bind_authentication = Pickle::unpickle(stream)?; + this.filter_login = Pickle::unpickle(stream)?; + this.filter_mailbox = Pickle::unpickle(stream)?; + this.filter_member_of = Pickle::unpickle(stream)?; + this.attr_class = Pickle::unpickle(stream)?; + this.attr_description = Pickle::unpickle(stream)?; + this.attr_email = Pickle::unpickle(stream)?; + this.attr_email_alias = Pickle::unpickle(stream)?; + this.attr_member_of = Pickle::unpickle(stream)?; + this.attr_secret = Pickle::unpickle(stream)?; + this.attr_secret_changed = Pickle::unpickle(stream)?; + this.group_class = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + this.pool_timeout_create = Pickle::unpickle(stream)?; + this.pool_timeout_recycle = Pickle::unpickle(stream)?; + this.pool_timeout_wait = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for LdapDirectory { + fn default() -> Self { + Self { + description: Default::default(), + url: "ldap://localhost:389".to_string(), + timeout: Duration::from_millis(30000), + allow_invalid_certs: false, + use_tls: false, + base_dn: Default::default(), + bind_dn: Default::default(), + bind_secret: Default::default(), + bind_authentication: true, + filter_login: "(&(objectClass=inetOrgPerson)(mail=?))".to_string(), + filter_mailbox: "(|(&(objectClass=inetOrgPerson)(|(mail=?)(mailAlias=?)))(&(objectClass=groupOfNames)(|(mail=?)(mailAlias=?))))".to_string(), + filter_member_of: Some("(&(objectClass=groupOfNames)(member=?))".to_string()), + attr_class: Map::new(vec!["objectClass".to_string()]), + attr_description: Map::new(vec!["description".to_string()]), + attr_email: Map::new(vec!["mail".to_string()]), + attr_email_alias: Map::new(vec!["mailAlias".to_string()]), + attr_member_of: Map::new(vec!["memberOf".to_string()]), + attr_secret: Map::new(vec!["userPassword".to_string()]), + attr_secret_changed: Map::new(vec!["pwdChangeTime".to_string()]), + group_class: "groupOfNames".to_string(), + pool_max_connections: 10u64, + pool_timeout_create: Duration::from_millis(30000), + pool_timeout_recycle: Duration::from_millis(30000), + pool_timeout_wait: Duration::from_millis(30000), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for LdapDirectory { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(27); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked(Property::BaseDn, self.base_dn.into_value()); + map.insert_unchecked(Property::BindDn, self.bind_dn.into_value()); + map.insert_unchecked(Property::BindSecret, self.bind_secret.into_value()); + map.insert_unchecked( + Property::BindAuthentication, + self.bind_authentication.into_value(), + ); + map.insert_unchecked(Property::FilterLogin, self.filter_login.into_value()); + map.insert_unchecked(Property::FilterMailbox, self.filter_mailbox.into_value()); + map.insert_unchecked(Property::FilterMemberOf, self.filter_member_of.into_value()); + map.insert_unchecked(Property::AttrClass, self.attr_class.into_value()); + map.insert_unchecked( + Property::AttrDescription, + self.attr_description.into_value(), + ); + map.insert_unchecked(Property::AttrEmail, self.attr_email.into_value()); + map.insert_unchecked(Property::AttrEmailAlias, self.attr_email_alias.into_value()); + map.insert_unchecked(Property::AttrMemberOf, self.attr_member_of.into_value()); + map.insert_unchecked(Property::AttrSecret, self.attr_secret.into_value()); + map.insert_unchecked( + Property::AttrSecretChanged, + self.attr_secret_changed.into_value(), + ); + map.insert_unchecked(Property::GroupClass, self.group_class.into_value()); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutCreate, + self.pool_timeout_create.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutRecycle, + self.pool_timeout_recycle.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutWait, + self.pool_timeout_wait.into_value(), + ); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for LdapDirectory { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::BaseDn) => self + .base_dn + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::BindDn) => self + .bind_dn + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::BindSecret) => self.bind_secret.patch(pointer, value), + Some(Property::BindAuthentication) => self.bind_authentication.patch(pointer, value), + Some(Property::FilterLogin) => self + .filter_login + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::FilterMailbox) => self + .filter_mailbox + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::FilterMemberOf) => self + .filter_member_of + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrClass) => self + .attr_class + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrDescription) => self + .attr_description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrEmail) => self + .attr_email + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrEmailAlias) => self + .attr_email_alias + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrMemberOf) => self + .attr_member_of + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrSecret) => self + .attr_secret + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AttrSecretChanged) => self + .attr_secret_changed + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::GroupClass) => self + .group_class + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value), + Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value), + Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Log { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Log; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.timestamp; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Timestamp, value)); + } + let value = &self.details; + if value.is_empty() { + errors.push(ValidationError::required(Property::Details)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Log { + fn pickle(&self, out: &mut Vec) { + self.timestamp.pickle(out); + self.level.pickle(out); + self.event.pickle(out); + self.details.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.timestamp = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.event = Pickle::unpickle(stream)?; + this.details = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Log { + fn default() -> Self { + Self { + timestamp: Default::default(), + level: Default::default(), + event: Default::default(), + details: Default::default(), + } + } +} + +impl IntoValue for Log { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Timestamp, self.timestamp.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Event, self.event.into_value()); + map.insert_unchecked(Property::Details, self.details.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Log { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Timestamp) => self.timestamp.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Event) => self.event.patch(pointer, value), + Some(Property::Details) => self.details.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl LookupStore { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + LookupStore::PostgreSql(inner) => inner.validate(errors), + LookupStore::MySql(inner) => inner.validate(errors), + LookupStore::Sqlite(inner) => inner.validate(errors), + LookupStore::Sharded(inner) => inner.validate(errors), + LookupStore::Redis(inner) => inner.validate(errors), + LookupStore::RedisCluster(inner) => inner.validate(errors), + } + } +} + +impl Default for LookupStore { + fn default() -> Self { + LookupStore::PostgreSql(Default::default()) + } +} + +impl Pickle for LookupStore { + fn pickle(&self, out: &mut Vec) { + match self { + LookupStore::PostgreSql(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + LookupStore::MySql(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + LookupStore::Sqlite(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + LookupStore::Sharded(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + LookupStore::Redis(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + LookupStore::RedisCluster(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(LookupStore::PostgreSql), + 1 => Pickle::unpickle(stream).map(LookupStore::MySql), + 2 => Pickle::unpickle(stream).map(LookupStore::Sqlite), + 3 => Pickle::unpickle(stream).map(LookupStore::Sharded), + 4 => Pickle::unpickle(stream).map(LookupStore::Redis), + 5 => Pickle::unpickle(stream).map(LookupStore::RedisCluster), + _ => None, + } + } +} + +impl IntoValue for LookupStore { + fn into_value(self) -> JmapValue<'static> { + match self { + LookupStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + LookupStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + LookupStore::Sqlite(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into())); + obj + } + LookupStore::Sharded(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sharded".into())); + obj + } + LookupStore::Redis(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Redis".into())); + obj + } + LookupStore::RedisCluster(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RedisCluster".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for LookupStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + LookupStoreType::PostgreSql => *self = LookupStore::PostgreSql(Default::default()), + LookupStoreType::MySql => *self = LookupStore::MySql(Default::default()), + LookupStoreType::Sqlite => *self = LookupStore::Sqlite(Default::default()), + LookupStoreType::Sharded => *self = LookupStore::Sharded(Default::default()), + LookupStoreType::Redis => *self = LookupStore::Redis(Default::default()), + LookupStoreType::RedisCluster => { + *self = LookupStore::RedisCluster(Default::default()) + } + } + } + match self { + LookupStore::PostgreSql(inner) => inner.patch(pointer, value), + LookupStore::MySql(inner) => inner.patch(pointer, value), + LookupStore::Sqlite(inner) => inner.patch(pointer, value), + LookupStore::Sharded(inner) => inner.patch(pointer, value), + LookupStore::Redis(inner) => inner.patch(pointer, value), + LookupStore::RedisCluster(inner) => inner.patch(pointer, value), + } + } +} + +impl LookupStore { + pub fn object_type(&self) -> LookupStoreType { + match self { + LookupStore::PostgreSql(_) => LookupStoreType::PostgreSql, + LookupStore::MySql(_) => LookupStoreType::MySql, + LookupStore::Sqlite(_) => LookupStoreType::Sqlite, + LookupStore::Sharded(_) => LookupStoreType::Sharded, + LookupStore::Redis(_) => LookupStoreType::Redis, + LookupStore::RedisCluster(_) => LookupStoreType::RedisCluster, + } + } +} + +impl MailExchanger { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::Hostname)); + } + } + let value = &self.priority; + if *value < 1 { + errors.push(ValidationError::min_value(Property::Priority, 1)); + } + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Priority, 65535)); + } + errors.len() == neb + } +} + +impl Pickle for MailExchanger { + fn pickle(&self, out: &mut Vec) { + self.hostname.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.hostname = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MailExchanger { + fn default() -> Self { + Self { + hostname: Default::default(), + priority: 10u64, + } + } +} + +impl IntoValue for MailExchanger { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Hostname, self.hostname.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MailExchanger { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Hostname) => self + .hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MailingList { + const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MailingList; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.aliases; + for value in value.values() { + value.validate(errors); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.recipients; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Recipients)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Email, &self.name, &self.domain_id); + i.text(Property::Text, &self.name); + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + for item in self.aliases.values() { + item.index(i); + } + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + for value in self.recipients.iter() { + i.text(Property::Text, value); + } + } +} + +impl Pickle for MailingList { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.domain_id.pickle(out); + self.description.pickle(out); + self.aliases.pickle(out); + self.member_tenant_id.pickle(out); + self.recipients.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.aliases = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.recipients = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MailingList { + fn default() -> Self { + Self { + name: Default::default(), + domain_id: Default::default(), + description: Default::default(), + aliases: Default::default(), + member_tenant_id: Default::default(), + recipients: Default::default(), + } + } +} + +impl IntoValue for MailingList { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Aliases, self.aliases.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Recipients, self.recipients.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MailingList { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch( + pointer.with_validators(&[StringValidator::EmailLocalPart]), + value, + ), + Some(Property::DomainId) => self.domain_id.patch(pointer, value), + Some(Property::EmailAddress) => pointer.assert_server_set(), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Aliases) => self.aliases.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Recipients) => self + .recipients + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MaskedEmail { + const FLAGS: u64 = OBJ_FILTER_ACCOUNT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MaskedEmail; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.email; + if value.is_empty() { + errors.push(ValidationError::required(Property::Email)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + if let Some(value) = &self.for_domain { + if value.is_empty() { + errors.push(ValidationError::required(Property::ForDomain)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.created_by { + if value.is_empty() { + errors.push(ValidationError::required(Property::CreatedBy)); + } + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + if let Some(value) = &self.url { + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for MaskedEmail { + fn pickle(&self, out: &mut Vec) { + self.enabled.pickle(out); + self.account_id.pickle(out); + self.email.pickle(out); + self.description.pickle(out); + self.for_domain.pickle(out); + self.created_at.pickle(out); + self.created_by.pickle(out); + self.expires_at.pickle(out); + self.url.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enabled = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.email = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.for_domain = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.created_by = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MaskedEmail { + fn default() -> Self { + Self { + enabled: true, + account_id: Default::default(), + email: Default::default(), + description: Default::default(), + for_domain: Default::default(), + created_at: Default::default(), + created_by: Default::default(), + expires_at: Default::default(), + url: Default::default(), + } + } +} + +impl IntoValue for MaskedEmail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Enabled, self.enabled.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::Email, self.email.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::ForDomain, self.for_domain.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::CreatedBy, self.created_by.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MaskedEmail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enabled) => self.enabled.patch(pointer, value), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::Email) => pointer.assert_server_set(), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::ForDomain) => self.for_domain.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::CreatedBy) => self.created_by.patch(pointer, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer.assert_read_only()?, value), + Some(Property::Url) => self.url.patch(pointer, value), + Some(property @ Property::EmailPrefix) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(property @ Property::EmailDomain) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MeilisearchStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.max_retries; + if *value > 1024 { + errors.push(ValidationError::max_value(Property::MaxRetries, 1024)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRetries, 1)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for MeilisearchStore { + fn pickle(&self, out: &mut Vec) { + self.url.pickle(out); + self.poll_interval.pickle(out); + self.max_retries.pickle(out); + self.fail_on_timeout.pickle(out); + self.timeout.pickle(out); + self.allow_invalid_certs.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.url = Pickle::unpickle(stream)?; + this.poll_interval = Pickle::unpickle(stream)?; + this.max_retries = Pickle::unpickle(stream)?; + this.fail_on_timeout = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MeilisearchStore { + fn default() -> Self { + Self { + url: Default::default(), + poll_interval: Duration::from_millis(500), + max_retries: 120u64, + fail_on_timeout: true, + timeout: Duration::from_millis(30000), + allow_invalid_certs: false, + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for MeilisearchStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::PollInterval, self.poll_interval.into_value()); + map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value()); + map.insert_unchecked(Property::FailOnTimeout, self.fail_on_timeout.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MeilisearchStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PollInterval) => self.poll_interval.patch(pointer, value), + Some(Property::MaxRetries) => self.max_retries.patch(pointer, value), + Some(Property::FailOnTimeout) => self.fail_on_timeout.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MemoryLookupKey { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MemoryLookupKey; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.namespace; + if value.is_empty() { + errors.push(ValidationError::required(Property::Namespace)); + } + let value = &self.key; + if value.is_empty() { + errors.push(ValidationError::required(Property::Key)); + } + if value.len() > 255 { + errors.push(ValidationError::max_length(Property::Key, 255)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Namespace, &self.namespace, &self.key); + i.search(Property::Namespace, &self.namespace); + } +} + +impl Pickle for MemoryLookupKey { + fn pickle(&self, out: &mut Vec) { + self.namespace.pickle(out); + self.key.pickle(out); + self.is_glob_pattern.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.namespace = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.is_glob_pattern = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MemoryLookupKey { + fn default() -> Self { + Self { + namespace: Default::default(), + key: Default::default(), + is_glob_pattern: false, + } + } +} + +impl IntoValue for MemoryLookupKey { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Namespace, self.namespace.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::IsGlobPattern, self.is_glob_pattern.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MemoryLookupKey { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Namespace) => self.namespace.patch(pointer, value), + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::IsGlobPattern) => self.is_glob_pattern.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MemoryLookupKeyValue { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MemoryLookupKeyValue; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.namespace; + if value.is_empty() { + errors.push(ValidationError::required(Property::Namespace)); + } + let value = &self.key; + if value.is_empty() { + errors.push(ValidationError::required(Property::Key)); + } + if value.len() > 255 { + errors.push(ValidationError::max_length(Property::Key, 255)); + } + let value = &self.value; + if value.is_empty() { + errors.push(ValidationError::required(Property::Value)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Namespace, &self.namespace, &self.key); + i.search(Property::Namespace, &self.namespace); + } +} + +impl Pickle for MemoryLookupKeyValue { + fn pickle(&self, out: &mut Vec) { + self.namespace.pickle(out); + self.key.pickle(out); + self.value.pickle(out); + self.is_glob_pattern.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.namespace = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.value = Pickle::unpickle(stream)?; + this.is_glob_pattern = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MemoryLookupKeyValue { + fn default() -> Self { + Self { + namespace: Default::default(), + key: Default::default(), + value: Default::default(), + is_glob_pattern: false, + } + } +} + +impl IntoValue for MemoryLookupKeyValue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Namespace, self.namespace.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Value, self.value.into_value()); + map.insert_unchecked(Property::IsGlobPattern, self.is_glob_pattern.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MemoryLookupKeyValue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Namespace) => self.namespace.patch(pointer, value), + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::IsGlobPattern) => self.is_glob_pattern.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Metric { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Metric; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Metric::Counter(inner) => inner.validate(errors), + Metric::Gauge(inner) => inner.validate(errors), + Metric::Histogram(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for Metric { + fn default() -> Self { + Metric::Counter(Default::default()) + } +} + +impl Pickle for Metric { + fn pickle(&self, out: &mut Vec) { + match self { + Metric::Counter(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Metric::Gauge(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Metric::Histogram(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Metric::Counter), + 1 => Pickle::unpickle(stream).map(Metric::Gauge), + 2 => Pickle::unpickle(stream).map(Metric::Histogram), + _ => None, + } + } +} + +impl IntoValue for Metric { + fn into_value(self) -> JmapValue<'static> { + match self { + Metric::Counter(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Counter".into())); + obj + } + Metric::Gauge(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Gauge".into())); + obj + } + Metric::Histogram(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Histogram".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Metric { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MetricType::Counter => *self = Metric::Counter(Default::default()), + MetricType::Gauge => *self = Metric::Gauge(Default::default()), + MetricType::Histogram => *self = Metric::Histogram(Default::default()), + } + } + match self { + Metric::Counter(inner) => inner.patch(pointer, value), + Metric::Gauge(inner) => inner.patch(pointer, value), + Metric::Histogram(inner) => inner.patch(pointer, value), + } + } +} + +impl Metric { + pub fn object_type(&self) -> MetricType { + match self { + Metric::Counter(_) => MetricType::Counter, + Metric::Gauge(_) => MetricType::Gauge, + Metric::Histogram(_) => MetricType::Histogram, + } + } +} + +impl MetricCount { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for MetricCount { + fn pickle(&self, out: &mut Vec) { + self.count.pickle(out); + self.metric.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.count = Pickle::unpickle(stream)?; + this.metric = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MetricCount { + fn default() -> Self { + Self { + count: 0u64, + metric: Default::default(), + } + } +} + +impl IntoValue for MetricCount { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Count, self.count.into_value()); + map.insert_unchecked(Property::Metric, self.metric.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MetricCount { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Count) => self.count.patch(pointer, value), + Some(Property::Metric) => self.metric.patch(pointer, value), + Some(property @ Property::Timestamp) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MetricSum { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for MetricSum { + fn pickle(&self, out: &mut Vec) { + self.count.pickle(out); + self.sum.pickle(out); + self.metric.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.count = Pickle::unpickle(stream)?; + this.sum = Pickle::unpickle(stream)?; + this.metric = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MetricSum { + fn default() -> Self { + Self { + count: 0u64, + sum: 0u64, + metric: Default::default(), + } + } +} + +impl IntoValue for MetricSum { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Count, self.count.into_value()); + map.insert_unchecked(Property::Sum, self.sum.into_value()); + map.insert_unchecked(Property::Metric, self.metric.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MetricSum { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Count) => self.count.patch(pointer, value), + Some(Property::Sum) => self.sum.patch(pointer, value), + Some(Property::Metric) => self.metric.patch(pointer, value), + Some(property @ Property::Timestamp) => { + Ok(MaybeUnpatched::Unpatched { property, value }) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Metrics { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Metrics; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.open_telemetry; + value.validate(errors); + let value = &self.prometheus; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Metrics { + fn pickle(&self, out: &mut Vec) { + self.open_telemetry.pickle(out); + self.prometheus.pickle(out); + self.metrics.pickle(out); + self.metrics_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.open_telemetry = Pickle::unpickle(stream)?; + this.prometheus = Pickle::unpickle(stream)?; + this.metrics = Pickle::unpickle(stream)?; + this.metrics_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Metrics { + fn default() -> Self { + Self { + open_telemetry: Default::default(), + prometheus: Default::default(), + metrics: Default::default(), + metrics_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for Metrics { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::OpenTelemetry, self.open_telemetry.into_value()); + map.insert_unchecked(Property::Prometheus, self.prometheus.into_value()); + map.insert_unchecked(Property::Metrics, self.metrics.into_value()); + map.insert_unchecked(Property::MetricsPolicy, self.metrics_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Metrics { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::OpenTelemetry) => self.open_telemetry.patch(pointer, value), + Some(Property::Prometheus) => self.prometheus.patch(pointer, value), + Some(Property::Metrics) => self.metrics.patch(pointer, value), + Some(Property::MetricsPolicy) => self.metrics_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MetricsOtel { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MetricsOtel::Disabled => true, + MetricsOtel::Http(inner) => inner.validate(errors), + MetricsOtel::Grpc(inner) => inner.validate(errors), + } + } +} + +impl Default for MetricsOtel { + fn default() -> Self { + MetricsOtel::Disabled + } +} + +impl Pickle for MetricsOtel { + fn pickle(&self, out: &mut Vec) { + match self { + MetricsOtel::Disabled => { + 0u16.pickle(out); + } + MetricsOtel::Http(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + MetricsOtel::Grpc(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(MetricsOtel::Disabled), + 1 => Pickle::unpickle(stream).map(MetricsOtel::Http), + 2 => Pickle::unpickle(stream).map(MetricsOtel::Grpc), + _ => None, + } + } +} + +impl IntoValue for MetricsOtel { + fn into_value(self) -> JmapValue<'static> { + match self { + MetricsOtel::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + MetricsOtel::Http(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Http".into())); + obj + } + MetricsOtel::Grpc(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Grpc".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MetricsOtel { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MetricsOtelType::Disabled => *self = MetricsOtel::Disabled, + MetricsOtelType::Http => *self = MetricsOtel::Http(Default::default()), + MetricsOtelType::Grpc => *self = MetricsOtel::Grpc(Default::default()), + } + } + match self { + MetricsOtel::Disabled => pointer.assert_eof(), + MetricsOtel::Http(inner) => inner.patch(pointer, value), + MetricsOtel::Grpc(inner) => inner.patch(pointer, value), + } + } +} + +impl MetricsOtel { + pub fn object_type(&self) -> MetricsOtelType { + match self { + MetricsOtel::Disabled => MetricsOtelType::Disabled, + MetricsOtel::Http(_) => MetricsOtelType::Http, + MetricsOtel::Grpc(_) => MetricsOtelType::Grpc, + } + } +} + +impl MetricsOtelGrpc { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.endpoint { + if value.is_empty() { + errors.push(ValidationError::required(Property::Endpoint)); + } + } + errors.len() == neb + } +} + +impl Pickle for MetricsOtelGrpc { + fn pickle(&self, out: &mut Vec) { + self.endpoint.pickle(out); + self.interval.pickle(out); + self.timeout.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.endpoint = Pickle::unpickle(stream)?; + this.interval = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MetricsOtelGrpc { + fn default() -> Self { + Self { + endpoint: Default::default(), + interval: Duration::from_millis(60000), + timeout: Duration::from_millis(10000), + } + } +} + +impl IntoValue for MetricsOtelGrpc { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Endpoint, self.endpoint.into_value()); + map.insert_unchecked(Property::Interval, self.interval.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MetricsOtelGrpc { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Endpoint) => self + .endpoint + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Interval) => self.interval.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MetricsOtelHttp { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.endpoint; + if value.is_empty() { + errors.push(ValidationError::required(Property::Endpoint)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for MetricsOtelHttp { + fn pickle(&self, out: &mut Vec) { + self.endpoint.pickle(out); + self.interval.pickle(out); + self.timeout.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.endpoint = Pickle::unpickle(stream)?; + this.interval = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MetricsOtelHttp { + fn default() -> Self { + Self { + endpoint: Default::default(), + interval: Duration::from_millis(60000), + timeout: Duration::from_millis(10000), + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for MetricsOtelHttp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Endpoint, self.endpoint.into_value()); + map.insert_unchecked(Property::Interval, self.interval.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MetricsOtelHttp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Endpoint) => self + .endpoint + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Interval) => self.interval.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MetricsPrometheus { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MetricsPrometheus::Disabled => true, + MetricsPrometheus::Enabled(inner) => inner.validate(errors), + } + } +} + +impl Default for MetricsPrometheus { + fn default() -> Self { + MetricsPrometheus::Disabled + } +} + +impl Pickle for MetricsPrometheus { + fn pickle(&self, out: &mut Vec) { + match self { + MetricsPrometheus::Disabled => { + 0u16.pickle(out); + } + MetricsPrometheus::Enabled(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(MetricsPrometheus::Disabled), + 1 => Pickle::unpickle(stream).map(MetricsPrometheus::Enabled), + _ => None, + } + } +} + +impl IntoValue for MetricsPrometheus { + fn into_value(self) -> JmapValue<'static> { + match self { + MetricsPrometheus::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + MetricsPrometheus::Enabled(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Enabled".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MetricsPrometheus { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MetricsPrometheusType::Disabled => *self = MetricsPrometheus::Disabled, + MetricsPrometheusType::Enabled => { + *self = MetricsPrometheus::Enabled(Default::default()) + } + } + } + match self { + MetricsPrometheus::Disabled => pointer.assert_eof(), + MetricsPrometheus::Enabled(inner) => inner.patch(pointer, value), + } + } +} + +impl MetricsPrometheus { + pub fn object_type(&self) -> MetricsPrometheusType { + match self { + MetricsPrometheus::Disabled => MetricsPrometheusType::Disabled, + MetricsPrometheus::Enabled(_) => MetricsPrometheusType::Enabled, + } + } +} + +impl MetricsPrometheusProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + errors.len() == neb + } +} + +impl Pickle for MetricsPrometheusProperties { + fn pickle(&self, out: &mut Vec) { + self.auth_secret.pickle(out); + self.auth_username.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.auth_secret = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MetricsPrometheusProperties { + fn default() -> Self { + Self { + auth_secret: Default::default(), + auth_username: Default::default(), + } + } +} + +impl IntoValue for MetricsPrometheusProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MetricsPrometheusProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MetricsStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MetricsStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MetricsStore::Disabled => true, + MetricsStore::Default => true, + MetricsStore::FoundationDb(inner) => inner.validate(errors), + MetricsStore::PostgreSql(inner) => inner.validate(errors), + MetricsStore::MySql(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for MetricsStore { + fn default() -> Self { + MetricsStore::Disabled + } +} + +impl Pickle for MetricsStore { + fn pickle(&self, out: &mut Vec) { + match self { + MetricsStore::Disabled => { + 0u16.pickle(out); + } + MetricsStore::Default => { + 1u16.pickle(out); + } + MetricsStore::FoundationDb(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + MetricsStore::PostgreSql(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + MetricsStore::MySql(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(MetricsStore::Disabled), + 1 => Some(MetricsStore::Default), + 2 => Pickle::unpickle(stream).map(MetricsStore::FoundationDb), + 3 => Pickle::unpickle(stream).map(MetricsStore::PostgreSql), + 4 => Pickle::unpickle(stream).map(MetricsStore::MySql), + _ => None, + } + } +} + +impl IntoValue for MetricsStore { + fn into_value(self) -> JmapValue<'static> { + match self { + MetricsStore::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + MetricsStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + MetricsStore::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + MetricsStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + MetricsStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MetricsStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MetricsStoreType::Disabled => *self = MetricsStore::Disabled, + MetricsStoreType::Default => *self = MetricsStore::Default, + MetricsStoreType::FoundationDb => { + *self = MetricsStore::FoundationDb(Default::default()) + } + MetricsStoreType::PostgreSql => { + *self = MetricsStore::PostgreSql(Default::default()) + } + MetricsStoreType::MySql => *self = MetricsStore::MySql(Default::default()), + } + } + match self { + MetricsStore::Disabled => pointer.assert_eof(), + MetricsStore::Default => pointer.assert_eof(), + MetricsStore::FoundationDb(inner) => inner.patch(pointer, value), + MetricsStore::PostgreSql(inner) => inner.patch(pointer, value), + MetricsStore::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl MetricsStore { + pub fn object_type(&self) -> MetricsStoreType { + match self { + MetricsStore::Disabled => MetricsStoreType::Disabled, + MetricsStore::Default => MetricsStoreType::Default, + MetricsStore::FoundationDb(_) => MetricsStoreType::FoundationDb, + MetricsStore::PostgreSql(_) => MetricsStoreType::PostgreSql, + MetricsStore::MySql(_) => MetricsStoreType::MySql, + } + } +} + +impl MtaConnectionIpHost { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.ehlo_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::EhloHostname)); + } + } + let value = &self.source_ip; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::SourceIp, value)); + } + errors.len() == neb + } +} + +impl Pickle for MtaConnectionIpHost { + fn pickle(&self, out: &mut Vec) { + self.ehlo_hostname.pickle(out); + self.source_ip.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.ehlo_hostname = Pickle::unpickle(stream)?; + this.source_ip = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaConnectionIpHost { + fn default() -> Self { + Self { + ehlo_hostname: Default::default(), + source_ip: Default::default(), + } + } +} + +impl IntoValue for MtaConnectionIpHost { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::EhloHostname, self.ehlo_hostname.into_value()); + map.insert_unchecked(Property::SourceIp, self.source_ip.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaConnectionIpHost { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::EhloHostname) => self + .ehlo_hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::SourceIp) => self.source_ip.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaConnectionStrategy { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaConnectionStrategy; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + if let Some(value) = &self.ehlo_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::EhloHostname)); + } + } + let value = &self.source_ips; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaConnectionStrategy { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.ehlo_hostname.pickle(out); + self.source_ips.pickle(out); + self.connect_timeout.pickle(out); + self.data_timeout.pickle(out); + self.ehlo_timeout.pickle(out); + self.greeting_timeout.pickle(out); + self.mail_from_timeout.pickle(out); + self.rcpt_to_timeout.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.ehlo_hostname = Pickle::unpickle(stream)?; + this.source_ips = Pickle::unpickle(stream)?; + this.connect_timeout = Pickle::unpickle(stream)?; + this.data_timeout = Pickle::unpickle(stream)?; + this.ehlo_timeout = Pickle::unpickle(stream)?; + this.greeting_timeout = Pickle::unpickle(stream)?; + this.mail_from_timeout = Pickle::unpickle(stream)?; + this.rcpt_to_timeout = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaConnectionStrategy { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + ehlo_hostname: Default::default(), + source_ips: Default::default(), + connect_timeout: Duration::from_millis(300000), + data_timeout: Duration::from_millis(600000), + ehlo_timeout: Duration::from_millis(300000), + greeting_timeout: Duration::from_millis(300000), + mail_from_timeout: Duration::from_millis(300000), + rcpt_to_timeout: Duration::from_millis(300000), + } + } +} + +impl IntoValue for MtaConnectionStrategy { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::EhloHostname, self.ehlo_hostname.into_value()); + map.insert_unchecked(Property::SourceIps, self.source_ips.into_value()); + map.insert_unchecked(Property::ConnectTimeout, self.connect_timeout.into_value()); + map.insert_unchecked(Property::DataTimeout, self.data_timeout.into_value()); + map.insert_unchecked(Property::EhloTimeout, self.ehlo_timeout.into_value()); + map.insert_unchecked( + Property::GreetingTimeout, + self.greeting_timeout.into_value(), + ); + map.insert_unchecked( + Property::MailFromTimeout, + self.mail_from_timeout.into_value(), + ); + map.insert_unchecked(Property::RcptToTimeout, self.rcpt_to_timeout.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaConnectionStrategy { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::EhloHostname) => self + .ehlo_hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::SourceIps) => self.source_ips.patch(pointer, value), + Some(Property::ConnectTimeout) => self.connect_timeout.patch(pointer, value), + Some(Property::DataTimeout) => self.data_timeout.patch(pointer, value), + Some(Property::EhloTimeout) => self.ehlo_timeout.patch(pointer, value), + Some(Property::GreetingTimeout) => self.greeting_timeout.patch(pointer, value), + Some(Property::MailFromTimeout) => self.mail_from_timeout.patch(pointer, value), + Some(Property::RcptToTimeout) => self.rcpt_to_timeout.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaDeliveryExpiration { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MtaDeliveryExpiration::Ttl(inner) => inner.validate(errors), + MtaDeliveryExpiration::Attempts(inner) => inner.validate(errors), + } + } +} + +impl Default for MtaDeliveryExpiration { + fn default() -> Self { + MtaDeliveryExpiration::Ttl(Default::default()) + } +} + +impl Pickle for MtaDeliveryExpiration { + fn pickle(&self, out: &mut Vec) { + match self { + MtaDeliveryExpiration::Ttl(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + MtaDeliveryExpiration::Attempts(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(MtaDeliveryExpiration::Ttl), + 1 => Pickle::unpickle(stream).map(MtaDeliveryExpiration::Attempts), + _ => None, + } + } +} + +impl IntoValue for MtaDeliveryExpiration { + fn into_value(self) -> JmapValue<'static> { + match self { + MtaDeliveryExpiration::Ttl(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ttl".into())); + obj + } + MtaDeliveryExpiration::Attempts(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Attempts".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MtaDeliveryExpiration { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MtaDeliveryExpirationType::Ttl => { + *self = MtaDeliveryExpiration::Ttl(Default::default()) + } + MtaDeliveryExpirationType::Attempts => { + *self = MtaDeliveryExpiration::Attempts(Default::default()) + } + } + } + match self { + MtaDeliveryExpiration::Ttl(inner) => inner.patch(pointer, value), + MtaDeliveryExpiration::Attempts(inner) => inner.patch(pointer, value), + } + } +} + +impl MtaDeliveryExpiration { + pub fn object_type(&self) -> MtaDeliveryExpirationType { + match self { + MtaDeliveryExpiration::Ttl(_) => MtaDeliveryExpirationType::Ttl, + MtaDeliveryExpiration::Attempts(_) => MtaDeliveryExpirationType::Attempts, + } + } +} + +impl MtaDeliveryExpirationAttempts { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_attempts; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAttempts, 1)); + } + errors.len() == neb + } +} + +impl Pickle for MtaDeliveryExpirationAttempts { + fn pickle(&self, out: &mut Vec) { + self.max_attempts.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_attempts = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaDeliveryExpirationAttempts { + fn default() -> Self { + Self { max_attempts: 5u64 } + } +} + +impl IntoValue for MtaDeliveryExpirationAttempts { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::MaxAttempts, self.max_attempts.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaDeliveryExpirationAttempts { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxAttempts) => self.max_attempts.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaDeliveryExpirationTtl { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for MtaDeliveryExpirationTtl { + fn pickle(&self, out: &mut Vec) { + self.expire.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.expire = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaDeliveryExpirationTtl { + fn default() -> Self { + Self { + expire: Duration::from_millis(259200000), + } + } +} + +impl IntoValue for MtaDeliveryExpirationTtl { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Expire, self.expire.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaDeliveryExpirationTtl { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Expire) => self.expire.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaDeliverySchedule { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaDeliverySchedule; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.expiry; + value.validate(errors); + let value = &self.notify; + value.validate(errors); + let value = &self.queue_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::QueueId)); + } + let value = &self.retry; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + i.foreign_key(ObjectType::MtaVirtualQueue, self.queue_id.into(), None); + } +} + +impl Pickle for MtaDeliverySchedule { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.expiry.pickle(out); + self.notify.pickle(out); + self.queue_id.pickle(out); + self.retry.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.expiry = Pickle::unpickle(stream)?; + this.notify = Pickle::unpickle(stream)?; + this.queue_id = Pickle::unpickle(stream)?; + this.retry = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaDeliverySchedule { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + expiry: Default::default(), + notify: Default::default(), + queue_id: Default::default(), + retry: Default::default(), + } + } +} + +impl IntoValue for MtaDeliverySchedule { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Expiry, self.expiry.into_value()); + map.insert_unchecked(Property::Notify, self.notify.into_value()); + map.insert_unchecked(Property::QueueId, self.queue_id.into_value()); + map.insert_unchecked(Property::Retry, self.retry.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaDeliverySchedule { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Expiry) => self.expiry.patch(pointer, value), + Some(Property::Notify) => self.notify.patch(pointer, value), + Some(Property::QueueId) => self.queue_id.patch(pointer, value), + Some(Property::Retry) => self.retry.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaDeliveryScheduleInterval { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for MtaDeliveryScheduleInterval { + fn pickle(&self, out: &mut Vec) { + self.duration.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.duration = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaDeliveryScheduleInterval { + fn default() -> Self { + Self { + duration: Duration::from_millis(3600000), + } + } +} + +impl IntoValue for MtaDeliveryScheduleInterval { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Duration, self.duration.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaDeliveryScheduleInterval { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Duration) => self.duration.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaDeliveryScheduleIntervals { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.intervals; + for value in value.values() { + value.validate(errors); + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Intervals, 1)); + } + errors.len() == neb + } +} + +impl Pickle for MtaDeliveryScheduleIntervals { + fn pickle(&self, out: &mut Vec) { + self.intervals.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.intervals = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaDeliveryScheduleIntervals { + fn default() -> Self { + Self { + intervals: Default::default(), + } + } +} + +impl IntoValue for MtaDeliveryScheduleIntervals { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Intervals, self.intervals.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaDeliveryScheduleIntervals { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Intervals) => self.intervals.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaDeliveryScheduleIntervalsOrDefault { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MtaDeliveryScheduleIntervalsOrDefault::Default => true, + MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => inner.validate(errors), + } + } +} + +impl Default for MtaDeliveryScheduleIntervalsOrDefault { + fn default() -> Self { + MtaDeliveryScheduleIntervalsOrDefault::Default + } +} + +impl Pickle for MtaDeliveryScheduleIntervalsOrDefault { + fn pickle(&self, out: &mut Vec) { + match self { + MtaDeliveryScheduleIntervalsOrDefault::Default => { + 0u16.pickle(out); + } + MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(MtaDeliveryScheduleIntervalsOrDefault::Default), + 1 => Pickle::unpickle(stream).map(MtaDeliveryScheduleIntervalsOrDefault::Custom), + _ => None, + } + } +} + +impl IntoValue for MtaDeliveryScheduleIntervalsOrDefault { + fn into_value(self) -> JmapValue<'static> { + match self { + MtaDeliveryScheduleIntervalsOrDefault::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + MtaDeliveryScheduleIntervalsOrDefault::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MtaDeliveryScheduleIntervalsOrDefault { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MtaDeliveryScheduleIntervalsOrDefaultType::Default => { + *self = MtaDeliveryScheduleIntervalsOrDefault::Default + } + MtaDeliveryScheduleIntervalsOrDefaultType::Custom => { + *self = MtaDeliveryScheduleIntervalsOrDefault::Custom(Default::default()) + } + } + } + match self { + MtaDeliveryScheduleIntervalsOrDefault::Default => pointer.assert_eof(), + MtaDeliveryScheduleIntervalsOrDefault::Custom(inner) => inner.patch(pointer, value), + } + } +} + +impl MtaDeliveryScheduleIntervalsOrDefault { + pub fn object_type(&self) -> MtaDeliveryScheduleIntervalsOrDefaultType { + match self { + MtaDeliveryScheduleIntervalsOrDefault::Default => { + MtaDeliveryScheduleIntervalsOrDefaultType::Default + } + MtaDeliveryScheduleIntervalsOrDefault::Custom(_) => { + MtaDeliveryScheduleIntervalsOrDefaultType::Custom + } + } + } +} + +impl ObjectImpl for MtaExtensions { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaExtensions; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.chunking; + value.validate(errors); + let value = &self.deliver_by; + value.validate(errors); + let value = &self.dsn; + value.validate(errors); + let value = &self.expn; + value.validate(errors); + let value = &self.future_release; + value.validate(errors); + let value = &self.mt_priority; + value.validate(errors); + let value = &self.no_soliciting; + value.validate(errors); + let value = &self.pipelining; + value.validate(errors); + let value = &self.require_tls; + value.validate(errors); + let value = &self.vrfy; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaExtensions { + pub fn ctx_chunking(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.chunking, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Chunking, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_deliver_by(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.deliver_by, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "15d".to_string(), + }]), + }), + property: Property::DeliverBy, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dsn(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dsn, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::Dsn, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_expn(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.expn, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::Expn, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_future_release(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.future_release, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "7d".to_string(), + }]), + }), + property: Property::FutureRelease, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_mt_priority(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.mt_priority, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "mixer".to_string(), + }]), + }), + property: Property::MtPriority, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: MTA_PRIORITY_CONSTANT, + } + } + + pub fn ctx_no_soliciting(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.no_soliciting, + default: Some(Expression { + else_: "''".to_string(), + ..Default::default() + }), + property: Property::NoSoliciting, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_pipelining(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.pipelining, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Pipelining, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_require_tls(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.require_tls, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::RequireTls, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_vrfy(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.vrfy, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::Vrfy, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_chunking(), + self.ctx_deliver_by(), + self.ctx_dsn(), + self.ctx_expn(), + self.ctx_future_release(), + self.ctx_mt_priority(), + self.ctx_no_soliciting(), + self.ctx_pipelining(), + self.ctx_require_tls(), + self.ctx_vrfy(), + ] + } +} + +impl Pickle for MtaExtensions { + fn pickle(&self, out: &mut Vec) { + self.chunking.pickle(out); + self.deliver_by.pickle(out); + self.dsn.pickle(out); + self.expn.pickle(out); + self.future_release.pickle(out); + self.mt_priority.pickle(out); + self.no_soliciting.pickle(out); + self.pipelining.pickle(out); + self.require_tls.pickle(out); + self.vrfy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.chunking = Pickle::unpickle(stream)?; + this.deliver_by = Pickle::unpickle(stream)?; + this.dsn = Pickle::unpickle(stream)?; + this.expn = Pickle::unpickle(stream)?; + this.future_release = Pickle::unpickle(stream)?; + this.mt_priority = Pickle::unpickle(stream)?; + this.no_soliciting = Pickle::unpickle(stream)?; + this.pipelining = Pickle::unpickle(stream)?; + this.require_tls = Pickle::unpickle(stream)?; + this.vrfy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaExtensions { + fn default() -> Self { + Self { + chunking: Expression { + else_: "true".to_string(), + ..Default::default() + }, + deliver_by: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "15d".to_string(), + }]), + }, + dsn: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }, + expn: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }, + future_release: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "7d".to_string(), + }]), + }, + mt_priority: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "mixer".to_string(), + }]), + }, + no_soliciting: Expression { + else_: "''".to_string(), + ..Default::default() + }, + pipelining: Expression { + else_: "true".to_string(), + ..Default::default() + }, + require_tls: Expression { + else_: "true".to_string(), + ..Default::default() + }, + vrfy: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".to_string(), + then: "true".to_string(), + }]), + }, + } + } +} + +impl IntoValue for MtaExtensions { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::Chunking, self.chunking.into_value()); + map.insert_unchecked(Property::DeliverBy, self.deliver_by.into_value()); + map.insert_unchecked(Property::Dsn, self.dsn.into_value()); + map.insert_unchecked(Property::Expn, self.expn.into_value()); + map.insert_unchecked(Property::FutureRelease, self.future_release.into_value()); + map.insert_unchecked(Property::MtPriority, self.mt_priority.into_value()); + map.insert_unchecked(Property::NoSoliciting, self.no_soliciting.into_value()); + map.insert_unchecked(Property::Pipelining, self.pipelining.into_value()); + map.insert_unchecked(Property::RequireTls, self.require_tls.into_value()); + map.insert_unchecked(Property::Vrfy, self.vrfy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaExtensions { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Chunking) => self.chunking.patch(pointer, value), + Some(Property::DeliverBy) => self.deliver_by.patch(pointer, value), + Some(Property::Dsn) => self.dsn.patch(pointer, value), + Some(Property::Expn) => self.expn.patch(pointer, value), + Some(Property::FutureRelease) => self.future_release.patch(pointer, value), + Some(Property::MtPriority) => self.mt_priority.patch(pointer, value), + Some(Property::NoSoliciting) => self.no_soliciting.patch(pointer, value), + Some(Property::Pipelining) => self.pipelining.patch(pointer, value), + Some(Property::RequireTls) => self.require_tls.patch(pointer, value), + Some(Property::Vrfy) => self.vrfy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaHook { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaHook; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.enable; + value.validate(errors); + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaHook { + pub fn ctx_enable(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.enable, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Enable, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_enable()] + } +} + +impl Pickle for MtaHook { + fn pickle(&self, out: &mut Vec) { + self.allow_invalid_certs.pickle(out); + self.enable.pickle(out); + self.max_response_size.pickle(out); + self.temp_fail_on_error.pickle(out); + self.stages.pickle(out); + self.timeout.pickle(out); + self.url.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.max_response_size = Pickle::unpickle(stream)?; + this.temp_fail_on_error = Pickle::unpickle(stream)?; + this.stages = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaHook { + fn default() -> Self { + Self { + allow_invalid_certs: false, + enable: Expression { + else_: "true".to_string(), + ..Default::default() + }, + max_response_size: 52428800u64, + temp_fail_on_error: true, + stages: Map::new(vec![MtaStage::Data]), + timeout: Duration::from_millis(30000), + url: Default::default(), + http_auth: Default::default(), + http_headers: Default::default(), + } + } +} + +impl IntoValue for MtaHook { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked( + Property::MaxResponseSize, + self.max_response_size.into_value(), + ); + map.insert_unchecked( + Property::TempFailOnError, + self.temp_fail_on_error.into_value(), + ); + map.insert_unchecked(Property::Stages, self.stages.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaHook { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::MaxResponseSize) => self.max_response_size.patch(pointer, value), + Some(Property::TempFailOnError) => self.temp_fail_on_error.patch(pointer, value), + Some(Property::Stages) => self.stages.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaInboundSession { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaInboundSession; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_duration; + value.validate(errors); + let value = &self.timeout; + value.validate(errors); + let value = &self.transfer_limit; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaInboundSession { + pub fn ctx_max_duration(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_duration, + default: Some(Expression { + else_: "10m".to_string(), + ..Default::default() + }), + property: Property::MaxDuration, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_timeout(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.timeout, + default: Some(Expression { + else_: "5m".to_string(), + ..Default::default() + }), + property: Property::Timeout, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_transfer_limit(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.transfer_limit, + default: Some(Expression { + else_: "262144000".to_string(), + ..Default::default() + }), + property: Property::TransferLimit, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_max_duration(), + self.ctx_timeout(), + self.ctx_transfer_limit(), + ] + } +} + +impl Pickle for MtaInboundSession { + fn pickle(&self, out: &mut Vec) { + self.max_duration.pickle(out); + self.timeout.pickle(out); + self.transfer_limit.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_duration = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.transfer_limit = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaInboundSession { + fn default() -> Self { + Self { + max_duration: Expression { + else_: "10m".to_string(), + ..Default::default() + }, + timeout: Expression { + else_: "5m".to_string(), + ..Default::default() + }, + transfer_limit: Expression { + else_: "262144000".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaInboundSession { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::MaxDuration, self.max_duration.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::TransferLimit, self.transfer_limit.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaInboundSession { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxDuration) => self.max_duration.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::TransferLimit) => self.transfer_limit.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaInboundThrottle { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaInboundThrottle; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.match_; + value.validate(errors); + let value = &self.rate; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaInboundThrottle { + pub fn ctx_match_(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.match_, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Match, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_match_()] + } +} + +impl Pickle for MtaInboundThrottle { + fn pickle(&self, out: &mut Vec) { + self.enable.pickle(out); + self.description.pickle(out); + self.key.pickle(out); + self.match_.pickle(out); + self.rate.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.match_ = Pickle::unpickle(stream)?; + this.rate = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaInboundThrottle { + fn default() -> Self { + Self { + enable: true, + description: Default::default(), + key: Default::default(), + match_: Expression { + else_: "true".to_string(), + ..Default::default() + }, + rate: Default::default(), + } + } +} + +impl IntoValue for MtaInboundThrottle { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Match, self.match_.into_value()); + map.insert_unchecked(Property::Rate, self.rate.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaInboundThrottle { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Description) => { + self.description.patch(pointer.assert_read_only()?, value) + } + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Match) => self.match_.patch(pointer, value), + Some(Property::Rate) => self.rate.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaMilter { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaMilter; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.enable; + value.validate(errors); + let value = &self.hostname; + if value.is_empty() { + errors.push(ValidationError::required(Property::Hostname)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.stages; + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Stages, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaMilter { + pub fn ctx_enable(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.enable, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Enable, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_enable()] + } +} + +impl Pickle for MtaMilter { + fn pickle(&self, out: &mut Vec) { + self.allow_invalid_certs.pickle(out); + self.enable.pickle(out); + self.hostname.pickle(out); + self.max_response_size.pickle(out); + self.temp_fail_on_error.pickle(out); + self.protocol_version.pickle(out); + self.port.pickle(out); + self.stages.pickle(out); + self.timeout_command.pickle(out); + self.timeout_connect.pickle(out); + self.timeout_data.pickle(out); + self.use_tls.pickle(out); + self.flags_action.pickle(out); + self.flags_protocol.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.hostname = Pickle::unpickle(stream)?; + this.max_response_size = Pickle::unpickle(stream)?; + this.temp_fail_on_error = Pickle::unpickle(stream)?; + this.protocol_version = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.stages = Pickle::unpickle(stream)?; + this.timeout_command = Pickle::unpickle(stream)?; + this.timeout_connect = Pickle::unpickle(stream)?; + this.timeout_data = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.flags_action = Pickle::unpickle(stream)?; + this.flags_protocol = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaMilter { + fn default() -> Self { + Self { + allow_invalid_certs: false, + enable: Expression { + else_: "true".to_string(), + ..Default::default() + }, + hostname: Default::default(), + max_response_size: 52428800u64, + temp_fail_on_error: true, + protocol_version: MilterVersion::V6, + port: 11332u64, + stages: Map::new(vec![MtaStage::Data]), + timeout_command: Duration::from_millis(30000), + timeout_connect: Duration::from_millis(30000), + timeout_data: Duration::from_millis(60000), + use_tls: false, + flags_action: Default::default(), + flags_protocol: Default::default(), + } + } +} + +impl IntoValue for MtaMilter { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Hostname, self.hostname.into_value()); + map.insert_unchecked( + Property::MaxResponseSize, + self.max_response_size.into_value(), + ); + map.insert_unchecked( + Property::TempFailOnError, + self.temp_fail_on_error.into_value(), + ); + map.insert_unchecked( + Property::ProtocolVersion, + self.protocol_version.into_value(), + ); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Stages, self.stages.into_value()); + map.insert_unchecked(Property::TimeoutCommand, self.timeout_command.into_value()); + map.insert_unchecked(Property::TimeoutConnect, self.timeout_connect.into_value()); + map.insert_unchecked(Property::TimeoutData, self.timeout_data.into_value()); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked(Property::FlagsAction, self.flags_action.into_value()); + map.insert_unchecked(Property::FlagsProtocol, self.flags_protocol.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaMilter { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Hostname) => self + .hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::MaxResponseSize) => self.max_response_size.patch(pointer, value), + Some(Property::TempFailOnError) => self.temp_fail_on_error.patch(pointer, value), + Some(Property::ProtocolVersion) => self.protocol_version.patch(pointer, value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Stages) => self.stages.patch(pointer, value), + Some(Property::TimeoutCommand) => self.timeout_command.patch(pointer, value), + Some(Property::TimeoutConnect) => self.timeout_connect.patch(pointer, value), + Some(Property::TimeoutData) => self.timeout_data.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::FlagsAction) => self.flags_action.patch(pointer, value), + Some(Property::FlagsProtocol) => self.flags_protocol.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaOutboundStrategy { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaOutboundStrategy; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.connection; + value.validate(errors); + let value = &self.route; + value.validate(errors); + let value = &self.schedule; + value.validate(errors); + let value = &self.tls; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaOutboundStrategy { + pub fn ctx_connection(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.connection, + default: Some(Expression { + else_: "'default'".to_string(), + ..Default::default() + }), + property: Property::Connection, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_route(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.route, + default: Some(Expression { + else_: "'mx'".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "is_local_domain(rcpt_domain)".to_string(), + then: "'local'".to_string(), + }]), + }), + property: Property::Route, + allowed_variables: MTA_QUEUE_RCPT_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_schedule(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.schedule, + default: Some(Expression { + else_: "'remote'".to_string(), + match_: List::from_iter([ + ExpressionMatch { + if_: "is_local_domain(rcpt_domain)".to_string(), + then: "'local'".to_string(), + }, + ExpressionMatch { + if_: "source == 'dsn'".to_string(), + then: "'dsn'".to_string(), + }, + ExpressionMatch { + if_: "source == 'report'".to_string(), + then: "'report'".to_string(), + }, + ]), + }), + property: Property::Schedule, + allowed_variables: MTA_QUEUE_RCPT_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_tls(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tls, + default: Some(Expression { + else_: "'default'".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "retry_num > 0 && last_error == 'tls'".to_string(), + then: "'invalid-tls'".to_string(), + }]), + }), + property: Property::Tls, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_connection(), + self.ctx_route(), + self.ctx_schedule(), + self.ctx_tls(), + ] + } +} + +impl Pickle for MtaOutboundStrategy { + fn pickle(&self, out: &mut Vec) { + self.connection.pickle(out); + self.route.pickle(out); + self.schedule.pickle(out); + self.tls.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.connection = Pickle::unpickle(stream)?; + this.route = Pickle::unpickle(stream)?; + this.schedule = Pickle::unpickle(stream)?; + this.tls = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaOutboundStrategy { + fn default() -> Self { + Self { + connection: Expression { + else_: "'default'".to_string(), + ..Default::default() + }, + route: Expression { + else_: "'mx'".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "is_local_domain(rcpt_domain)".to_string(), + then: "'local'".to_string(), + }]), + }, + schedule: Expression { + else_: "'remote'".to_string(), + match_: List::from_iter([ + ExpressionMatch { + if_: "is_local_domain(rcpt_domain)".to_string(), + then: "'local'".to_string(), + }, + ExpressionMatch { + if_: "source == 'dsn'".to_string(), + then: "'dsn'".to_string(), + }, + ExpressionMatch { + if_: "source == 'report'".to_string(), + then: "'report'".to_string(), + }, + ]), + }, + tls: Expression { + else_: "'default'".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "retry_num > 0 && last_error == 'tls'".to_string(), + then: "'invalid-tls'".to_string(), + }]), + }, + } + } +} + +impl IntoValue for MtaOutboundStrategy { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Connection, self.connection.into_value()); + map.insert_unchecked(Property::Route, self.route.into_value()); + map.insert_unchecked(Property::Schedule, self.schedule.into_value()); + map.insert_unchecked(Property::Tls, self.tls.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaOutboundStrategy { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Connection) => self.connection.patch(pointer, value), + Some(Property::Route) => self.route.patch(pointer, value), + Some(Property::Schedule) => self.schedule.patch(pointer, value), + Some(Property::Tls) => self.tls.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaOutboundThrottle { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaOutboundThrottle; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.match_; + value.validate(errors); + let value = &self.rate; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaOutboundThrottle { + pub fn ctx_match_(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.match_, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Match, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_match_()] + } +} + +impl Pickle for MtaOutboundThrottle { + fn pickle(&self, out: &mut Vec) { + self.enable.pickle(out); + self.description.pickle(out); + self.key.pickle(out); + self.match_.pickle(out); + self.rate.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.match_ = Pickle::unpickle(stream)?; + this.rate = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaOutboundThrottle { + fn default() -> Self { + Self { + enable: true, + description: Default::default(), + key: Default::default(), + match_: Expression { + else_: "true".to_string(), + ..Default::default() + }, + rate: Default::default(), + } + } +} + +impl IntoValue for MtaOutboundThrottle { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Match, self.match_.into_value()); + map.insert_unchecked(Property::Rate, self.rate.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaOutboundThrottle { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Match) => self.match_.patch(pointer, value), + Some(Property::Rate) => self.rate.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaQueueQuota { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaQueueQuota; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.key; + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Key, 1)); + } + let value = &self.match_; + value.validate(errors); + if let Some(value) = &self.messages { + if *value < 1 { + errors.push(ValidationError::min_value(Property::Messages, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaQueueQuota { + pub fn ctx_match_(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.match_, + default: None, + property: Property::Match, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_match_()] + } +} + +impl Pickle for MtaQueueQuota { + fn pickle(&self, out: &mut Vec) { + self.enable.pickle(out); + self.description.pickle(out); + self.key.pickle(out); + self.match_.pickle(out); + self.messages.pickle(out); + self.size.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.match_ = Pickle::unpickle(stream)?; + this.messages = Pickle::unpickle(stream)?; + this.size = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaQueueQuota { + fn default() -> Self { + Self { + enable: true, + description: Default::default(), + key: Default::default(), + match_: Default::default(), + messages: Default::default(), + size: Default::default(), + } + } +} + +impl IntoValue for MtaQueueQuota { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Match, self.match_.into_value()); + map.insert_unchecked(Property::Messages, self.messages.into_value()); + map.insert_unchecked(Property::Size, self.size.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaQueueQuota { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Description) => { + self.description.patch(pointer.assert_read_only()?, value) + } + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Match) => self.match_.patch(pointer, value), + Some(Property::Messages) => self.messages.patch(pointer, value), + Some(Property::Size) => self.size.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaRoute { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaRoute; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + MtaRoute::Mx(inner) => inner.validate(errors), + MtaRoute::Relay(inner) => inner.validate(errors), + MtaRoute::Local(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + MtaRoute::Mx(object) => { + object.index(i); + } + MtaRoute::Relay(object) => { + object.index(i); + } + MtaRoute::Local(object) => { + object.index(i); + } + } + } +} + +impl Default for MtaRoute { + fn default() -> Self { + MtaRoute::Mx(Default::default()) + } +} + +impl Pickle for MtaRoute { + fn pickle(&self, out: &mut Vec) { + match self { + MtaRoute::Mx(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + MtaRoute::Relay(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + MtaRoute::Local(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(MtaRoute::Mx), + 1 => Pickle::unpickle(stream).map(MtaRoute::Relay), + 2 => Pickle::unpickle(stream).map(MtaRoute::Local), + _ => None, + } + } +} + +impl IntoValue for MtaRoute { + fn into_value(self) -> JmapValue<'static> { + match self { + MtaRoute::Mx(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Mx".into())); + obj + } + MtaRoute::Relay(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Relay".into())); + obj + } + MtaRoute::Local(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Local".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for MtaRoute { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + MtaRouteType::Mx => *self = MtaRoute::Mx(Default::default()), + MtaRouteType::Relay => *self = MtaRoute::Relay(Default::default()), + MtaRouteType::Local => *self = MtaRoute::Local(Default::default()), + } + } + match self { + MtaRoute::Mx(inner) => inner.patch(pointer, value), + MtaRoute::Relay(inner) => inner.patch(pointer, value), + MtaRoute::Local(inner) => inner.patch(pointer, value), + } + } +} + +impl MtaRoute { + pub fn object_type(&self) -> MtaRouteType { + match self { + MtaRoute::Mx(_) => MtaRouteType::Mx, + MtaRoute::Relay(_) => MtaRouteType::Relay, + MtaRoute::Local(_) => MtaRouteType::Local, + } + } +} + +impl MtaRouteCommon { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaRouteCommon { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaRouteCommon { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + } + } +} + +impl IntoValue for MtaRouteCommon { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaRouteCommon { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaRouteMx { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_multihomed; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMultihomed, 1)); + } + let value = &self.max_mx_hosts; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMxHosts, 1)); + } + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaRouteMx { + fn pickle(&self, out: &mut Vec) { + self.ip_lookup_strategy.pickle(out); + self.max_multihomed.pickle(out); + self.max_mx_hosts.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.ip_lookup_strategy = Pickle::unpickle(stream)?; + this.max_multihomed = Pickle::unpickle(stream)?; + this.max_mx_hosts = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaRouteMx { + fn default() -> Self { + Self { + ip_lookup_strategy: MtaIpStrategy::V4ThenV6, + max_multihomed: 2u64, + max_mx_hosts: 5u64, + name: Default::default(), + description: Default::default(), + } + } +} + +impl IntoValue for MtaRouteMx { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked( + Property::IpLookupStrategy, + self.ip_lookup_strategy.into_value(), + ); + map.insert_unchecked(Property::MaxMultihomed, self.max_multihomed.into_value()); + map.insert_unchecked(Property::MaxMxHosts, self.max_mx_hosts.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaRouteMx { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IpLookupStrategy) => self.ip_lookup_strategy.patch(pointer, value), + Some(Property::MaxMultihomed) => self.max_multihomed.patch(pointer, value), + Some(Property::MaxMxHosts) => self.max_mx_hosts.patch(pointer, value), + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MtaRouteRelay { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.address; + if value.is_empty() { + errors.push(ValidationError::required(Property::Address)); + } + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaRouteRelay { + fn pickle(&self, out: &mut Vec) { + self.address.pickle(out); + self.auth_secret.pickle(out); + self.auth_username.pickle(out); + self.port.pickle(out); + self.protocol.pickle(out); + self.allow_invalid_certs.pickle(out); + self.implicit_tls.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.address = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.protocol = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.implicit_tls = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaRouteRelay { + fn default() -> Self { + Self { + address: Default::default(), + auth_secret: Default::default(), + auth_username: Default::default(), + port: 25u64, + protocol: MtaProtocol::Smtp, + allow_invalid_certs: false, + implicit_tls: false, + name: Default::default(), + description: Default::default(), + } + } +} + +impl IntoValue for MtaRouteRelay { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Address, self.address.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Protocol, self.protocol.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::ImplicitTls, self.implicit_tls.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaRouteRelay { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Address) => self + .address + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::AuthUsername) => self.auth_username.patch(pointer, value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Protocol) => self.protocol.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::ImplicitTls) => self.implicit_tls.patch(pointer, value), + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageAuth { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageAuth; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_failures; + value.validate(errors); + let value = &self.wait_on_fail; + value.validate(errors); + let value = &self.sasl_mechanisms; + value.validate(errors); + let value = &self.must_match_sender; + value.validate(errors); + let value = &self.require; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageAuth { + pub fn ctx_max_failures(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_failures, + default: Some(Expression { + else_: "3".to_string(), + ..Default::default() + }), + property: Property::MaxFailures, + allowed_variables: MTA_EHLO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_wait_on_fail(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.wait_on_fail, + default: Some(Expression { + else_: "5s".to_string(), + ..Default::default() + }), + property: Property::WaitOnFail, + allowed_variables: MTA_EHLO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_sasl_mechanisms(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.sasl_mechanisms, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ + ExpressionMatch { + if_: "local_port != 25 && is_tls".to_string(), + then: "[plain, login, oauthbearer, xoauth2]".to_string(), + }, + ExpressionMatch { + if_: "local_port != 25".to_string(), + then: "[oauthbearer, xoauth2]".to_string(), + }, + ]), + }), + property: Property::SaslMechanisms, + allowed_variables: MTA_EHLO_VARIABLE, + allowed_constants: MTA_AUTH_TYPE_CONSTANT, + } + } + + pub fn ctx_must_match_sender(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.must_match_sender, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::MustMatchSender, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_require(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.require, + default: Some(Expression { + else_: "local_port != 25".to_string(), + ..Default::default() + }), + property: Property::Require, + allowed_variables: MTA_EHLO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_max_failures(), + self.ctx_wait_on_fail(), + self.ctx_sasl_mechanisms(), + self.ctx_must_match_sender(), + self.ctx_require(), + ] + } +} + +impl Pickle for MtaStageAuth { + fn pickle(&self, out: &mut Vec) { + self.max_failures.pickle(out); + self.wait_on_fail.pickle(out); + self.sasl_mechanisms.pickle(out); + self.must_match_sender.pickle(out); + self.require.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_failures = Pickle::unpickle(stream)?; + this.wait_on_fail = Pickle::unpickle(stream)?; + this.sasl_mechanisms = Pickle::unpickle(stream)?; + this.must_match_sender = Pickle::unpickle(stream)?; + this.require = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageAuth { + fn default() -> Self { + Self { + max_failures: Expression { + else_: "3".to_string(), + ..Default::default() + }, + wait_on_fail: Expression { + else_: "5s".to_string(), + ..Default::default() + }, + sasl_mechanisms: Expression { + else_: "false".to_string(), + match_: List::from_iter([ + ExpressionMatch { + if_: "local_port != 25 && is_tls".to_string(), + then: "[plain, login, oauthbearer, xoauth2]".to_string(), + }, + ExpressionMatch { + if_: "local_port != 25".to_string(), + then: "[oauthbearer, xoauth2]".to_string(), + }, + ]), + }, + must_match_sender: Expression { + else_: "true".to_string(), + ..Default::default() + }, + require: Expression { + else_: "local_port != 25".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageAuth { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::MaxFailures, self.max_failures.into_value()); + map.insert_unchecked(Property::WaitOnFail, self.wait_on_fail.into_value()); + map.insert_unchecked(Property::SaslMechanisms, self.sasl_mechanisms.into_value()); + map.insert_unchecked( + Property::MustMatchSender, + self.must_match_sender.into_value(), + ); + map.insert_unchecked(Property::Require, self.require.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageAuth { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxFailures) => self.max_failures.patch(pointer, value), + Some(Property::WaitOnFail) => self.wait_on_fail.patch(pointer, value), + Some(Property::SaslMechanisms) => self.sasl_mechanisms.patch(pointer, value), + Some(Property::MustMatchSender) => self.must_match_sender.patch(pointer, value), + Some(Property::Require) => self.require.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageConnect { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageConnect; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.smtp_greeting; + value.validate(errors); + let value = &self.hostname; + value.validate(errors); + let value = &self.script; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageConnect { + pub fn ctx_smtp_greeting(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.smtp_greeting, + default: Some(Expression { + else_: "system('hostname') + ' Stalwart ESMTP at your service'".to_string(), + ..Default::default() + }), + property: Property::SmtpGreeting, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_hostname(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.hostname, + default: Some(Expression { + else_: "system('hostname')".to_string(), + ..Default::default() + }), + property: Property::Hostname, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_script(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.script, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Script, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_smtp_greeting(), + self.ctx_hostname(), + self.ctx_script(), + ] + } +} + +impl Pickle for MtaStageConnect { + fn pickle(&self, out: &mut Vec) { + self.smtp_greeting.pickle(out); + self.hostname.pickle(out); + self.script.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.smtp_greeting = Pickle::unpickle(stream)?; + this.hostname = Pickle::unpickle(stream)?; + this.script = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageConnect { + fn default() -> Self { + Self { + smtp_greeting: Expression { + else_: "system('hostname') + ' Stalwart ESMTP at your service'".to_string(), + ..Default::default() + }, + hostname: Expression { + else_: "system('hostname')".to_string(), + ..Default::default() + }, + script: Expression { + else_: "false".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageConnect { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::SmtpGreeting, self.smtp_greeting.into_value()); + map.insert_unchecked(Property::Hostname, self.hostname.into_value()); + map.insert_unchecked(Property::Script, self.script.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageConnect { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::SmtpGreeting) => self.smtp_greeting.patch(pointer, value), + Some(Property::Hostname) => self.hostname.patch(pointer, value), + Some(Property::Script) => self.script.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageData { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageData; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.add_auth_results_header; + value.validate(errors); + let value = &self.add_date_header; + value.validate(errors); + let value = &self.add_message_id_header; + value.validate(errors); + let value = &self.add_received_header; + value.validate(errors); + let value = &self.add_received_spf_header; + value.validate(errors); + let value = &self.add_return_path_header; + value.validate(errors); + let value = &self.max_messages; + value.validate(errors); + let value = &self.max_received_headers; + value.validate(errors); + let value = &self.max_message_size; + value.validate(errors); + let value = &self.script; + value.validate(errors); + let value = &self.enable_spam_filter; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageData { + pub fn ctx_add_auth_results_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_auth_results_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddAuthResultsHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_add_date_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_date_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddDateHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_add_message_id_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_message_id_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddMessageIdHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_add_received_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_received_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddReceivedHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_add_received_spf_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_received_spf_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddReceivedSpfHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_add_return_path_header(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.add_return_path_header, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::AddReturnPathHeader, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_max_messages(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_messages, + default: Some(Expression { + else_: "10".to_string(), + ..Default::default() + }), + property: Property::MaxMessages, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_max_received_headers(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_received_headers, + default: Some(Expression { + else_: "50".to_string(), + ..Default::default() + }), + property: Property::MaxReceivedHeaders, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_max_message_size(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_message_size, + default: Some(Expression { + else_: "104857600".to_string(), + ..Default::default() + }), + property: Property::MaxMessageSize, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_script(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.script, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Script, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_enable_spam_filter(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.enable_spam_filter, + default: Some(Expression { + else_: "is_empty(authenticated_as)".to_string(), + ..Default::default() + }), + property: Property::EnableSpamFilter, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_add_auth_results_header(), + self.ctx_add_date_header(), + self.ctx_add_message_id_header(), + self.ctx_add_received_header(), + self.ctx_add_received_spf_header(), + self.ctx_add_return_path_header(), + self.ctx_max_messages(), + self.ctx_max_received_headers(), + self.ctx_max_message_size(), + self.ctx_script(), + self.ctx_enable_spam_filter(), + ] + } +} + +impl Pickle for MtaStageData { + fn pickle(&self, out: &mut Vec) { + self.add_auth_results_header.pickle(out); + self.add_date_header.pickle(out); + self.add_delivered_to_header.pickle(out); + self.add_message_id_header.pickle(out); + self.add_received_header.pickle(out); + self.add_received_spf_header.pickle(out); + self.add_return_path_header.pickle(out); + self.max_messages.pickle(out); + self.max_received_headers.pickle(out); + self.max_message_size.pickle(out); + self.script.pickle(out); + self.enable_spam_filter.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.add_auth_results_header = Pickle::unpickle(stream)?; + this.add_date_header = Pickle::unpickle(stream)?; + this.add_delivered_to_header = Pickle::unpickle(stream)?; + this.add_message_id_header = Pickle::unpickle(stream)?; + this.add_received_header = Pickle::unpickle(stream)?; + this.add_received_spf_header = Pickle::unpickle(stream)?; + this.add_return_path_header = Pickle::unpickle(stream)?; + this.max_messages = Pickle::unpickle(stream)?; + this.max_received_headers = Pickle::unpickle(stream)?; + this.max_message_size = Pickle::unpickle(stream)?; + this.script = Pickle::unpickle(stream)?; + this.enable_spam_filter = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageData { + fn default() -> Self { + Self { + add_auth_results_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + add_date_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + add_delivered_to_header: true, + add_message_id_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + add_received_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + add_received_spf_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + add_return_path_header: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + max_messages: Expression { + else_: "10".to_string(), + ..Default::default() + }, + max_received_headers: Expression { + else_: "50".to_string(), + ..Default::default() + }, + max_message_size: Expression { + else_: "104857600".to_string(), + ..Default::default() + }, + script: Expression { + else_: "false".to_string(), + ..Default::default() + }, + enable_spam_filter: Expression { + else_: "is_empty(authenticated_as)".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageData { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked( + Property::AddAuthResultsHeader, + self.add_auth_results_header.into_value(), + ); + map.insert_unchecked(Property::AddDateHeader, self.add_date_header.into_value()); + map.insert_unchecked( + Property::AddDeliveredToHeader, + self.add_delivered_to_header.into_value(), + ); + map.insert_unchecked( + Property::AddMessageIdHeader, + self.add_message_id_header.into_value(), + ); + map.insert_unchecked( + Property::AddReceivedHeader, + self.add_received_header.into_value(), + ); + map.insert_unchecked( + Property::AddReceivedSpfHeader, + self.add_received_spf_header.into_value(), + ); + map.insert_unchecked( + Property::AddReturnPathHeader, + self.add_return_path_header.into_value(), + ); + map.insert_unchecked(Property::MaxMessages, self.max_messages.into_value()); + map.insert_unchecked( + Property::MaxReceivedHeaders, + self.max_received_headers.into_value(), + ); + map.insert_unchecked(Property::MaxMessageSize, self.max_message_size.into_value()); + map.insert_unchecked(Property::Script, self.script.into_value()); + map.insert_unchecked( + Property::EnableSpamFilter, + self.enable_spam_filter.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageData { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AddAuthResultsHeader) => { + self.add_auth_results_header.patch(pointer, value) + } + Some(Property::AddDateHeader) => self.add_date_header.patch(pointer, value), + Some(Property::AddDeliveredToHeader) => { + self.add_delivered_to_header.patch(pointer, value) + } + Some(Property::AddMessageIdHeader) => self.add_message_id_header.patch(pointer, value), + Some(Property::AddReceivedHeader) => self.add_received_header.patch(pointer, value), + Some(Property::AddReceivedSpfHeader) => { + self.add_received_spf_header.patch(pointer, value) + } + Some(Property::AddReturnPathHeader) => { + self.add_return_path_header.patch(pointer, value) + } + Some(Property::MaxMessages) => self.max_messages.patch(pointer, value), + Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value), + Some(Property::MaxMessageSize) => self.max_message_size.patch(pointer, value), + Some(Property::Script) => self.script.patch(pointer, value), + Some(Property::EnableSpamFilter) => self.enable_spam_filter.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageEhlo { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageEhlo; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.reject_non_fqdn; + value.validate(errors); + let value = &self.require; + value.validate(errors); + let value = &self.script; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageEhlo { + pub fn ctx_reject_non_fqdn(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.reject_non_fqdn, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }), + property: Property::RejectNonFqdn, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_require(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.require, + default: Some(Expression { + else_: "true".to_string(), + ..Default::default() + }), + property: Property::Require, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_script(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.script, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Script, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_reject_non_fqdn(), + self.ctx_require(), + self.ctx_script(), + ] + } +} + +impl Pickle for MtaStageEhlo { + fn pickle(&self, out: &mut Vec) { + self.reject_non_fqdn.pickle(out); + self.require.pickle(out); + self.script.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.reject_non_fqdn = Pickle::unpickle(stream)?; + this.require = Pickle::unpickle(stream)?; + this.script = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageEhlo { + fn default() -> Self { + Self { + reject_non_fqdn: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "true".to_string(), + }]), + }, + require: Expression { + else_: "true".to_string(), + ..Default::default() + }, + script: Expression { + else_: "false".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageEhlo { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::RejectNonFqdn, self.reject_non_fqdn.into_value()); + map.insert_unchecked(Property::Require, self.require.into_value()); + map.insert_unchecked(Property::Script, self.script.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageEhlo { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::RejectNonFqdn) => self.reject_non_fqdn.patch(pointer, value), + Some(Property::Require) => self.require.patch(pointer, value), + Some(Property::Script) => self.script.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageMail { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageMail; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.is_sender_allowed; + value.validate(errors); + let value = &self.rewrite; + value.validate(errors); + let value = &self.script; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageMail { + pub fn ctx_is_sender_allowed(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.is_sender_allowed, + default: Some(Expression { + else_: "!is_empty(authenticated_as) || !key_exists('spam-block', sender_domain)" + .to_string(), + match_: List::from_iter([]), + }), + property: Property::IsSenderAllowed, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_rewrite(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.rewrite, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Rewrite, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_script(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.script, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Script, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_is_sender_allowed(), + self.ctx_rewrite(), + self.ctx_script(), + ] + } +} + +impl Pickle for MtaStageMail { + fn pickle(&self, out: &mut Vec) { + self.is_sender_allowed.pickle(out); + self.rewrite.pickle(out); + self.script.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.is_sender_allowed = Pickle::unpickle(stream)?; + this.rewrite = Pickle::unpickle(stream)?; + this.script = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageMail { + fn default() -> Self { + Self { + is_sender_allowed: Expression { + else_: "!is_empty(authenticated_as) || !key_exists('spam-block', sender_domain)" + .to_string(), + match_: List::from_iter([]), + }, + rewrite: Expression { + else_: "false".to_string(), + ..Default::default() + }, + script: Expression { + else_: "false".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageMail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked( + Property::IsSenderAllowed, + self.is_sender_allowed.into_value(), + ); + map.insert_unchecked(Property::Rewrite, self.rewrite.into_value()); + map.insert_unchecked(Property::Script, self.script.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageMail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IsSenderAllowed) => self.is_sender_allowed.patch(pointer, value), + Some(Property::Rewrite) => self.rewrite.patch(pointer, value), + Some(Property::Script) => self.script.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaStageRcpt { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaStageRcpt; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_failures; + value.validate(errors); + let value = &self.wait_on_fail; + value.validate(errors); + let value = &self.max_recipients; + value.validate(errors); + let value = &self.allow_relaying; + value.validate(errors); + let value = &self.rewrite; + value.validate(errors); + let value = &self.script; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl MtaStageRcpt { + pub fn ctx_max_failures(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_failures, + default: Some(Expression { + else_: "5".to_string(), + ..Default::default() + }), + property: Property::MaxFailures, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_wait_on_fail(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.wait_on_fail, + default: Some(Expression { + else_: "5s".to_string(), + ..Default::default() + }), + property: Property::WaitOnFail, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_max_recipients(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_recipients, + default: Some(Expression { + else_: "100".to_string(), + ..Default::default() + }), + property: Property::MaxRecipients, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_allow_relaying(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.allow_relaying, + default: Some(Expression { + else_: "!is_empty(authenticated_as)".to_string(), + ..Default::default() + }), + property: Property::AllowRelaying, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_rewrite(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.rewrite, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Rewrite, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_script(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.script, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::Script, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_max_failures(), + self.ctx_wait_on_fail(), + self.ctx_max_recipients(), + self.ctx_allow_relaying(), + self.ctx_rewrite(), + self.ctx_script(), + ] + } +} + +impl Pickle for MtaStageRcpt { + fn pickle(&self, out: &mut Vec) { + self.max_failures.pickle(out); + self.wait_on_fail.pickle(out); + self.max_recipients.pickle(out); + self.allow_relaying.pickle(out); + self.rewrite.pickle(out); + self.script.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_failures = Pickle::unpickle(stream)?; + this.wait_on_fail = Pickle::unpickle(stream)?; + this.max_recipients = Pickle::unpickle(stream)?; + this.allow_relaying = Pickle::unpickle(stream)?; + this.rewrite = Pickle::unpickle(stream)?; + this.script = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaStageRcpt { + fn default() -> Self { + Self { + max_failures: Expression { + else_: "5".to_string(), + ..Default::default() + }, + wait_on_fail: Expression { + else_: "5s".to_string(), + ..Default::default() + }, + max_recipients: Expression { + else_: "100".to_string(), + ..Default::default() + }, + allow_relaying: Expression { + else_: "!is_empty(authenticated_as)".to_string(), + ..Default::default() + }, + rewrite: Expression { + else_: "false".to_string(), + ..Default::default() + }, + script: Expression { + else_: "false".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for MtaStageRcpt { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::MaxFailures, self.max_failures.into_value()); + map.insert_unchecked(Property::WaitOnFail, self.wait_on_fail.into_value()); + map.insert_unchecked(Property::MaxRecipients, self.max_recipients.into_value()); + map.insert_unchecked(Property::AllowRelaying, self.allow_relaying.into_value()); + map.insert_unchecked(Property::Rewrite, self.rewrite.into_value()); + map.insert_unchecked(Property::Script, self.script.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaStageRcpt { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxFailures) => self.max_failures.patch(pointer, value), + Some(Property::WaitOnFail) => self.wait_on_fail.patch(pointer, value), + Some(Property::MaxRecipients) => self.max_recipients.patch(pointer, value), + Some(Property::AllowRelaying) => self.allow_relaying.patch(pointer, value), + Some(Property::Rewrite) => self.rewrite.patch(pointer, value), + Some(Property::Script) => self.script.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaSts { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaSts; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.mx_hosts; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::MxHosts)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for MtaSts { + fn pickle(&self, out: &mut Vec) { + self.max_age.pickle(out); + self.mode.pickle(out); + self.mx_hosts.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_age = Pickle::unpickle(stream)?; + this.mode = Pickle::unpickle(stream)?; + this.mx_hosts = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaSts { + fn default() -> Self { + Self { + max_age: Duration::from_millis(604800000), + mode: PolicyEnforcement::Testing, + mx_hosts: Default::default(), + } + } +} + +impl IntoValue for MtaSts { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::MaxAge, self.max_age.into_value()); + map.insert_unchecked(Property::Mode, self.mode.into_value()); + map.insert_unchecked(Property::MxHosts, self.mx_hosts.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaSts { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxAge) => self.max_age.patch(pointer, value), + Some(Property::Mode) => self.mode.patch(pointer, value), + Some(Property::MxHosts) => self + .mx_hosts + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaTlsStrategy { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaTlsStrategy; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaTlsStrategy { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.allow_invalid_certs.pickle(out); + self.dane.pickle(out); + self.description.pickle(out); + self.mta_sts.pickle(out); + self.start_tls.pickle(out); + self.mta_sts_timeout.pickle(out); + self.tls_timeout.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.dane = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.mta_sts = Pickle::unpickle(stream)?; + this.start_tls = Pickle::unpickle(stream)?; + this.mta_sts_timeout = Pickle::unpickle(stream)?; + this.tls_timeout = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaTlsStrategy { + fn default() -> Self { + Self { + name: Default::default(), + allow_invalid_certs: false, + dane: MtaRequiredOrOptional::Optional, + description: Default::default(), + mta_sts: MtaRequiredOrOptional::Optional, + start_tls: MtaRequiredOrOptional::Optional, + mta_sts_timeout: Duration::from_millis(300000), + tls_timeout: Duration::from_millis(180000), + } + } +} + +impl IntoValue for MtaTlsStrategy { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::Dane, self.dane.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MtaSts, self.mta_sts.into_value()); + map.insert_unchecked(Property::StartTls, self.start_tls.into_value()); + map.insert_unchecked(Property::MtaStsTimeout, self.mta_sts_timeout.into_value()); + map.insert_unchecked(Property::TlsTimeout, self.tls_timeout.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaTlsStrategy { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::Dane) => self.dane.patch(pointer, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::MtaSts) => self.mta_sts.patch(pointer, value), + Some(Property::StartTls) => self.start_tls.patch(pointer, value), + Some(Property::MtaStsTimeout) => self.mta_sts_timeout.patch(pointer, value), + Some(Property::TlsTimeout) => self.tls_timeout.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for MtaVirtualQueue { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::MtaVirtualQueue; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if value.len() > 8 { + errors.push(ValidationError::max_length(Property::Name, 8)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.threads_per_node; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ThreadsPerNode, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for MtaVirtualQueue { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.threads_per_node.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.threads_per_node = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MtaVirtualQueue { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + threads_per_node: 25u64, + } + } +} + +impl IntoValue for MtaVirtualQueue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::ThreadsPerNode, self.threads_per_node.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MtaVirtualQueue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Trim]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::ThreadsPerNode) => self.threads_per_node.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MySqlSettings { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.host; + if value.is_empty() { + errors.push(ValidationError::required(Property::Host)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.database; + if value.is_empty() { + errors.push(ValidationError::required(Property::Database)); + } + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.auth_secret; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for MySqlSettings { + fn pickle(&self, out: &mut Vec) { + self.host.pickle(out); + self.port.pickle(out); + self.database.pickle(out); + self.auth_username.pickle(out); + self.auth_secret.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.database = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MySqlSettings { + fn default() -> Self { + Self { + host: Default::default(), + port: 3306u64, + database: "stalwart".to_string(), + auth_username: Some("stalwart".to_string()), + auth_secret: Default::default(), + } + } +} + +impl IntoValue for MySqlSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Database, self.database.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MySqlSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Database) => self + .database + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl MySqlStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.max_allowed_packet { + if *value > 1073741824 { + errors.push(ValidationError::max_value( + Property::MaxAllowedPacket, + 1073741824, + )); + } + if *value < 1024 { + errors.push(ValidationError::min_value(Property::MaxAllowedPacket, 1024)); + } + } + if let Some(value) = &self.pool_max_connections { + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1)); + } + } + if let Some(value) = &self.pool_min_connections { + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMinConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMinConnections, 1)); + } + } + let value = &self.read_replicas; + for value in value.values() { + value.validate(errors); + } + let value = &self.host; + if value.is_empty() { + errors.push(ValidationError::required(Property::Host)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.database; + if value.is_empty() { + errors.push(ValidationError::required(Property::Database)); + } + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.auth_secret; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for MySqlStore { + fn pickle(&self, out: &mut Vec) { + self.timeout.pickle(out); + self.use_tls.pickle(out); + self.allow_invalid_certs.pickle(out); + self.max_allowed_packet.pickle(out); + self.pool_max_connections.pickle(out); + self.pool_min_connections.pickle(out); + self.read_replicas.pickle(out); + self.host.pickle(out); + self.port.pickle(out); + self.database.pickle(out); + self.auth_username.pickle(out); + self.auth_secret.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.timeout = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.max_allowed_packet = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + this.pool_min_connections = Pickle::unpickle(stream)?; + this.read_replicas = Pickle::unpickle(stream)?; + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.database = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for MySqlStore { + fn default() -> Self { + Self { + timeout: Some(Duration::from_millis(15000)), + use_tls: false, + allow_invalid_certs: false, + max_allowed_packet: Default::default(), + pool_max_connections: Some(10u64), + pool_min_connections: Some(5u64), + read_replicas: Default::default(), + host: Default::default(), + port: 3306u64, + database: "stalwart".to_string(), + auth_username: Some("stalwart".to_string()), + auth_secret: Default::default(), + } + } +} + +impl IntoValue for MySqlStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked( + Property::MaxAllowedPacket, + self.max_allowed_packet.into_value(), + ); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + map.insert_unchecked( + Property::PoolMinConnections, + self.pool_min_connections.into_value(), + ); + map.insert_unchecked(Property::ReadReplicas, self.read_replicas.into_value()); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Database, self.database.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for MySqlStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::MaxAllowedPacket) => self.max_allowed_packet.patch(pointer, value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::PoolMinConnections) => self.pool_min_connections.patch(pointer, value), + Some(Property::ReadReplicas) => self.read_replicas.patch(pointer, value), + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Database) => self + .database + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl NatsCoordinator { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.addresses; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Addresses)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Addresses, 1)); + } + let value = &self.capacity_client; + if *value < 1 { + errors.push(ValidationError::min_value(Property::CapacityClient, 1)); + } + let value = &self.capacity_read_buffer; + if *value < 1 { + errors.push(ValidationError::min_value(Property::CapacityReadBuffer, 1)); + } + let value = &self.capacity_subscription; + if *value < 1 { + errors.push(ValidationError::min_value( + Property::CapacitySubscription, + 1, + )); + } + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.credentials; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for NatsCoordinator { + fn pickle(&self, out: &mut Vec) { + self.addresses.pickle(out); + self.max_reconnects.pickle(out); + self.timeout_connection.pickle(out); + self.timeout_request.pickle(out); + self.ping_interval.pickle(out); + self.capacity_client.pickle(out); + self.capacity_read_buffer.pickle(out); + self.capacity_subscription.pickle(out); + self.no_echo.pickle(out); + self.use_tls.pickle(out); + self.auth_secret.pickle(out); + self.auth_username.pickle(out); + self.credentials.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.addresses = Pickle::unpickle(stream)?; + this.max_reconnects = Pickle::unpickle(stream)?; + this.timeout_connection = Pickle::unpickle(stream)?; + this.timeout_request = Pickle::unpickle(stream)?; + this.ping_interval = Pickle::unpickle(stream)?; + this.capacity_client = Pickle::unpickle(stream)?; + this.capacity_read_buffer = Pickle::unpickle(stream)?; + this.capacity_subscription = Pickle::unpickle(stream)?; + this.no_echo = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.credentials = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for NatsCoordinator { + fn default() -> Self { + Self { + addresses: Map::new(vec!["127.0.0.1:4444".to_string()]), + max_reconnects: Default::default(), + timeout_connection: Duration::from_millis(5000), + timeout_request: Duration::from_millis(10000), + ping_interval: Duration::from_millis(60000), + capacity_client: 2048u64, + capacity_read_buffer: 65535u64, + capacity_subscription: 65536u64, + no_echo: true, + use_tls: false, + auth_secret: Default::default(), + auth_username: Some("stalwart".to_string()), + credentials: Default::default(), + } + } +} + +impl IntoValue for NatsCoordinator { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked(Property::Addresses, self.addresses.into_value()); + map.insert_unchecked(Property::MaxReconnects, self.max_reconnects.into_value()); + map.insert_unchecked( + Property::TimeoutConnection, + self.timeout_connection.into_value(), + ); + map.insert_unchecked(Property::TimeoutRequest, self.timeout_request.into_value()); + map.insert_unchecked(Property::PingInterval, self.ping_interval.into_value()); + map.insert_unchecked(Property::CapacityClient, self.capacity_client.into_value()); + map.insert_unchecked( + Property::CapacityReadBuffer, + self.capacity_read_buffer.into_value(), + ); + map.insert_unchecked( + Property::CapacitySubscription, + self.capacity_subscription.into_value(), + ); + map.insert_unchecked(Property::NoEcho, self.no_echo.into_value()); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::Credentials, self.credentials.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for NatsCoordinator { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Addresses) => self.addresses.patch(pointer, value), + Some(Property::MaxReconnects) => self.max_reconnects.patch(pointer, value), + Some(Property::TimeoutConnection) => self.timeout_connection.patch(pointer, value), + Some(Property::TimeoutRequest) => self.timeout_request.patch(pointer, value), + Some(Property::PingInterval) => self.ping_interval.patch(pointer, value), + Some(Property::CapacityClient) => self.capacity_client.patch(pointer, value), + Some(Property::CapacityReadBuffer) => self.capacity_read_buffer.patch(pointer, value), + Some(Property::CapacitySubscription) => { + self.capacity_subscription.patch(pointer, value) + } + Some(Property::NoEcho) => self.no_echo.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Credentials) => self.credentials.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for NetworkListener { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::NetworkListener; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.bind; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Bind, value)); + } + } + if value.len() < 1 { + errors.push(ValidationError::min_items(Property::Bind, 1)); + } + let value = &self.override_proxy_trusted_networks; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid( + Property::OverrideProxyTrustedNetworks, + value, + )); + } + } + if let Some(value) = &self.socket_backlog { + if *value < 1 { + errors.push(ValidationError::min_value(Property::SocketBacklog, 1)); + } + } + if let Some(value) = &self.socket_receive_buffer_size { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::SocketReceiveBufferSize, + 1, + )); + } + } + if let Some(value) = &self.socket_send_buffer_size { + if *value < 1 { + errors.push(ValidationError::min_value( + Property::SocketSendBufferSize, + 1, + )); + } + } + if let Some(value) = &self.socket_tos_v4 { + if *value < 1 { + errors.push(ValidationError::min_value(Property::SocketTosV4, 1)); + } + } + if let Some(value) = &self.socket_ttl { + if *value < 1 { + errors.push(ValidationError::min_value(Property::SocketTtl, 1)); + } + } + if let Some(value) = &self.max_connections { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxConnections, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for NetworkListener { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.bind.pickle(out); + self.protocol.pickle(out); + self.override_proxy_trusted_networks.pickle(out); + self.socket_backlog.pickle(out); + self.socket_no_delay.pickle(out); + self.socket_receive_buffer_size.pickle(out); + self.socket_reuse_address.pickle(out); + self.socket_reuse_port.pickle(out); + self.socket_send_buffer_size.pickle(out); + self.socket_tos_v4.pickle(out); + self.socket_ttl.pickle(out); + self.use_tls.pickle(out); + self.tls_disable_cipher_suites.pickle(out); + self.tls_disable_protocols.pickle(out); + self.tls_ignore_client_order.pickle(out); + self.tls_implicit.pickle(out); + self.tls_timeout.pickle(out); + self.max_connections.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.bind = Pickle::unpickle(stream)?; + this.protocol = Pickle::unpickle(stream)?; + this.override_proxy_trusted_networks = Pickle::unpickle(stream)?; + this.socket_backlog = Pickle::unpickle(stream)?; + this.socket_no_delay = Pickle::unpickle(stream)?; + this.socket_receive_buffer_size = Pickle::unpickle(stream)?; + this.socket_reuse_address = Pickle::unpickle(stream)?; + this.socket_reuse_port = Pickle::unpickle(stream)?; + this.socket_send_buffer_size = Pickle::unpickle(stream)?; + this.socket_tos_v4 = Pickle::unpickle(stream)?; + this.socket_ttl = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.tls_disable_cipher_suites = Pickle::unpickle(stream)?; + this.tls_disable_protocols = Pickle::unpickle(stream)?; + this.tls_ignore_client_order = Pickle::unpickle(stream)?; + this.tls_implicit = Pickle::unpickle(stream)?; + this.tls_timeout = Pickle::unpickle(stream)?; + this.max_connections = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for NetworkListener { + fn default() -> Self { + Self { + name: Default::default(), + bind: Default::default(), + protocol: NetworkListenerProtocol::Smtp, + override_proxy_trusted_networks: Default::default(), + socket_backlog: Some(1024u64), + socket_no_delay: true, + socket_receive_buffer_size: Default::default(), + socket_reuse_address: true, + socket_reuse_port: true, + socket_send_buffer_size: Default::default(), + socket_tos_v4: Default::default(), + socket_ttl: Default::default(), + use_tls: true, + tls_disable_cipher_suites: Default::default(), + tls_disable_protocols: Default::default(), + tls_ignore_client_order: true, + tls_implicit: false, + tls_timeout: Some(Duration::from_millis(60000)), + max_connections: Some(8192u64), + } + } +} + +impl IntoValue for NetworkListener { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(21); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Bind, self.bind.into_value()); + map.insert_unchecked(Property::Protocol, self.protocol.into_value()); + map.insert_unchecked( + Property::OverrideProxyTrustedNetworks, + self.override_proxy_trusted_networks.into_value(), + ); + map.insert_unchecked(Property::SocketBacklog, self.socket_backlog.into_value()); + map.insert_unchecked(Property::SocketNoDelay, self.socket_no_delay.into_value()); + map.insert_unchecked( + Property::SocketReceiveBufferSize, + self.socket_receive_buffer_size.into_value(), + ); + map.insert_unchecked( + Property::SocketReuseAddress, + self.socket_reuse_address.into_value(), + ); + map.insert_unchecked( + Property::SocketReusePort, + self.socket_reuse_port.into_value(), + ); + map.insert_unchecked( + Property::SocketSendBufferSize, + self.socket_send_buffer_size.into_value(), + ); + map.insert_unchecked(Property::SocketTosV4, self.socket_tos_v4.into_value()); + map.insert_unchecked(Property::SocketTtl, self.socket_ttl.into_value()); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked( + Property::TlsDisableCipherSuites, + self.tls_disable_cipher_suites.into_value(), + ); + map.insert_unchecked( + Property::TlsDisableProtocols, + self.tls_disable_protocols.into_value(), + ); + map.insert_unchecked( + Property::TlsIgnoreClientOrder, + self.tls_ignore_client_order.into_value(), + ); + map.insert_unchecked(Property::TlsImplicit, self.tls_implicit.into_value()); + map.insert_unchecked(Property::TlsTimeout, self.tls_timeout.into_value()); + map.insert_unchecked(Property::MaxConnections, self.max_connections.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for NetworkListener { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer.assert_read_only()?, value), + Some(Property::Bind) => self + .bind + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Protocol) => self.protocol.patch(pointer, value), + Some(Property::OverrideProxyTrustedNetworks) => self + .override_proxy_trusted_networks + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::SocketBacklog) => self.socket_backlog.patch(pointer, value), + Some(Property::SocketNoDelay) => self.socket_no_delay.patch(pointer, value), + Some(Property::SocketReceiveBufferSize) => { + self.socket_receive_buffer_size.patch(pointer, value) + } + Some(Property::SocketReuseAddress) => self.socket_reuse_address.patch(pointer, value), + Some(Property::SocketReusePort) => self.socket_reuse_port.patch(pointer, value), + Some(Property::SocketSendBufferSize) => { + self.socket_send_buffer_size.patch(pointer, value) + } + Some(Property::SocketTosV4) => self.socket_tos_v4.patch(pointer, value), + Some(Property::SocketTtl) => self.socket_ttl.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::TlsDisableCipherSuites) => { + self.tls_disable_cipher_suites.patch(pointer, value) + } + Some(Property::TlsDisableProtocols) => self.tls_disable_protocols.patch(pointer, value), + Some(Property::TlsIgnoreClientOrder) => { + self.tls_ignore_client_order.patch(pointer, value) + } + Some(Property::TlsImplicit) => self.tls_implicit.patch(pointer, value), + Some(Property::TlsTimeout) => self.tls_timeout.patch(pointer, value), + Some(Property::MaxConnections) => self.max_connections.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for OAuthClient { + const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::OAuthClient; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.client_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::ClientId)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.contacts; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Contacts)); + } + } + if let Some(value) = &self.secret { + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.redirect_uris; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::RedirectUris)); + } + } + if let Some(value) = &self.logo { + if value.is_empty() { + errors.push(ValidationError::required(Property::Logo)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::ClientId, &self.client_id); + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + for value in self.contacts.iter() { + i.text(Property::Text, value); + } + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for OAuthClient { + fn pickle(&self, out: &mut Vec) { + self.client_id.pickle(out); + self.description.pickle(out); + self.contacts.pickle(out); + self.secret.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + self.member_tenant_id.pickle(out); + self.redirect_uris.pickle(out); + self.logo.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.client_id = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.contacts = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.redirect_uris = Pickle::unpickle(stream)?; + this.logo = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for OAuthClient { + fn default() -> Self { + Self { + client_id: Default::default(), + description: Default::default(), + contacts: Default::default(), + secret: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + member_tenant_id: Default::default(), + redirect_uris: Default::default(), + logo: Default::default(), + } + } +} + +impl IntoValue for OAuthClient { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::ClientId, self.client_id.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Contacts, self.contacts.into_value()); + if self.secret.is_some() { + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + } + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::RedirectUris, self.redirect_uris.into_value()); + map.insert_unchecked(Property::Logo, self.logo.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for OAuthClient { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ClientId) => self + .client_id + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Contacts) => self + .contacts + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::RedirectUris) => self.redirect_uris.patch(pointer, value), + Some(Property::Logo) => self.logo.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl OidcDirectory { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.issuer_url; + if value.is_empty() { + errors.push(ValidationError::required(Property::IssuerUrl)); + } + if let Some(value) = &self.require_audience { + if value.is_empty() { + errors.push(ValidationError::required(Property::RequireAudience)); + } + } + let value = &self.require_scopes; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::RequireScopes)); + } + } + let value = &self.claim_username; + if value.is_empty() { + errors.push(ValidationError::required(Property::ClaimUsername)); + } + if let Some(value) = &self.username_domain { + if value.is_empty() { + errors.push(ValidationError::required(Property::UsernameDomain)); + } + } + if let Some(value) = &self.claim_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::ClaimName)); + } + } + if let Some(value) = &self.claim_groups { + if value.is_empty() { + errors.push(ValidationError::required(Property::ClaimGroups)); + } + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for OidcDirectory { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.issuer_url.pickle(out); + self.require_audience.pickle(out); + self.require_scopes.pickle(out); + self.claim_username.pickle(out); + self.username_domain.pickle(out); + self.claim_name.pickle(out); + self.claim_groups.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.issuer_url = Pickle::unpickle(stream)?; + this.require_audience = Pickle::unpickle(stream)?; + this.require_scopes = Pickle::unpickle(stream)?; + this.claim_username = Pickle::unpickle(stream)?; + this.username_domain = Pickle::unpickle(stream)?; + this.claim_name = Pickle::unpickle(stream)?; + this.claim_groups = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for OidcDirectory { + fn default() -> Self { + Self { + description: Default::default(), + issuer_url: Default::default(), + require_audience: Some("stalwart".to_string()), + require_scopes: Map::new(vec!["openid".to_string(), "email".to_string()]), + claim_username: "preferred_username".to_string(), + username_domain: Default::default(), + claim_name: Some("name".to_string()), + claim_groups: Default::default(), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for OidcDirectory { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::IssuerUrl, self.issuer_url.into_value()); + map.insert_unchecked( + Property::RequireAudience, + self.require_audience.into_value(), + ); + map.insert_unchecked(Property::RequireScopes, self.require_scopes.into_value()); + map.insert_unchecked(Property::ClaimUsername, self.claim_username.into_value()); + map.insert_unchecked(Property::UsernameDomain, self.username_domain.into_value()); + map.insert_unchecked(Property::ClaimName, self.claim_name.into_value()); + map.insert_unchecked(Property::ClaimGroups, self.claim_groups.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for OidcDirectory { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::IssuerUrl) => self + .issuer_url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::RequireAudience) => self + .require_audience + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::RequireScopes) => self + .require_scopes + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ClaimUsername) => self + .claim_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::UsernameDomain) => self.username_domain.patch(pointer, value), + Some(Property::ClaimName) => self + .claim_name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ClaimGroups) => self.claim_groups.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for OidcProvider { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::OidcProvider; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.auth_code_max_attempts; + if *value < 1 { + errors.push(ValidationError::min_value(Property::AuthCodeMaxAttempts, 1)); + } + if *value > 1000 { + errors.push(ValidationError::max_value( + Property::AuthCodeMaxAttempts, + 1000, + )); + } + let value = &self.encryption_key; + value.validate(errors); + let value = &self.signature_key; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for OidcProvider { + fn pickle(&self, out: &mut Vec) { + self.auth_code_max_attempts.pickle(out); + self.anonymous_client_registration.pickle(out); + self.require_client_registration.pickle(out); + self.auth_code_expiry.pickle(out); + self.refresh_token_expiry.pickle(out); + self.refresh_token_renewal.pickle(out); + self.access_token_expiry.pickle(out); + self.user_code_expiry.pickle(out); + self.id_token_expiry.pickle(out); + self.encryption_key.pickle(out); + self.signature_algorithm.pickle(out); + self.signature_key.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.auth_code_max_attempts = Pickle::unpickle(stream)?; + this.anonymous_client_registration = Pickle::unpickle(stream)?; + this.require_client_registration = Pickle::unpickle(stream)?; + this.auth_code_expiry = Pickle::unpickle(stream)?; + this.refresh_token_expiry = Pickle::unpickle(stream)?; + this.refresh_token_renewal = Pickle::unpickle(stream)?; + this.access_token_expiry = Pickle::unpickle(stream)?; + this.user_code_expiry = Pickle::unpickle(stream)?; + this.id_token_expiry = Pickle::unpickle(stream)?; + this.encryption_key = Pickle::unpickle(stream)?; + this.signature_algorithm = Pickle::unpickle(stream)?; + this.signature_key = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for OidcProvider { + fn default() -> Self { + Self { + auth_code_max_attempts: 3u64, + anonymous_client_registration: false, + require_client_registration: false, + auth_code_expiry: Duration::from_millis(600000), + refresh_token_expiry: Duration::from_millis(2592000000), + refresh_token_renewal: Duration::from_millis(345600000), + access_token_expiry: Duration::from_millis(3600000), + user_code_expiry: Duration::from_millis(1800000), + id_token_expiry: Duration::from_millis(900000), + encryption_key: Default::default(), + signature_algorithm: JwtSignatureAlgorithm::Hs256, + signature_key: Default::default(), + } + } +} + +impl IntoValue for OidcProvider { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked( + Property::AuthCodeMaxAttempts, + self.auth_code_max_attempts.into_value(), + ); + map.insert_unchecked( + Property::AnonymousClientRegistration, + self.anonymous_client_registration.into_value(), + ); + map.insert_unchecked( + Property::RequireClientRegistration, + self.require_client_registration.into_value(), + ); + map.insert_unchecked(Property::AuthCodeExpiry, self.auth_code_expiry.into_value()); + map.insert_unchecked( + Property::RefreshTokenExpiry, + self.refresh_token_expiry.into_value(), + ); + map.insert_unchecked( + Property::RefreshTokenRenewal, + self.refresh_token_renewal.into_value(), + ); + map.insert_unchecked( + Property::AccessTokenExpiry, + self.access_token_expiry.into_value(), + ); + map.insert_unchecked(Property::UserCodeExpiry, self.user_code_expiry.into_value()); + map.insert_unchecked(Property::IdTokenExpiry, self.id_token_expiry.into_value()); + map.insert_unchecked(Property::EncryptionKey, self.encryption_key.into_value()); + map.insert_unchecked( + Property::SignatureAlgorithm, + self.signature_algorithm.into_value(), + ); + map.insert_unchecked(Property::SignatureKey, self.signature_key.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for OidcProvider { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AuthCodeMaxAttempts) => { + self.auth_code_max_attempts.patch(pointer, value) + } + Some(Property::AnonymousClientRegistration) => { + self.anonymous_client_registration.patch(pointer, value) + } + Some(Property::RequireClientRegistration) => { + self.require_client_registration.patch(pointer, value) + } + Some(Property::AuthCodeExpiry) => self.auth_code_expiry.patch(pointer, value), + Some(Property::RefreshTokenExpiry) => self.refresh_token_expiry.patch(pointer, value), + Some(Property::RefreshTokenRenewal) => self.refresh_token_renewal.patch(pointer, value), + Some(Property::AccessTokenExpiry) => self.access_token_expiry.patch(pointer, value), + Some(Property::UserCodeExpiry) => self.user_code_expiry.patch(pointer, value), + Some(Property::IdTokenExpiry) => self.id_token_expiry.patch(pointer, value), + Some(Property::EncryptionKey) => self.encryption_key.patch(pointer, value), + Some(Property::SignatureAlgorithm) => self.signature_algorithm.patch(pointer, value), + Some(Property::SignatureKey) => self.signature_key.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl OtpAuth { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.otp_code { + if value.is_empty() { + errors.push(ValidationError::required(Property::OtpCode)); + } + } + if let Some(value) = &self.otp_url { + if value.is_empty() { + errors.push(ValidationError::required(Property::OtpUrl)); + } + } + errors.len() == neb + } +} + +impl Pickle for OtpAuth { + fn pickle(&self, out: &mut Vec) { + self.otp_code.pickle(out); + self.otp_url.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.otp_code = Pickle::unpickle(stream)?; + this.otp_url = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for OtpAuth { + fn default() -> Self { + Self { + otp_code: Default::default(), + otp_url: Default::default(), + } + } +} + +impl IntoValue for OtpAuth { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + if self.otp_code.is_some() { + map.insert_unchecked(Property::OtpCode, JmapValue::Str(MASKED_PASSWORD.into())); + } + if self.otp_url.is_some() { + map.insert_unchecked(Property::OtpUrl, JmapValue::Str(MASKED_PASSWORD.into())); + } + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for OtpAuth { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::OtpCode) => self.otp_code.patch(pointer, value), + Some(Property::OtpUrl) => self.otp_url.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl PasswordCredential { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.credential_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CredentialId, value)); + } + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + if let Some(value) = &self.otp_auth { + if value.is_empty() { + errors.push(ValidationError::required(Property::OtpAuth)); + } + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + let value = &self.allowed_ips; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::AllowedIps, value)); + } + } + errors.len() == neb + } +} + +impl Pickle for PasswordCredential { + fn pickle(&self, out: &mut Vec) { + self.credential_id.pickle(out); + self.secret.pickle(out); + self.otp_auth.pickle(out); + self.expires_at.pickle(out); + self.allowed_ips.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.credential_id = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.otp_auth = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.allowed_ips = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PasswordCredential { + fn default() -> Self { + Self { + credential_id: Default::default(), + secret: Default::default(), + otp_auth: Default::default(), + expires_at: Default::default(), + allowed_ips: Default::default(), + } + } +} + +impl IntoValue for PasswordCredential { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::CredentialId, self.credential_id.into_value()); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + if self.otp_auth.is_some() { + map.insert_unchecked(Property::OtpAuth, JmapValue::Str(MASKED_PASSWORD.into())); + } + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PasswordCredential { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CredentialId) => pointer.assert_server_set(), + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::OtpAuth) => self.otp_auth.patch(pointer, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Permissions { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Permissions::Inherit => true, + Permissions::Merge(inner) => inner.validate(errors), + Permissions::Replace(inner) => inner.validate(errors), + } + } +} + +impl Default for Permissions { + fn default() -> Self { + Permissions::Inherit + } +} + +impl Pickle for Permissions { + fn pickle(&self, out: &mut Vec) { + match self { + Permissions::Inherit => { + 0u16.pickle(out); + } + Permissions::Merge(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Permissions::Replace(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(Permissions::Inherit), + 1 => Pickle::unpickle(stream).map(Permissions::Merge), + 2 => Pickle::unpickle(stream).map(Permissions::Replace), + _ => None, + } + } +} + +impl IntoValue for Permissions { + fn into_value(self) -> JmapValue<'static> { + match self { + Permissions::Inherit => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Inherit".into())); + JmapValue::Object(obj) + } + Permissions::Merge(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Merge".into())); + obj + } + Permissions::Replace(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Replace".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Permissions { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + PermissionsType::Inherit => *self = Permissions::Inherit, + PermissionsType::Merge => *self = Permissions::Merge(Default::default()), + PermissionsType::Replace => *self = Permissions::Replace(Default::default()), + } + } + match self { + Permissions::Inherit => pointer.assert_eof(), + Permissions::Merge(inner) => inner.patch(pointer, value), + Permissions::Replace(inner) => inner.patch(pointer, value), + } + } +} + +impl Permissions { + pub fn object_type(&self) -> PermissionsType { + match self { + Permissions::Inherit => PermissionsType::Inherit, + Permissions::Merge(_) => PermissionsType::Merge, + Permissions::Replace(_) => PermissionsType::Replace, + } + } +} + +impl PermissionsList { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for PermissionsList { + fn pickle(&self, out: &mut Vec) { + self.enabled_permissions.pickle(out); + self.disabled_permissions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enabled_permissions = Pickle::unpickle(stream)?; + this.disabled_permissions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PermissionsList { + fn default() -> Self { + Self { + enabled_permissions: Default::default(), + disabled_permissions: Default::default(), + } + } +} + +impl IntoValue for PermissionsList { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked( + Property::EnabledPermissions, + self.enabled_permissions.into_value(), + ); + map.insert_unchecked( + Property::DisabledPermissions, + self.disabled_permissions.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PermissionsList { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::EnabledPermissions) => self.enabled_permissions.patch(pointer, value), + Some(Property::DisabledPermissions) => self.disabled_permissions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl PostgreSqlSettings { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.host; + if value.is_empty() { + errors.push(ValidationError::required(Property::Host)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.database; + if value.is_empty() { + errors.push(ValidationError::required(Property::Database)); + } + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.options { + if value.is_empty() { + errors.push(ValidationError::required(Property::Options)); + } + } + errors.len() == neb + } +} + +impl Pickle for PostgreSqlSettings { + fn pickle(&self, out: &mut Vec) { + self.host.pickle(out); + self.port.pickle(out); + self.database.pickle(out); + self.auth_username.pickle(out); + self.auth_secret.pickle(out); + self.options.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.database = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + this.options = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PostgreSqlSettings { + fn default() -> Self { + Self { + host: Default::default(), + port: 5432u64, + database: "stalwart".to_string(), + auth_username: Some("stalwart".to_string()), + auth_secret: Default::default(), + options: Default::default(), + } + } +} + +impl IntoValue for PostgreSqlSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Database, self.database.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::Options, self.options.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PostgreSqlSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Database) => self + .database + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::Options) => self + .options + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl PostgreSqlStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.pool_max_connections { + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1)); + } + } + let value = &self.read_replicas; + for value in value.values() { + value.validate(errors); + } + let value = &self.host; + if value.is_empty() { + errors.push(ValidationError::required(Property::Host)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::Port, 1)); + } + let value = &self.database; + if value.is_empty() { + errors.push(ValidationError::required(Property::Database)); + } + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.options { + if value.is_empty() { + errors.push(ValidationError::required(Property::Options)); + } + } + errors.len() == neb + } +} + +impl Pickle for PostgreSqlStore { + fn pickle(&self, out: &mut Vec) { + self.timeout.pickle(out); + self.use_tls.pickle(out); + self.allow_invalid_certs.pickle(out); + self.pool_max_connections.pickle(out); + self.pool_recycling_method.pickle(out); + self.read_replicas.pickle(out); + self.host.pickle(out); + self.port.pickle(out); + self.database.pickle(out); + self.auth_username.pickle(out); + self.auth_secret.pickle(out); + self.options.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.timeout = Pickle::unpickle(stream)?; + this.use_tls = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + this.pool_recycling_method = Pickle::unpickle(stream)?; + this.read_replicas = Pickle::unpickle(stream)?; + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.database = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + this.options = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PostgreSqlStore { + fn default() -> Self { + Self { + timeout: Some(Duration::from_millis(15000)), + use_tls: false, + allow_invalid_certs: false, + pool_max_connections: Some(10u64), + pool_recycling_method: PostgreSqlRecyclingMethod::Fast, + read_replicas: Default::default(), + host: Default::default(), + port: 5432u64, + database: "stalwart".to_string(), + auth_username: Some("stalwart".to_string()), + auth_secret: Default::default(), + options: Default::default(), + } + } +} + +impl IntoValue for PostgreSqlStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::UseTls, self.use_tls.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + map.insert_unchecked( + Property::PoolRecyclingMethod, + self.pool_recycling_method.into_value(), + ); + map.insert_unchecked(Property::ReadReplicas, self.read_replicas.into_value()); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Database, self.database.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::Options, self.options.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PostgreSqlStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::UseTls) => self.use_tls.patch(pointer, value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::PoolRecyclingMethod) => self.pool_recycling_method.patch(pointer, value), + Some(Property::ReadReplicas) => self.read_replicas.patch(pointer, value), + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Database) => self + .database + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::Options) => self + .options + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for PublicKey { + const FLAGS: u64 = OBJ_FILTER_ACCOUNT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::PublicKey; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.key; + if value.is_empty() { + errors.push(ValidationError::required(Property::Key)); + } + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + let value = &self.email_addresses; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::EmailAddresses)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.search(Property::AccountId, &self.account_id); + } +} + +impl Pickle for PublicKey { + fn pickle(&self, out: &mut Vec) { + self.account_id.pickle(out); + self.key.pickle(out); + self.description.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + self.email_addresses.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.account_id = Pickle::unpickle(stream)?; + this.key = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.email_addresses = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PublicKey { + fn default() -> Self { + Self { + account_id: Default::default(), + key: Default::default(), + description: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + email_addresses: Default::default(), + } + } +} + +impl IntoValue for PublicKey { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::EmailAddresses, self.email_addresses.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PublicKey { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::Key) => self + .key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::EmailAddresses) => self + .email_addresses + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl PublicText { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + PublicText::Text(inner) => inner.validate(errors), + PublicText::EnvironmentVariable(inner) => inner.validate(errors), + PublicText::File(inner) => inner.validate(errors), + } + } +} + +impl Default for PublicText { + fn default() -> Self { + PublicText::Text(Default::default()) + } +} + +impl Pickle for PublicText { + fn pickle(&self, out: &mut Vec) { + match self { + PublicText::Text(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + PublicText::EnvironmentVariable(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + PublicText::File(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(PublicText::Text), + 1 => Pickle::unpickle(stream).map(PublicText::EnvironmentVariable), + 2 => Pickle::unpickle(stream).map(PublicText::File), + _ => None, + } + } +} + +impl IntoValue for PublicText { + fn into_value(self) -> JmapValue<'static> { + match self { + PublicText::Text(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Text".into())); + obj + } + PublicText::EnvironmentVariable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into())); + obj + } + PublicText::File(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("File".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for PublicText { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + PublicTextType::Text => *self = PublicText::Text(Default::default()), + PublicTextType::EnvironmentVariable => { + *self = PublicText::EnvironmentVariable(Default::default()) + } + PublicTextType::File => *self = PublicText::File(Default::default()), + } + } + match self { + PublicText::Text(inner) => inner.patch(pointer, value), + PublicText::EnvironmentVariable(inner) => inner.patch(pointer, value), + PublicText::File(inner) => inner.patch(pointer, value), + } + } +} + +impl PublicText { + pub fn object_type(&self) -> PublicTextType { + match self { + PublicText::Text(_) => PublicTextType::Text, + PublicText::EnvironmentVariable(_) => PublicTextType::EnvironmentVariable, + PublicText::File(_) => PublicTextType::File, + } + } +} + +impl PublicTextValue { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + if value.is_empty() { + errors.push(ValidationError::required(Property::Value)); + } + errors.len() == neb + } +} + +impl Pickle for PublicTextValue { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for PublicTextValue { + fn default() -> Self { + Self { + value: Default::default(), + } + } +} + +impl IntoValue for PublicTextValue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for PublicTextValue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl QueueExpiry { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + QueueExpiry::Ttl(inner) => inner.validate(errors), + QueueExpiry::Attempts(inner) => inner.validate(errors), + } + } +} + +impl Default for QueueExpiry { + fn default() -> Self { + QueueExpiry::Ttl(Default::default()) + } +} + +impl Pickle for QueueExpiry { + fn pickle(&self, out: &mut Vec) { + match self { + QueueExpiry::Ttl(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + QueueExpiry::Attempts(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(QueueExpiry::Ttl), + 1 => Pickle::unpickle(stream).map(QueueExpiry::Attempts), + _ => None, + } + } +} + +impl IntoValue for QueueExpiry { + fn into_value(self) -> JmapValue<'static> { + match self { + QueueExpiry::Ttl(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ttl".into())); + obj + } + QueueExpiry::Attempts(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Attempts".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for QueueExpiry { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + QueueExpiryType::Ttl => *self = QueueExpiry::Ttl(Default::default()), + QueueExpiryType::Attempts => *self = QueueExpiry::Attempts(Default::default()), + } + } + match self { + QueueExpiry::Ttl(inner) => inner.patch(pointer, value), + QueueExpiry::Attempts(inner) => inner.patch(pointer, value), + } + } +} + +impl QueueExpiry { + pub fn object_type(&self) -> QueueExpiryType { + match self { + QueueExpiry::Ttl(_) => QueueExpiryType::Ttl, + QueueExpiry::Attempts(_) => QueueExpiryType::Attempts, + } + } +} + +impl QueueExpiryAttempts { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for QueueExpiryAttempts { + fn pickle(&self, out: &mut Vec) { + self.expires_attempts.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.expires_attempts = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for QueueExpiryAttempts { + fn default() -> Self { + Self { + expires_attempts: 0u64, + } + } +} + +impl IntoValue for QueueExpiryAttempts { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked( + Property::ExpiresAttempts, + self.expires_attempts.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for QueueExpiryAttempts { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ExpiresAttempts) => self.expires_attempts.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl QueueExpiryTtl { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.expires_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + errors.len() == neb + } +} + +impl Pickle for QueueExpiryTtl { + fn pickle(&self, out: &mut Vec) { + self.expires_at.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.expires_at = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for QueueExpiryTtl { + fn default() -> Self { + Self { + expires_at: Default::default(), + } + } +} + +impl IntoValue for QueueExpiryTtl { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for QueueExpiryTtl { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for QueuedMessage { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::QueuedMessage; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.next_retry { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NextRetry, value)); + } + } + if let Some(value) = &self.next_notify { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NextNotify, value)); + } + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + let value = &self.return_path; + if value.is_empty() { + errors.push(ValidationError::required(Property::ReturnPath)); + } + let value = &self.recipients; + for value in value.values() { + value.validate(errors); + } + let value = &self.received_from_ip; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivedFromIp, value)); + } + let value = &self.received_via_port; + if *value < 1 { + errors.push(ValidationError::min_value(Property::ReceivedViaPort, 1)); + } + if *value > 65535 { + errors.push(ValidationError::max_value(Property::ReceivedViaPort, 65535)); + } + if let Some(value) = &self.env_id { + if value.is_empty() { + errors.push(ValidationError::required(Property::EnvId)); + } + } + let value = &self.priority; + if *value < (-100) { + errors.push(ValidationError::min_value(Property::Priority, -100)); + } + if *value > (100) { + errors.push(ValidationError::max_value(Property::Priority, 100)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for QueuedMessage { + fn pickle(&self, out: &mut Vec) { + self.created_at.pickle(out); + self.next_retry.pickle(out); + self.next_notify.pickle(out); + self.blob_id.pickle(out); + self.return_path.pickle(out); + self.recipients.pickle(out); + self.received_from_ip.pickle(out); + self.received_via_port.pickle(out); + self.flags.pickle(out); + self.env_id.pickle(out); + self.priority.pickle(out); + self.size.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.created_at = Pickle::unpickle(stream)?; + this.next_retry = Pickle::unpickle(stream)?; + this.next_notify = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + this.return_path = Pickle::unpickle(stream)?; + this.recipients = Pickle::unpickle(stream)?; + this.received_from_ip = Pickle::unpickle(stream)?; + this.received_via_port = Pickle::unpickle(stream)?; + this.flags = Pickle::unpickle(stream)?; + this.env_id = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + this.size = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for QueuedMessage { + fn default() -> Self { + Self { + created_at: Default::default(), + next_retry: Default::default(), + next_notify: Default::default(), + blob_id: Default::default(), + return_path: Default::default(), + recipients: Default::default(), + received_from_ip: Default::default(), + received_via_port: 25u64, + flags: Default::default(), + env_id: Default::default(), + priority: 0i64, + size: 0u64, + } + } +} + +impl IntoValue for QueuedMessage { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::NextRetry, self.next_retry.into_value()); + map.insert_unchecked(Property::NextNotify, self.next_notify.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + map.insert_unchecked(Property::ReturnPath, self.return_path.into_value()); + map.insert_unchecked(Property::Recipients, self.recipients.into_value()); + map.insert_unchecked(Property::ReceivedFromIp, self.received_from_ip.into_value()); + map.insert_unchecked( + Property::ReceivedViaPort, + self.received_via_port.into_value(), + ); + map.insert_unchecked(Property::Flags, self.flags.into_value()); + map.insert_unchecked(Property::EnvId, self.env_id.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + map.insert_unchecked(Property::Size, self.size.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for QueuedMessage { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::NextRetry) => self.next_retry.patch(pointer, value), + Some(Property::NextNotify) => pointer.assert_server_set(), + Some(Property::BlobId) => pointer.assert_server_set(), + Some(Property::ReturnPath) => pointer.assert_server_set(), + Some(Property::Recipients) => self.recipients.patch(pointer, value), + Some(Property::ReceivedFromIp) => pointer.assert_server_set(), + Some(Property::ReceivedViaPort) => pointer.assert_server_set(), + Some(Property::Flags) => pointer.assert_server_set(), + Some(Property::EnvId) => self.env_id.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Size) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl QueuedRecipient { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.retry_due; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::RetryDue, value)); + } + let value = &self.notify_due; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::NotifyDue, value)); + } + let value = &self.expires; + value.validate(errors); + let value = &self.queue_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::QueueName)); + } + if value.len() > 8 { + errors.push(ValidationError::max_length(Property::QueueName, 8)); + } + let value = &self.status; + value.validate(errors); + if let Some(value) = &self.orcpt { + if value.is_empty() { + errors.push(ValidationError::required(Property::Orcpt)); + } + } + errors.len() == neb + } +} + +impl Pickle for QueuedRecipient { + fn pickle(&self, out: &mut Vec) { + self.retry_count.pickle(out); + self.retry_due.pickle(out); + self.notify_count.pickle(out); + self.notify_due.pickle(out); + self.expires.pickle(out); + self.queue_name.pickle(out); + self.status.pickle(out); + self.flags.pickle(out); + self.orcpt.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.retry_count = Pickle::unpickle(stream)?; + this.retry_due = Pickle::unpickle(stream)?; + this.notify_count = Pickle::unpickle(stream)?; + this.notify_due = Pickle::unpickle(stream)?; + this.expires = Pickle::unpickle(stream)?; + this.queue_name = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + this.flags = Pickle::unpickle(stream)?; + this.orcpt = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for QueuedRecipient { + fn default() -> Self { + Self { + retry_count: 0u64, + retry_due: Default::default(), + notify_count: 0u64, + notify_due: Default::default(), + expires: Default::default(), + queue_name: Default::default(), + status: Default::default(), + flags: Default::default(), + orcpt: Default::default(), + } + } +} + +impl IntoValue for QueuedRecipient { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::RetryCount, self.retry_count.into_value()); + map.insert_unchecked(Property::RetryDue, self.retry_due.into_value()); + map.insert_unchecked(Property::NotifyCount, self.notify_count.into_value()); + map.insert_unchecked(Property::NotifyDue, self.notify_due.into_value()); + map.insert_unchecked(Property::Expires, self.expires.into_value()); + map.insert_unchecked(Property::QueueName, self.queue_name.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + map.insert_unchecked(Property::Flags, self.flags.into_value()); + map.insert_unchecked(Property::Orcpt, self.orcpt.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for QueuedRecipient { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::RetryCount) => self.retry_count.patch(pointer, value), + Some(Property::RetryDue) => self.retry_due.patch(pointer, value), + Some(Property::NotifyCount) => self.notify_count.patch(pointer, value), + Some(Property::NotifyDue) => self.notify_due.patch(pointer, value), + Some(Property::Expires) => self.expires.patch(pointer, value), + Some(Property::QueueName) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Flags) => pointer.assert_server_set(), + Some(Property::Orcpt) => self.orcpt.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Rate { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.count; + if *value < 1 { + errors.push(ValidationError::min_value(Property::Count, 1)); + } + if *value > 1000000 { + errors.push(ValidationError::max_value(Property::Count, 1000000)); + } + let value = &self.period; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Period, value)); + } + if *value < Duration::from_millis(1) { + errors.push(ValidationError::min_value(Property::Period, 1)); + } + errors.len() == neb + } +} + +impl Pickle for Rate { + fn pickle(&self, out: &mut Vec) { + self.count.pickle(out); + self.period.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.count = Pickle::unpickle(stream)?; + this.period = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Rate { + fn default() -> Self { + Self { + count: 0u64, + period: Duration::from_millis(0), + } + } +} + +impl IntoValue for Rate { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Count, self.count.into_value()); + map.insert_unchecked(Property::Period, self.period.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Rate { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Count) => self.count.patch(pointer, value), + Some(Property::Period) => self.period.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl RecipientStatus { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + RecipientStatus::Scheduled => true, + RecipientStatus::Completed(inner) => inner.validate(errors), + RecipientStatus::TemporaryFailure(inner) => inner.validate(errors), + RecipientStatus::PermanentFailure(inner) => inner.validate(errors), + } + } +} + +impl Default for RecipientStatus { + fn default() -> Self { + RecipientStatus::Scheduled + } +} + +impl Pickle for RecipientStatus { + fn pickle(&self, out: &mut Vec) { + match self { + RecipientStatus::Scheduled => { + 0u16.pickle(out); + } + RecipientStatus::Completed(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + RecipientStatus::TemporaryFailure(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + RecipientStatus::PermanentFailure(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(RecipientStatus::Scheduled), + 1 => Pickle::unpickle(stream).map(RecipientStatus::Completed), + 2 => Pickle::unpickle(stream).map(RecipientStatus::TemporaryFailure), + 3 => Pickle::unpickle(stream).map(RecipientStatus::PermanentFailure), + _ => None, + } + } +} + +impl IntoValue for RecipientStatus { + fn into_value(self) -> JmapValue<'static> { + match self { + RecipientStatus::Scheduled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Scheduled".into())); + JmapValue::Object(obj) + } + RecipientStatus::Completed(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Completed".into())); + obj + } + RecipientStatus::TemporaryFailure(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("TemporaryFailure".into())); + obj + } + RecipientStatus::PermanentFailure(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PermanentFailure".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for RecipientStatus { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + RecipientStatusType::Scheduled => *self = RecipientStatus::Scheduled, + RecipientStatusType::Completed => { + *self = RecipientStatus::Completed(Default::default()) + } + RecipientStatusType::TemporaryFailure => { + *self = RecipientStatus::TemporaryFailure(Default::default()) + } + RecipientStatusType::PermanentFailure => { + *self = RecipientStatus::PermanentFailure(Default::default()) + } + } + } + match self { + RecipientStatus::Scheduled => pointer.assert_eof(), + RecipientStatus::Completed(inner) => inner.patch(pointer, value), + RecipientStatus::TemporaryFailure(inner) => inner.patch(pointer, value), + RecipientStatus::PermanentFailure(inner) => inner.patch(pointer, value), + } + } +} + +impl RecipientStatus { + pub fn object_type(&self) -> RecipientStatusType { + match self { + RecipientStatus::Scheduled => RecipientStatusType::Scheduled, + RecipientStatus::Completed(_) => RecipientStatusType::Completed, + RecipientStatus::TemporaryFailure(_) => RecipientStatusType::TemporaryFailure, + RecipientStatus::PermanentFailure(_) => RecipientStatusType::PermanentFailure, + } + } +} + +impl RedisClusterStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.urls; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Urls)); + } + } + if let Some(value) = &self.auth_username { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthUsername)); + } + } + let value = &self.auth_secret; + value.validate(errors); + if let Some(value) = &self.max_retry_wait { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::MaxRetryWait, value)); + } + if *value > Duration::from_millis(1024) { + errors.push(ValidationError::max_value(Property::MaxRetryWait, 1024)); + } + if *value < Duration::from_millis(1) { + errors.push(ValidationError::min_value(Property::MaxRetryWait, 1)); + } + } + if let Some(value) = &self.min_retry_wait { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::MinRetryWait, value)); + } + if *value > Duration::from_millis(1024) { + errors.push(ValidationError::max_value(Property::MinRetryWait, 1024)); + } + if *value < Duration::from_millis(1) { + errors.push(ValidationError::min_value(Property::MinRetryWait, 1)); + } + } + if let Some(value) = &self.max_retries { + if *value > 1024 { + errors.push(ValidationError::max_value(Property::MaxRetries, 1024)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRetries, 1)); + } + } + let value = &self.pool_max_connections; + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1)); + } + errors.len() == neb + } +} + +impl Pickle for RedisClusterStore { + fn pickle(&self, out: &mut Vec) { + self.urls.pickle(out); + self.timeout.pickle(out); + self.auth_username.pickle(out); + self.auth_secret.pickle(out); + self.max_retry_wait.pickle(out); + self.min_retry_wait.pickle(out); + self.max_retries.pickle(out); + self.read_from_replicas.pickle(out); + self.protocol_version.pickle(out); + self.pool_max_connections.pickle(out); + self.pool_timeout_create.pickle(out); + self.pool_timeout_wait.pickle(out); + self.pool_timeout_recycle.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.urls = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.auth_username = Pickle::unpickle(stream)?; + this.auth_secret = Pickle::unpickle(stream)?; + this.max_retry_wait = Pickle::unpickle(stream)?; + this.min_retry_wait = Pickle::unpickle(stream)?; + this.max_retries = Pickle::unpickle(stream)?; + this.read_from_replicas = Pickle::unpickle(stream)?; + this.protocol_version = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + this.pool_timeout_create = Pickle::unpickle(stream)?; + this.pool_timeout_wait = Pickle::unpickle(stream)?; + this.pool_timeout_recycle = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for RedisClusterStore { + fn default() -> Self { + Self { + urls: Map::new(vec!["redis://127.0.0.1".to_string()]), + timeout: Duration::from_millis(10000), + auth_username: Some("stalwart".to_string()), + auth_secret: Default::default(), + max_retry_wait: Default::default(), + min_retry_wait: Default::default(), + max_retries: Default::default(), + read_from_replicas: true, + protocol_version: RedisProtocol::Resp2, + pool_max_connections: 10u64, + pool_timeout_create: Some(Duration::from_millis(30000)), + pool_timeout_wait: Some(Duration::from_millis(30000)), + pool_timeout_recycle: Some(Duration::from_millis(30000)), + } + } +} + +impl IntoValue for RedisClusterStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked(Property::Urls, self.urls.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::AuthUsername, self.auth_username.into_value()); + map.insert_unchecked(Property::AuthSecret, self.auth_secret.into_value()); + map.insert_unchecked(Property::MaxRetryWait, self.max_retry_wait.into_value()); + map.insert_unchecked(Property::MinRetryWait, self.min_retry_wait.into_value()); + map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value()); + map.insert_unchecked( + Property::ReadFromReplicas, + self.read_from_replicas.into_value(), + ); + map.insert_unchecked( + Property::ProtocolVersion, + self.protocol_version.into_value(), + ); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutCreate, + self.pool_timeout_create.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutWait, + self.pool_timeout_wait.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutRecycle, + self.pool_timeout_recycle.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for RedisClusterStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Urls) => self + .urls + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AuthUsername) => self + .auth_username + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AuthSecret) => self.auth_secret.patch(pointer, value), + Some(Property::MaxRetryWait) => self.max_retry_wait.patch(pointer, value), + Some(Property::MinRetryWait) => self.min_retry_wait.patch(pointer, value), + Some(Property::MaxRetries) => self.max_retries.patch(pointer, value), + Some(Property::ReadFromReplicas) => self.read_from_replicas.patch(pointer, value), + Some(Property::ProtocolVersion) => self.protocol_version.patch(pointer, value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value), + Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value), + Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl RedisStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.pool_max_connections; + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1)); + } + errors.len() == neb + } +} + +impl Pickle for RedisStore { + fn pickle(&self, out: &mut Vec) { + self.url.pickle(out); + self.timeout.pickle(out); + self.pool_max_connections.pickle(out); + self.pool_timeout_create.pickle(out); + self.pool_timeout_wait.pickle(out); + self.pool_timeout_recycle.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.url = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + this.pool_timeout_create = Pickle::unpickle(stream)?; + this.pool_timeout_wait = Pickle::unpickle(stream)?; + this.pool_timeout_recycle = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for RedisStore { + fn default() -> Self { + Self { + url: "redis://127.0.0.1".to_string(), + timeout: Duration::from_millis(10000), + pool_max_connections: 10u64, + pool_timeout_create: Some(Duration::from_millis(30000)), + pool_timeout_wait: Some(Duration::from_millis(30000)), + pool_timeout_recycle: Some(Duration::from_millis(30000)), + } + } +} + +impl IntoValue for RedisStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutCreate, + self.pool_timeout_create.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutWait, + self.pool_timeout_wait.into_value(), + ); + map.insert_unchecked( + Property::PoolTimeoutRecycle, + self.pool_timeout_recycle.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for RedisStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::PoolTimeoutCreate) => self.pool_timeout_create.patch(pointer, value), + Some(Property::PoolTimeoutWait) => self.pool_timeout_wait.patch(pointer, value), + Some(Property::PoolTimeoutRecycle) => self.pool_timeout_recycle.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for ReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::ReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.inbound_report_addresses; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::InboundReportAddresses)); + } + } + if let Some(value) = &self.outbound_report_domain { + if value.is_empty() { + errors.push(ValidationError::required(Property::OutboundReportDomain)); + } + } + let value = &self.outbound_report_submitter; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl ReportSettings { + pub fn ctx_outbound_report_submitter(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.outbound_report_submitter, + default: Some(Expression { + else_: "system('hostname')".to_string(), + ..Default::default() + }), + property: Property::OutboundReportSubmitter, + allowed_variables: MTA_RCPT_DOMAIN_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_outbound_report_submitter()] + } +} + +impl Pickle for ReportSettings { + fn pickle(&self, out: &mut Vec) { + self.inbound_report_addresses.pickle(out); + self.inbound_report_forwarding.pickle(out); + self.outbound_report_domain.pickle(out); + self.outbound_report_submitter.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.inbound_report_addresses = Pickle::unpickle(stream)?; + this.inbound_report_forwarding = Pickle::unpickle(stream)?; + this.outbound_report_domain = Pickle::unpickle(stream)?; + this.outbound_report_submitter = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ReportSettings { + fn default() -> Self { + Self { + inbound_report_addresses: Map::new(vec!["postmaster@*".to_string()]), + inbound_report_forwarding: true, + outbound_report_domain: Default::default(), + outbound_report_submitter: Expression { + else_: "system('hostname')".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for ReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked( + Property::InboundReportAddresses, + self.inbound_report_addresses.into_value(), + ); + map.insert_unchecked( + Property::InboundReportForwarding, + self.inbound_report_forwarding.into_value(), + ); + map.insert_unchecked( + Property::OutboundReportDomain, + self.outbound_report_domain.into_value(), + ); + map.insert_unchecked( + Property::OutboundReportSubmitter, + self.outbound_report_submitter.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::InboundReportAddresses) => self + .inbound_report_addresses + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::InboundReportForwarding) => { + self.inbound_report_forwarding.patch(pointer, value) + } + Some(Property::OutboundReportDomain) => self + .outbound_report_domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::OutboundReportSubmitter) => { + self.outbound_report_submitter.patch(pointer, value) + } + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl RocksDbStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.path; + if value.is_empty() { + errors.push(ValidationError::required(Property::Path)); + } + let value = &self.blob_size; + if *value > 1048576 { + errors.push(ValidationError::max_value(Property::BlobSize, 1048576)); + } + if *value < 1024 { + errors.push(ValidationError::min_value(Property::BlobSize, 1024)); + } + let value = &self.buffer_size; + if *value > 1073741824 { + errors.push(ValidationError::max_value(Property::BufferSize, 1073741824)); + } + if *value < 8192 { + errors.push(ValidationError::min_value(Property::BufferSize, 8192)); + } + if let Some(value) = &self.pool_workers { + if *value > 64 { + errors.push(ValidationError::max_value(Property::PoolWorkers, 64)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolWorkers, 1)); + } + } + errors.len() == neb + } +} + +impl Pickle for RocksDbStore { + fn pickle(&self, out: &mut Vec) { + self.path.pickle(out); + self.blob_size.pickle(out); + self.buffer_size.pickle(out); + self.pool_workers.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.path = Pickle::unpickle(stream)?; + this.blob_size = Pickle::unpickle(stream)?; + this.buffer_size = Pickle::unpickle(stream)?; + this.pool_workers = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for RocksDbStore { + fn default() -> Self { + Self { + path: Default::default(), + blob_size: 16834u64, + buffer_size: 134217728u64, + pool_workers: Default::default(), + } + } +} + +impl IntoValue for RocksDbStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Path, self.path.into_value()); + map.insert_unchecked(Property::BlobSize, self.blob_size.into_value()); + map.insert_unchecked(Property::BufferSize, self.buffer_size.into_value()); + map.insert_unchecked(Property::PoolWorkers, self.pool_workers.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for RocksDbStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Path) => self + .path + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::BlobSize) => self.blob_size.patch(pointer, value), + Some(Property::BufferSize) => self.buffer_size.patch(pointer, value), + Some(Property::PoolWorkers) => self.pool_workers.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Role { + const FLAGS: u64 = OBJ_FILTER_TENANT | OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Role; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.role_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::RoleIds)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.text(Property::Description, &self.description); + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + for id in self.role_ids.iter() { + i.foreign_key(ObjectType::Role, Some(*id), None); + } + } +} + +impl Pickle for Role { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.member_tenant_id.pickle(out); + self.role_ids.pickle(out); + self.enabled_permissions.pickle(out); + self.disabled_permissions.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.role_ids = Pickle::unpickle(stream)?; + this.enabled_permissions = Pickle::unpickle(stream)?; + this.disabled_permissions = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Role { + fn default() -> Self { + Self { + description: Default::default(), + member_tenant_id: Default::default(), + role_ids: Default::default(), + enabled_permissions: Default::default(), + disabled_permissions: Default::default(), + } + } +} + +impl IntoValue for Role { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::RoleIds, self.role_ids.into_value()); + map.insert_unchecked( + Property::EnabledPermissions, + self.enabled_permissions.into_value(), + ); + map.insert_unchecked( + Property::DisabledPermissions, + self.disabled_permissions.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Role { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::RoleIds) => self.role_ids.patch(pointer, value), + Some(Property::EnabledPermissions) => self.enabled_permissions.patch(pointer, value), + Some(Property::DisabledPermissions) => self.disabled_permissions.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Roles { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Roles::Default => true, + Roles::Custom(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + Roles::Default => {} + Roles::Custom(object) => { + object.index(i); + } + } + } +} + +impl Default for Roles { + fn default() -> Self { + Roles::Default + } +} + +impl Pickle for Roles { + fn pickle(&self, out: &mut Vec) { + match self { + Roles::Default => { + 0u16.pickle(out); + } + Roles::Custom(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(Roles::Default), + 1 => Pickle::unpickle(stream).map(Roles::Custom), + _ => None, + } + } +} + +impl IntoValue for Roles { + fn into_value(self) -> JmapValue<'static> { + match self { + Roles::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + Roles::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Roles { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + RolesType::Default => *self = Roles::Default, + RolesType::Custom => *self = Roles::Custom(Default::default()), + } + } + match self { + Roles::Default => pointer.assert_eof(), + Roles::Custom(inner) => inner.patch(pointer, value), + } + } +} + +impl Roles { + pub fn object_type(&self) -> RolesType { + match self { + Roles::Default => RolesType::Default, + Roles::Custom(_) => RolesType::Custom, + } + } +} + +impl S3Store { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.region; + value.validate(errors); + let value = &self.bucket; + if value.is_empty() { + errors.push(ValidationError::required(Property::Bucket)); + } + if let Some(value) = &self.access_key { + if value.is_empty() { + errors.push(ValidationError::required(Property::AccessKey)); + } + } + let value = &self.secret_key; + value.validate(errors); + let value = &self.security_token; + value.validate(errors); + let value = &self.session_token; + value.validate(errors); + if let Some(value) = &self.profile { + if value.is_empty() { + errors.push(ValidationError::required(Property::Profile)); + } + } + let value = &self.max_retries; + if *value > 10 { + errors.push(ValidationError::max_value(Property::MaxRetries, 10)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxRetries, 1)); + } + if let Some(value) = &self.key_prefix { + if value.is_empty() { + errors.push(ValidationError::required(Property::KeyPrefix)); + } + } + errors.len() == neb + } +} + +impl Pickle for S3Store { + fn pickle(&self, out: &mut Vec) { + self.region.pickle(out); + self.bucket.pickle(out); + self.access_key.pickle(out); + self.secret_key.pickle(out); + self.security_token.pickle(out); + self.session_token.pickle(out); + self.profile.pickle(out); + self.timeout.pickle(out); + self.max_retries.pickle(out); + self.key_prefix.pickle(out); + self.allow_invalid_certs.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.region = Pickle::unpickle(stream)?; + this.bucket = Pickle::unpickle(stream)?; + this.access_key = Pickle::unpickle(stream)?; + this.secret_key = Pickle::unpickle(stream)?; + this.security_token = Pickle::unpickle(stream)?; + this.session_token = Pickle::unpickle(stream)?; + this.profile = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.max_retries = Pickle::unpickle(stream)?; + this.key_prefix = Pickle::unpickle(stream)?; + this.allow_invalid_certs = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for S3Store { + fn default() -> Self { + Self { + region: Default::default(), + bucket: Default::default(), + access_key: Default::default(), + secret_key: Default::default(), + security_token: Default::default(), + session_token: Default::default(), + profile: Default::default(), + timeout: Duration::from_millis(30000), + max_retries: 3u64, + key_prefix: Default::default(), + allow_invalid_certs: false, + } + } +} + +impl IntoValue for S3Store { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::Region, self.region.into_value()); + map.insert_unchecked(Property::Bucket, self.bucket.into_value()); + map.insert_unchecked(Property::AccessKey, self.access_key.into_value()); + map.insert_unchecked(Property::SecretKey, self.secret_key.into_value()); + map.insert_unchecked(Property::SecurityToken, self.security_token.into_value()); + map.insert_unchecked(Property::SessionToken, self.session_token.into_value()); + map.insert_unchecked(Property::Profile, self.profile.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::MaxRetries, self.max_retries.into_value()); + map.insert_unchecked(Property::KeyPrefix, self.key_prefix.into_value()); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for S3Store { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Region) => self.region.patch(pointer, value), + Some(Property::Bucket) => self + .bucket + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AccessKey) => self + .access_key + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::SecretKey) => self.secret_key.patch(pointer, value), + Some(Property::SecurityToken) => self.security_token.patch(pointer, value), + Some(Property::SessionToken) => self.session_token.patch(pointer, value), + Some(Property::Profile) => self + .profile + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::MaxRetries) => self.max_retries.patch(pointer, value), + Some(Property::KeyPrefix) => self + .key_prefix + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl S3StoreCustomRegion { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.custom_endpoint; + if value.is_empty() { + errors.push(ValidationError::required(Property::CustomEndpoint)); + } + let value = &self.custom_region; + if value.is_empty() { + errors.push(ValidationError::required(Property::CustomRegion)); + } + errors.len() == neb + } +} + +impl Pickle for S3StoreCustomRegion { + fn pickle(&self, out: &mut Vec) { + self.custom_endpoint.pickle(out); + self.custom_region.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.custom_endpoint = Pickle::unpickle(stream)?; + this.custom_region = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for S3StoreCustomRegion { + fn default() -> Self { + Self { + custom_endpoint: Default::default(), + custom_region: Default::default(), + } + } +} + +impl IntoValue for S3StoreCustomRegion { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::CustomEndpoint, self.custom_endpoint.into_value()); + map.insert_unchecked(Property::CustomRegion, self.custom_region.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for S3StoreCustomRegion { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CustomEndpoint) => self + .custom_endpoint + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::CustomRegion) => self + .custom_region + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl S3StoreRegion { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + S3StoreRegion::UsEast1 => true, + S3StoreRegion::UsEast2 => true, + S3StoreRegion::UsWest1 => true, + S3StoreRegion::UsWest2 => true, + S3StoreRegion::CaCentral1 => true, + S3StoreRegion::AfSouth1 => true, + S3StoreRegion::ApEast1 => true, + S3StoreRegion::ApSouth1 => true, + S3StoreRegion::ApNortheast1 => true, + S3StoreRegion::ApNortheast2 => true, + S3StoreRegion::ApNortheast3 => true, + S3StoreRegion::ApSoutheast1 => true, + S3StoreRegion::ApSoutheast2 => true, + S3StoreRegion::CnNorth1 => true, + S3StoreRegion::CnNorthwest1 => true, + S3StoreRegion::EuNorth1 => true, + S3StoreRegion::EuCentral1 => true, + S3StoreRegion::EuCentral2 => true, + S3StoreRegion::EuWest1 => true, + S3StoreRegion::EuWest2 => true, + S3StoreRegion::EuWest3 => true, + S3StoreRegion::IlCentral1 => true, + S3StoreRegion::MeSouth1 => true, + S3StoreRegion::SaEast1 => true, + S3StoreRegion::DoNyc3 => true, + S3StoreRegion::DoAms3 => true, + S3StoreRegion::DoSgp1 => true, + S3StoreRegion::DoFra1 => true, + S3StoreRegion::Yandex => true, + S3StoreRegion::WaUsEast1 => true, + S3StoreRegion::WaUsEast2 => true, + S3StoreRegion::WaUsCentral1 => true, + S3StoreRegion::WaUsWest1 => true, + S3StoreRegion::WaCaCentral1 => true, + S3StoreRegion::WaEuCentral1 => true, + S3StoreRegion::WaEuCentral2 => true, + S3StoreRegion::WaEuWest1 => true, + S3StoreRegion::WaEuWest2 => true, + S3StoreRegion::WaApNortheast1 => true, + S3StoreRegion::WaApNortheast2 => true, + S3StoreRegion::WaApSoutheast1 => true, + S3StoreRegion::WaApSoutheast2 => true, + S3StoreRegion::Custom(inner) => inner.validate(errors), + } + } +} + +impl Default for S3StoreRegion { + fn default() -> Self { + S3StoreRegion::UsEast1 + } +} + +impl Pickle for S3StoreRegion { + fn pickle(&self, out: &mut Vec) { + match self { + S3StoreRegion::UsEast1 => { + 0u16.pickle(out); + } + S3StoreRegion::UsEast2 => { + 1u16.pickle(out); + } + S3StoreRegion::UsWest1 => { + 2u16.pickle(out); + } + S3StoreRegion::UsWest2 => { + 3u16.pickle(out); + } + S3StoreRegion::CaCentral1 => { + 4u16.pickle(out); + } + S3StoreRegion::AfSouth1 => { + 5u16.pickle(out); + } + S3StoreRegion::ApEast1 => { + 6u16.pickle(out); + } + S3StoreRegion::ApSouth1 => { + 7u16.pickle(out); + } + S3StoreRegion::ApNortheast1 => { + 8u16.pickle(out); + } + S3StoreRegion::ApNortheast2 => { + 9u16.pickle(out); + } + S3StoreRegion::ApNortheast3 => { + 10u16.pickle(out); + } + S3StoreRegion::ApSoutheast1 => { + 11u16.pickle(out); + } + S3StoreRegion::ApSoutheast2 => { + 12u16.pickle(out); + } + S3StoreRegion::CnNorth1 => { + 13u16.pickle(out); + } + S3StoreRegion::CnNorthwest1 => { + 14u16.pickle(out); + } + S3StoreRegion::EuNorth1 => { + 15u16.pickle(out); + } + S3StoreRegion::EuCentral1 => { + 16u16.pickle(out); + } + S3StoreRegion::EuCentral2 => { + 17u16.pickle(out); + } + S3StoreRegion::EuWest1 => { + 18u16.pickle(out); + } + S3StoreRegion::EuWest2 => { + 19u16.pickle(out); + } + S3StoreRegion::EuWest3 => { + 20u16.pickle(out); + } + S3StoreRegion::IlCentral1 => { + 21u16.pickle(out); + } + S3StoreRegion::MeSouth1 => { + 22u16.pickle(out); + } + S3StoreRegion::SaEast1 => { + 23u16.pickle(out); + } + S3StoreRegion::DoNyc3 => { + 24u16.pickle(out); + } + S3StoreRegion::DoAms3 => { + 25u16.pickle(out); + } + S3StoreRegion::DoSgp1 => { + 26u16.pickle(out); + } + S3StoreRegion::DoFra1 => { + 27u16.pickle(out); + } + S3StoreRegion::Yandex => { + 28u16.pickle(out); + } + S3StoreRegion::WaUsEast1 => { + 29u16.pickle(out); + } + S3StoreRegion::WaUsEast2 => { + 30u16.pickle(out); + } + S3StoreRegion::WaUsCentral1 => { + 31u16.pickle(out); + } + S3StoreRegion::WaUsWest1 => { + 32u16.pickle(out); + } + S3StoreRegion::WaCaCentral1 => { + 33u16.pickle(out); + } + S3StoreRegion::WaEuCentral1 => { + 34u16.pickle(out); + } + S3StoreRegion::WaEuCentral2 => { + 35u16.pickle(out); + } + S3StoreRegion::WaEuWest1 => { + 36u16.pickle(out); + } + S3StoreRegion::WaEuWest2 => { + 37u16.pickle(out); + } + S3StoreRegion::WaApNortheast1 => { + 38u16.pickle(out); + } + S3StoreRegion::WaApNortheast2 => { + 39u16.pickle(out); + } + S3StoreRegion::WaApSoutheast1 => { + 40u16.pickle(out); + } + S3StoreRegion::WaApSoutheast2 => { + 41u16.pickle(out); + } + S3StoreRegion::Custom(inner) => { + 42u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(S3StoreRegion::UsEast1), + 1 => Some(S3StoreRegion::UsEast2), + 2 => Some(S3StoreRegion::UsWest1), + 3 => Some(S3StoreRegion::UsWest2), + 4 => Some(S3StoreRegion::CaCentral1), + 5 => Some(S3StoreRegion::AfSouth1), + 6 => Some(S3StoreRegion::ApEast1), + 7 => Some(S3StoreRegion::ApSouth1), + 8 => Some(S3StoreRegion::ApNortheast1), + 9 => Some(S3StoreRegion::ApNortheast2), + 10 => Some(S3StoreRegion::ApNortheast3), + 11 => Some(S3StoreRegion::ApSoutheast1), + 12 => Some(S3StoreRegion::ApSoutheast2), + 13 => Some(S3StoreRegion::CnNorth1), + 14 => Some(S3StoreRegion::CnNorthwest1), + 15 => Some(S3StoreRegion::EuNorth1), + 16 => Some(S3StoreRegion::EuCentral1), + 17 => Some(S3StoreRegion::EuCentral2), + 18 => Some(S3StoreRegion::EuWest1), + 19 => Some(S3StoreRegion::EuWest2), + 20 => Some(S3StoreRegion::EuWest3), + 21 => Some(S3StoreRegion::IlCentral1), + 22 => Some(S3StoreRegion::MeSouth1), + 23 => Some(S3StoreRegion::SaEast1), + 24 => Some(S3StoreRegion::DoNyc3), + 25 => Some(S3StoreRegion::DoAms3), + 26 => Some(S3StoreRegion::DoSgp1), + 27 => Some(S3StoreRegion::DoFra1), + 28 => Some(S3StoreRegion::Yandex), + 29 => Some(S3StoreRegion::WaUsEast1), + 30 => Some(S3StoreRegion::WaUsEast2), + 31 => Some(S3StoreRegion::WaUsCentral1), + 32 => Some(S3StoreRegion::WaUsWest1), + 33 => Some(S3StoreRegion::WaCaCentral1), + 34 => Some(S3StoreRegion::WaEuCentral1), + 35 => Some(S3StoreRegion::WaEuCentral2), + 36 => Some(S3StoreRegion::WaEuWest1), + 37 => Some(S3StoreRegion::WaEuWest2), + 38 => Some(S3StoreRegion::WaApNortheast1), + 39 => Some(S3StoreRegion::WaApNortheast2), + 40 => Some(S3StoreRegion::WaApSoutheast1), + 41 => Some(S3StoreRegion::WaApSoutheast2), + 42 => Pickle::unpickle(stream).map(S3StoreRegion::Custom), + _ => None, + } + } +} + +impl IntoValue for S3StoreRegion { + fn into_value(self) -> JmapValue<'static> { + match self { + S3StoreRegion::UsEast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("UsEast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::UsEast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("UsEast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::UsWest1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("UsWest1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::UsWest2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("UsWest2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::CaCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("CaCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::AfSouth1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("AfSouth1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApEast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApEast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApSouth1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApSouth1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApNortheast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApNortheast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApNortheast3 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApNortheast3".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApSoutheast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApSoutheast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::ApSoutheast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("ApSoutheast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::CnNorth1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("CnNorth1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::CnNorthwest1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("CnNorthwest1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuNorth1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuNorth1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuCentral2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuCentral2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuWest1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuWest2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::EuWest3 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("EuWest3".into())); + JmapValue::Object(obj) + } + S3StoreRegion::IlCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("IlCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::MeSouth1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("MeSouth1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::SaEast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("SaEast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::DoNyc3 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DoNyc3".into())); + JmapValue::Object(obj) + } + S3StoreRegion::DoAms3 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DoAms3".into())); + JmapValue::Object(obj) + } + S3StoreRegion::DoSgp1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DoSgp1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::DoFra1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("DoFra1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::Yandex => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Yandex".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaUsEast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsEast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaUsEast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsEast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaUsCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaUsWest1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaUsWest1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaCaCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaCaCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaEuCentral1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuCentral1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaEuCentral2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuCentral2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaEuWest1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuWest1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaEuWest2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaEuWest2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaApNortheast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaApNortheast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaApNortheast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaApNortheast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaApSoutheast1 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaApSoutheast1".into())); + JmapValue::Object(obj) + } + S3StoreRegion::WaApSoutheast2 => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("WaApSoutheast2".into())); + JmapValue::Object(obj) + } + S3StoreRegion::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for S3StoreRegion { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + S3StoreRegionType::UsEast1 => *self = S3StoreRegion::UsEast1, + S3StoreRegionType::UsEast2 => *self = S3StoreRegion::UsEast2, + S3StoreRegionType::UsWest1 => *self = S3StoreRegion::UsWest1, + S3StoreRegionType::UsWest2 => *self = S3StoreRegion::UsWest2, + S3StoreRegionType::CaCentral1 => *self = S3StoreRegion::CaCentral1, + S3StoreRegionType::AfSouth1 => *self = S3StoreRegion::AfSouth1, + S3StoreRegionType::ApEast1 => *self = S3StoreRegion::ApEast1, + S3StoreRegionType::ApSouth1 => *self = S3StoreRegion::ApSouth1, + S3StoreRegionType::ApNortheast1 => *self = S3StoreRegion::ApNortheast1, + S3StoreRegionType::ApNortheast2 => *self = S3StoreRegion::ApNortheast2, + S3StoreRegionType::ApNortheast3 => *self = S3StoreRegion::ApNortheast3, + S3StoreRegionType::ApSoutheast1 => *self = S3StoreRegion::ApSoutheast1, + S3StoreRegionType::ApSoutheast2 => *self = S3StoreRegion::ApSoutheast2, + S3StoreRegionType::CnNorth1 => *self = S3StoreRegion::CnNorth1, + S3StoreRegionType::CnNorthwest1 => *self = S3StoreRegion::CnNorthwest1, + S3StoreRegionType::EuNorth1 => *self = S3StoreRegion::EuNorth1, + S3StoreRegionType::EuCentral1 => *self = S3StoreRegion::EuCentral1, + S3StoreRegionType::EuCentral2 => *self = S3StoreRegion::EuCentral2, + S3StoreRegionType::EuWest1 => *self = S3StoreRegion::EuWest1, + S3StoreRegionType::EuWest2 => *self = S3StoreRegion::EuWest2, + S3StoreRegionType::EuWest3 => *self = S3StoreRegion::EuWest3, + S3StoreRegionType::IlCentral1 => *self = S3StoreRegion::IlCentral1, + S3StoreRegionType::MeSouth1 => *self = S3StoreRegion::MeSouth1, + S3StoreRegionType::SaEast1 => *self = S3StoreRegion::SaEast1, + S3StoreRegionType::DoNyc3 => *self = S3StoreRegion::DoNyc3, + S3StoreRegionType::DoAms3 => *self = S3StoreRegion::DoAms3, + S3StoreRegionType::DoSgp1 => *self = S3StoreRegion::DoSgp1, + S3StoreRegionType::DoFra1 => *self = S3StoreRegion::DoFra1, + S3StoreRegionType::Yandex => *self = S3StoreRegion::Yandex, + S3StoreRegionType::WaUsEast1 => *self = S3StoreRegion::WaUsEast1, + S3StoreRegionType::WaUsEast2 => *self = S3StoreRegion::WaUsEast2, + S3StoreRegionType::WaUsCentral1 => *self = S3StoreRegion::WaUsCentral1, + S3StoreRegionType::WaUsWest1 => *self = S3StoreRegion::WaUsWest1, + S3StoreRegionType::WaCaCentral1 => *self = S3StoreRegion::WaCaCentral1, + S3StoreRegionType::WaEuCentral1 => *self = S3StoreRegion::WaEuCentral1, + S3StoreRegionType::WaEuCentral2 => *self = S3StoreRegion::WaEuCentral2, + S3StoreRegionType::WaEuWest1 => *self = S3StoreRegion::WaEuWest1, + S3StoreRegionType::WaEuWest2 => *self = S3StoreRegion::WaEuWest2, + S3StoreRegionType::WaApNortheast1 => *self = S3StoreRegion::WaApNortheast1, + S3StoreRegionType::WaApNortheast2 => *self = S3StoreRegion::WaApNortheast2, + S3StoreRegionType::WaApSoutheast1 => *self = S3StoreRegion::WaApSoutheast1, + S3StoreRegionType::WaApSoutheast2 => *self = S3StoreRegion::WaApSoutheast2, + S3StoreRegionType::Custom => *self = S3StoreRegion::Custom(Default::default()), + } + } + match self { + S3StoreRegion::UsEast1 => pointer.assert_eof(), + S3StoreRegion::UsEast2 => pointer.assert_eof(), + S3StoreRegion::UsWest1 => pointer.assert_eof(), + S3StoreRegion::UsWest2 => pointer.assert_eof(), + S3StoreRegion::CaCentral1 => pointer.assert_eof(), + S3StoreRegion::AfSouth1 => pointer.assert_eof(), + S3StoreRegion::ApEast1 => pointer.assert_eof(), + S3StoreRegion::ApSouth1 => pointer.assert_eof(), + S3StoreRegion::ApNortheast1 => pointer.assert_eof(), + S3StoreRegion::ApNortheast2 => pointer.assert_eof(), + S3StoreRegion::ApNortheast3 => pointer.assert_eof(), + S3StoreRegion::ApSoutheast1 => pointer.assert_eof(), + S3StoreRegion::ApSoutheast2 => pointer.assert_eof(), + S3StoreRegion::CnNorth1 => pointer.assert_eof(), + S3StoreRegion::CnNorthwest1 => pointer.assert_eof(), + S3StoreRegion::EuNorth1 => pointer.assert_eof(), + S3StoreRegion::EuCentral1 => pointer.assert_eof(), + S3StoreRegion::EuCentral2 => pointer.assert_eof(), + S3StoreRegion::EuWest1 => pointer.assert_eof(), + S3StoreRegion::EuWest2 => pointer.assert_eof(), + S3StoreRegion::EuWest3 => pointer.assert_eof(), + S3StoreRegion::IlCentral1 => pointer.assert_eof(), + S3StoreRegion::MeSouth1 => pointer.assert_eof(), + S3StoreRegion::SaEast1 => pointer.assert_eof(), + S3StoreRegion::DoNyc3 => pointer.assert_eof(), + S3StoreRegion::DoAms3 => pointer.assert_eof(), + S3StoreRegion::DoSgp1 => pointer.assert_eof(), + S3StoreRegion::DoFra1 => pointer.assert_eof(), + S3StoreRegion::Yandex => pointer.assert_eof(), + S3StoreRegion::WaUsEast1 => pointer.assert_eof(), + S3StoreRegion::WaUsEast2 => pointer.assert_eof(), + S3StoreRegion::WaUsCentral1 => pointer.assert_eof(), + S3StoreRegion::WaUsWest1 => pointer.assert_eof(), + S3StoreRegion::WaCaCentral1 => pointer.assert_eof(), + S3StoreRegion::WaEuCentral1 => pointer.assert_eof(), + S3StoreRegion::WaEuCentral2 => pointer.assert_eof(), + S3StoreRegion::WaEuWest1 => pointer.assert_eof(), + S3StoreRegion::WaEuWest2 => pointer.assert_eof(), + S3StoreRegion::WaApNortheast1 => pointer.assert_eof(), + S3StoreRegion::WaApNortheast2 => pointer.assert_eof(), + S3StoreRegion::WaApSoutheast1 => pointer.assert_eof(), + S3StoreRegion::WaApSoutheast2 => pointer.assert_eof(), + S3StoreRegion::Custom(inner) => inner.patch(pointer, value), + } + } +} + +impl S3StoreRegion { + pub fn object_type(&self) -> S3StoreRegionType { + match self { + S3StoreRegion::UsEast1 => S3StoreRegionType::UsEast1, + S3StoreRegion::UsEast2 => S3StoreRegionType::UsEast2, + S3StoreRegion::UsWest1 => S3StoreRegionType::UsWest1, + S3StoreRegion::UsWest2 => S3StoreRegionType::UsWest2, + S3StoreRegion::CaCentral1 => S3StoreRegionType::CaCentral1, + S3StoreRegion::AfSouth1 => S3StoreRegionType::AfSouth1, + S3StoreRegion::ApEast1 => S3StoreRegionType::ApEast1, + S3StoreRegion::ApSouth1 => S3StoreRegionType::ApSouth1, + S3StoreRegion::ApNortheast1 => S3StoreRegionType::ApNortheast1, + S3StoreRegion::ApNortheast2 => S3StoreRegionType::ApNortheast2, + S3StoreRegion::ApNortheast3 => S3StoreRegionType::ApNortheast3, + S3StoreRegion::ApSoutheast1 => S3StoreRegionType::ApSoutheast1, + S3StoreRegion::ApSoutheast2 => S3StoreRegionType::ApSoutheast2, + S3StoreRegion::CnNorth1 => S3StoreRegionType::CnNorth1, + S3StoreRegion::CnNorthwest1 => S3StoreRegionType::CnNorthwest1, + S3StoreRegion::EuNorth1 => S3StoreRegionType::EuNorth1, + S3StoreRegion::EuCentral1 => S3StoreRegionType::EuCentral1, + S3StoreRegion::EuCentral2 => S3StoreRegionType::EuCentral2, + S3StoreRegion::EuWest1 => S3StoreRegionType::EuWest1, + S3StoreRegion::EuWest2 => S3StoreRegionType::EuWest2, + S3StoreRegion::EuWest3 => S3StoreRegionType::EuWest3, + S3StoreRegion::IlCentral1 => S3StoreRegionType::IlCentral1, + S3StoreRegion::MeSouth1 => S3StoreRegionType::MeSouth1, + S3StoreRegion::SaEast1 => S3StoreRegionType::SaEast1, + S3StoreRegion::DoNyc3 => S3StoreRegionType::DoNyc3, + S3StoreRegion::DoAms3 => S3StoreRegionType::DoAms3, + S3StoreRegion::DoSgp1 => S3StoreRegionType::DoSgp1, + S3StoreRegion::DoFra1 => S3StoreRegionType::DoFra1, + S3StoreRegion::Yandex => S3StoreRegionType::Yandex, + S3StoreRegion::WaUsEast1 => S3StoreRegionType::WaUsEast1, + S3StoreRegion::WaUsEast2 => S3StoreRegionType::WaUsEast2, + S3StoreRegion::WaUsCentral1 => S3StoreRegionType::WaUsCentral1, + S3StoreRegion::WaUsWest1 => S3StoreRegionType::WaUsWest1, + S3StoreRegion::WaCaCentral1 => S3StoreRegionType::WaCaCentral1, + S3StoreRegion::WaEuCentral1 => S3StoreRegionType::WaEuCentral1, + S3StoreRegion::WaEuCentral2 => S3StoreRegionType::WaEuCentral2, + S3StoreRegion::WaEuWest1 => S3StoreRegionType::WaEuWest1, + S3StoreRegion::WaEuWest2 => S3StoreRegionType::WaEuWest2, + S3StoreRegion::WaApNortheast1 => S3StoreRegionType::WaApNortheast1, + S3StoreRegion::WaApNortheast2 => S3StoreRegionType::WaApNortheast2, + S3StoreRegion::WaApSoutheast1 => S3StoreRegionType::WaApSoutheast1, + S3StoreRegion::WaApSoutheast2 => S3StoreRegionType::WaApSoutheast2, + S3StoreRegion::Custom(_) => S3StoreRegionType::Custom, + } + } +} + +impl ObjectImpl for Search { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Search; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.index_batch_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::IndexBatchSize, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Search { + fn pickle(&self, out: &mut Vec) { + self.index_batch_size.pickle(out); + self.default_language.pickle(out); + self.disable_languages.pickle(out); + self.index_calendar.pickle(out); + self.index_calendar_fields.pickle(out); + self.index_contacts.pickle(out); + self.index_contact_fields.pickle(out); + self.index_email.pickle(out); + self.index_email_fields.pickle(out); + self.index_telemetry.pickle(out); + self.index_tracing_fields.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.index_batch_size = Pickle::unpickle(stream)?; + this.default_language = Pickle::unpickle(stream)?; + this.disable_languages = Pickle::unpickle(stream)?; + this.index_calendar = Pickle::unpickle(stream)?; + this.index_calendar_fields = Pickle::unpickle(stream)?; + this.index_contacts = Pickle::unpickle(stream)?; + this.index_contact_fields = Pickle::unpickle(stream)?; + this.index_email = Pickle::unpickle(stream)?; + this.index_email_fields = Pickle::unpickle(stream)?; + this.index_telemetry = Pickle::unpickle(stream)?; + this.index_tracing_fields = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Search { + fn default() -> Self { + Self { + index_batch_size: 100u64, + default_language: Locale::EnUS, + disable_languages: Default::default(), + index_calendar: true, + index_calendar_fields: Map::new(vec![ + SearchCalendarField::Title, + SearchCalendarField::Description, + SearchCalendarField::Location, + SearchCalendarField::Owner, + SearchCalendarField::Attendee, + SearchCalendarField::Start, + SearchCalendarField::Uid, + ]), + index_contacts: true, + index_contact_fields: Map::new(vec![ + SearchContactField::Member, + SearchContactField::Kind, + SearchContactField::Name, + SearchContactField::Nickname, + SearchContactField::Organization, + SearchContactField::Email, + SearchContactField::Phone, + SearchContactField::OnlineService, + SearchContactField::Address, + SearchContactField::Note, + SearchContactField::Uid, + ]), + index_email: true, + index_email_fields: Map::new(vec![ + SearchEmailField::From, + SearchEmailField::To, + SearchEmailField::Cc, + SearchEmailField::Bcc, + SearchEmailField::Subject, + SearchEmailField::Body, + SearchEmailField::Attachment, + SearchEmailField::ReceivedAt, + SearchEmailField::SentAt, + SearchEmailField::Size, + SearchEmailField::HasAttachment, + ]), + index_telemetry: true, + index_tracing_fields: Map::new(vec![ + SearchTracingField::EventType, + SearchTracingField::QueueId, + SearchTracingField::Keywords, + ]), + } + } +} + +impl IntoValue for Search { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::IndexBatchSize, self.index_batch_size.into_value()); + map.insert_unchecked( + Property::DefaultLanguage, + self.default_language.into_value(), + ); + map.insert_unchecked( + Property::DisableLanguages, + self.disable_languages.into_value(), + ); + map.insert_unchecked(Property::IndexCalendar, self.index_calendar.into_value()); + map.insert_unchecked( + Property::IndexCalendarFields, + self.index_calendar_fields.into_value(), + ); + map.insert_unchecked(Property::IndexContacts, self.index_contacts.into_value()); + map.insert_unchecked( + Property::IndexContactFields, + self.index_contact_fields.into_value(), + ); + map.insert_unchecked(Property::IndexEmail, self.index_email.into_value()); + map.insert_unchecked( + Property::IndexEmailFields, + self.index_email_fields.into_value(), + ); + map.insert_unchecked(Property::IndexTelemetry, self.index_telemetry.into_value()); + map.insert_unchecked( + Property::IndexTracingFields, + self.index_tracing_fields.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Search { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IndexBatchSize) => self.index_batch_size.patch(pointer, value), + Some(Property::DefaultLanguage) => self.default_language.patch(pointer, value), + Some(Property::DisableLanguages) => self.disable_languages.patch(pointer, value), + Some(Property::IndexCalendar) => self.index_calendar.patch(pointer, value), + Some(Property::IndexCalendarFields) => self.index_calendar_fields.patch(pointer, value), + Some(Property::IndexContacts) => self.index_contacts.patch(pointer, value), + Some(Property::IndexContactFields) => self.index_contact_fields.patch(pointer, value), + Some(Property::IndexEmail) => self.index_email.patch(pointer, value), + Some(Property::IndexEmailFields) => self.index_email_fields.patch(pointer, value), + Some(Property::IndexTelemetry) => self.index_telemetry.patch(pointer, value), + Some(Property::IndexTracingFields) => self.index_tracing_fields.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SearchStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SearchStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SearchStore::Default => true, + SearchStore::ElasticSearch(inner) => inner.validate(errors), + SearchStore::Meilisearch(inner) => inner.validate(errors), + SearchStore::FoundationDb(inner) => inner.validate(errors), + SearchStore::PostgreSql(inner) => inner.validate(errors), + SearchStore::MySql(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for SearchStore { + fn default() -> Self { + SearchStore::Default + } +} + +impl Pickle for SearchStore { + fn pickle(&self, out: &mut Vec) { + match self { + SearchStore::Default => { + 0u16.pickle(out); + } + SearchStore::ElasticSearch(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SearchStore::Meilisearch(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SearchStore::FoundationDb(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + SearchStore::PostgreSql(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + SearchStore::MySql(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SearchStore::Default), + 1 => Pickle::unpickle(stream).map(SearchStore::ElasticSearch), + 2 => Pickle::unpickle(stream).map(SearchStore::Meilisearch), + 3 => Pickle::unpickle(stream).map(SearchStore::FoundationDb), + 4 => Pickle::unpickle(stream).map(SearchStore::PostgreSql), + 5 => Pickle::unpickle(stream).map(SearchStore::MySql), + _ => None, + } + } +} + +impl IntoValue for SearchStore { + fn into_value(self) -> JmapValue<'static> { + match self { + SearchStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + SearchStore::ElasticSearch(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("ElasticSearch".into())); + obj + } + SearchStore::Meilisearch(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Meilisearch".into())); + obj + } + SearchStore::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + SearchStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + SearchStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SearchStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SearchStoreType::Default => *self = SearchStore::Default, + SearchStoreType::ElasticSearch => { + *self = SearchStore::ElasticSearch(Default::default()) + } + SearchStoreType::Meilisearch => { + *self = SearchStore::Meilisearch(Default::default()) + } + SearchStoreType::FoundationDb => { + *self = SearchStore::FoundationDb(Default::default()) + } + SearchStoreType::PostgreSql => *self = SearchStore::PostgreSql(Default::default()), + SearchStoreType::MySql => *self = SearchStore::MySql(Default::default()), + } + } + match self { + SearchStore::Default => pointer.assert_eof(), + SearchStore::ElasticSearch(inner) => inner.patch(pointer, value), + SearchStore::Meilisearch(inner) => inner.patch(pointer, value), + SearchStore::FoundationDb(inner) => inner.patch(pointer, value), + SearchStore::PostgreSql(inner) => inner.patch(pointer, value), + SearchStore::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl SearchStore { + pub fn object_type(&self) -> SearchStoreType { + match self { + SearchStore::Default => SearchStoreType::Default, + SearchStore::ElasticSearch(_) => SearchStoreType::ElasticSearch, + SearchStore::Meilisearch(_) => SearchStoreType::Meilisearch, + SearchStore::FoundationDb(_) => SearchStoreType::FoundationDb, + SearchStore::PostgreSql(_) => SearchStoreType::PostgreSql, + SearchStore::MySql(_) => SearchStoreType::MySql, + } + } +} + +impl SecondaryCredential { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.credential_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CredentialId, value)); + } + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.expires_at { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + } + let value = &self.permissions; + value.validate(errors); + let value = &self.allowed_ips; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::AllowedIps, value)); + } + } + errors.len() == neb + } +} + +impl Pickle for SecondaryCredential { + fn pickle(&self, out: &mut Vec) { + self.credential_id.pickle(out); + self.description.pickle(out); + self.secret.pickle(out); + self.created_at.pickle(out); + self.expires_at.pickle(out); + self.permissions.pickle(out); + self.allowed_ips.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.credential_id = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.secret = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.allowed_ips = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SecondaryCredential { + fn default() -> Self { + Self { + credential_id: Default::default(), + description: Default::default(), + secret: Default::default(), + created_at: Default::default(), + expires_at: Default::default(), + permissions: Default::default(), + allowed_ips: Default::default(), + } + } +} + +impl IntoValue for SecondaryCredential { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::CredentialId, self.credential_id.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::AllowedIps, self.allowed_ips.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SecondaryCredential { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CredentialId) => pointer.assert_server_set(), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Secret) => pointer.assert_server_set(), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::AllowedIps) => self.allowed_ips.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SecretKey { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SecretKey::Value(inner) => inner.validate(errors), + SecretKey::EnvironmentVariable(inner) => inner.validate(errors), + SecretKey::File(inner) => inner.validate(errors), + } + } +} + +impl Default for SecretKey { + fn default() -> Self { + SecretKey::Value(Default::default()) + } +} + +impl Pickle for SecretKey { + fn pickle(&self, out: &mut Vec) { + match self { + SecretKey::Value(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SecretKey::EnvironmentVariable(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SecretKey::File(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SecretKey::Value), + 1 => Pickle::unpickle(stream).map(SecretKey::EnvironmentVariable), + 2 => Pickle::unpickle(stream).map(SecretKey::File), + _ => None, + } + } +} + +impl IntoValue for SecretKey { + fn into_value(self) -> JmapValue<'static> { + match self { + SecretKey::Value(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Value".into())); + obj + } + SecretKey::EnvironmentVariable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into())); + obj + } + SecretKey::File(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("File".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SecretKey { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SecretKeyType::Value => *self = SecretKey::Value(Default::default()), + SecretKeyType::EnvironmentVariable => { + *self = SecretKey::EnvironmentVariable(Default::default()) + } + SecretKeyType::File => *self = SecretKey::File(Default::default()), + } + } + match self { + SecretKey::Value(inner) => inner.patch(pointer, value), + SecretKey::EnvironmentVariable(inner) => inner.patch(pointer, value), + SecretKey::File(inner) => inner.patch(pointer, value), + } + } +} + +impl SecretKey { + pub fn object_type(&self) -> SecretKeyType { + match self { + SecretKey::Value(_) => SecretKeyType::Value, + SecretKey::EnvironmentVariable(_) => SecretKeyType::EnvironmentVariable, + SecretKey::File(_) => SecretKeyType::File, + } + } +} + +impl SecretKeyEnvironmentVariable { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.variable_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::VariableName)); + } + errors.len() == neb + } +} + +impl Pickle for SecretKeyEnvironmentVariable { + fn pickle(&self, out: &mut Vec) { + self.variable_name.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.variable_name = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SecretKeyEnvironmentVariable { + fn default() -> Self { + Self { + variable_name: Default::default(), + } + } +} + +impl IntoValue for SecretKeyEnvironmentVariable { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::VariableName, self.variable_name.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SecretKeyEnvironmentVariable { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::VariableName) => self.variable_name.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SecretKeyFile { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.file_path; + if value.is_empty() { + errors.push(ValidationError::required(Property::FilePath)); + } + errors.len() == neb + } +} + +impl Pickle for SecretKeyFile { + fn pickle(&self, out: &mut Vec) { + self.file_path.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.file_path = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SecretKeyFile { + fn default() -> Self { + Self { + file_path: Default::default(), + } + } +} + +impl IntoValue for SecretKeyFile { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::FilePath, self.file_path.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SecretKeyFile { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::FilePath) => self.file_path.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SecretKeyOptional { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SecretKeyOptional::None => true, + SecretKeyOptional::Value(inner) => inner.validate(errors), + SecretKeyOptional::EnvironmentVariable(inner) => inner.validate(errors), + SecretKeyOptional::File(inner) => inner.validate(errors), + } + } +} + +impl Default for SecretKeyOptional { + fn default() -> Self { + SecretKeyOptional::None + } +} + +impl Pickle for SecretKeyOptional { + fn pickle(&self, out: &mut Vec) { + match self { + SecretKeyOptional::None => { + 0u16.pickle(out); + } + SecretKeyOptional::Value(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SecretKeyOptional::EnvironmentVariable(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SecretKeyOptional::File(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SecretKeyOptional::None), + 1 => Pickle::unpickle(stream).map(SecretKeyOptional::Value), + 2 => Pickle::unpickle(stream).map(SecretKeyOptional::EnvironmentVariable), + 3 => Pickle::unpickle(stream).map(SecretKeyOptional::File), + _ => None, + } + } +} + +impl IntoValue for SecretKeyOptional { + fn into_value(self) -> JmapValue<'static> { + match self { + SecretKeyOptional::None => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("None".into())); + JmapValue::Object(obj) + } + SecretKeyOptional::Value(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Value".into())); + obj + } + SecretKeyOptional::EnvironmentVariable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into())); + obj + } + SecretKeyOptional::File(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("File".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SecretKeyOptional { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SecretKeyOptionalType::None => *self = SecretKeyOptional::None, + SecretKeyOptionalType::Value => { + *self = SecretKeyOptional::Value(Default::default()) + } + SecretKeyOptionalType::EnvironmentVariable => { + *self = SecretKeyOptional::EnvironmentVariable(Default::default()) + } + SecretKeyOptionalType::File => *self = SecretKeyOptional::File(Default::default()), + } + } + match self { + SecretKeyOptional::None => pointer.assert_eof(), + SecretKeyOptional::Value(inner) => inner.patch(pointer, value), + SecretKeyOptional::EnvironmentVariable(inner) => inner.patch(pointer, value), + SecretKeyOptional::File(inner) => inner.patch(pointer, value), + } + } +} + +impl SecretKeyOptional { + pub fn object_type(&self) -> SecretKeyOptionalType { + match self { + SecretKeyOptional::None => SecretKeyOptionalType::None, + SecretKeyOptional::Value(_) => SecretKeyOptionalType::Value, + SecretKeyOptional::EnvironmentVariable(_) => SecretKeyOptionalType::EnvironmentVariable, + SecretKeyOptional::File(_) => SecretKeyOptionalType::File, + } + } +} + +impl SecretKeyValue { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + errors.len() == neb + } +} + +impl Pickle for SecretKeyValue { + fn pickle(&self, out: &mut Vec) { + self.secret.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.secret = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SecretKeyValue { + fn default() -> Self { + Self { + secret: Default::default(), + } + } +} + +impl IntoValue for SecretKeyValue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SecretKeyValue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SecretText { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SecretText::Text(inner) => inner.validate(errors), + SecretText::EnvironmentVariable(inner) => inner.validate(errors), + SecretText::File(inner) => inner.validate(errors), + } + } +} + +impl Default for SecretText { + fn default() -> Self { + SecretText::Text(Default::default()) + } +} + +impl Pickle for SecretText { + fn pickle(&self, out: &mut Vec) { + match self { + SecretText::Text(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SecretText::EnvironmentVariable(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SecretText::File(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SecretText::Text), + 1 => Pickle::unpickle(stream).map(SecretText::EnvironmentVariable), + 2 => Pickle::unpickle(stream).map(SecretText::File), + _ => None, + } + } +} + +impl IntoValue for SecretText { + fn into_value(self) -> JmapValue<'static> { + match self { + SecretText::Text(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Text".into())); + obj + } + SecretText::EnvironmentVariable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into())); + obj + } + SecretText::File(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("File".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SecretText { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SecretTextType::Text => *self = SecretText::Text(Default::default()), + SecretTextType::EnvironmentVariable => { + *self = SecretText::EnvironmentVariable(Default::default()) + } + SecretTextType::File => *self = SecretText::File(Default::default()), + } + } + match self { + SecretText::Text(inner) => inner.patch(pointer, value), + SecretText::EnvironmentVariable(inner) => inner.patch(pointer, value), + SecretText::File(inner) => inner.patch(pointer, value), + } + } +} + +impl SecretText { + pub fn object_type(&self) -> SecretTextType { + match self { + SecretText::Text(_) => SecretTextType::Text, + SecretText::EnvironmentVariable(_) => SecretTextType::EnvironmentVariable, + SecretText::File(_) => SecretTextType::File, + } + } +} + +impl SecretTextOptional { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SecretTextOptional::None => true, + SecretTextOptional::Text(inner) => inner.validate(errors), + SecretTextOptional::EnvironmentVariable(inner) => inner.validate(errors), + SecretTextOptional::File(inner) => inner.validate(errors), + } + } +} + +impl Default for SecretTextOptional { + fn default() -> Self { + SecretTextOptional::None + } +} + +impl Pickle for SecretTextOptional { + fn pickle(&self, out: &mut Vec) { + match self { + SecretTextOptional::None => { + 0u16.pickle(out); + } + SecretTextOptional::Text(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SecretTextOptional::EnvironmentVariable(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SecretTextOptional::File(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SecretTextOptional::None), + 1 => Pickle::unpickle(stream).map(SecretTextOptional::Text), + 2 => Pickle::unpickle(stream).map(SecretTextOptional::EnvironmentVariable), + 3 => Pickle::unpickle(stream).map(SecretTextOptional::File), + _ => None, + } + } +} + +impl IntoValue for SecretTextOptional { + fn into_value(self) -> JmapValue<'static> { + match self { + SecretTextOptional::None => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("None".into())); + JmapValue::Object(obj) + } + SecretTextOptional::Text(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Text".into())); + obj + } + SecretTextOptional::EnvironmentVariable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("EnvironmentVariable".into())); + obj + } + SecretTextOptional::File(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("File".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SecretTextOptional { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SecretTextOptionalType::None => *self = SecretTextOptional::None, + SecretTextOptionalType::Text => { + *self = SecretTextOptional::Text(Default::default()) + } + SecretTextOptionalType::EnvironmentVariable => { + *self = SecretTextOptional::EnvironmentVariable(Default::default()) + } + SecretTextOptionalType::File => { + *self = SecretTextOptional::File(Default::default()) + } + } + } + match self { + SecretTextOptional::None => pointer.assert_eof(), + SecretTextOptional::Text(inner) => inner.patch(pointer, value), + SecretTextOptional::EnvironmentVariable(inner) => inner.patch(pointer, value), + SecretTextOptional::File(inner) => inner.patch(pointer, value), + } + } +} + +impl SecretTextOptional { + pub fn object_type(&self) -> SecretTextOptionalType { + match self { + SecretTextOptional::None => SecretTextOptionalType::None, + SecretTextOptional::Text(_) => SecretTextOptionalType::Text, + SecretTextOptional::EnvironmentVariable(_) => { + SecretTextOptionalType::EnvironmentVariable + } + SecretTextOptional::File(_) => SecretTextOptionalType::File, + } + } +} + +impl SecretTextValue { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::Secret)); + } + errors.len() == neb + } +} + +impl Pickle for SecretTextValue { + fn pickle(&self, out: &mut Vec) { + self.secret.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.secret = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SecretTextValue { + fn default() -> Self { + Self { + secret: Default::default(), + } + } +} + +impl IntoValue for SecretTextValue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Secret, JmapValue::Str(MASKED_PASSWORD.into())); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SecretTextValue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Secret) => self.secret.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Security { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Security; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.abuse_ban_rate { + value.validate(errors); + } + if let Some(value) = &self.auth_ban_rate { + value.validate(errors); + } + if let Some(value) = &self.loiter_ban_rate { + value.validate(errors); + } + let value = &self.scan_ban_paths; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ScanBanPaths)); + } + } + if let Some(value) = &self.scan_ban_rate { + value.validate(errors); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Security { + fn pickle(&self, out: &mut Vec) { + self.abuse_ban_rate.pickle(out); + self.abuse_ban_period.pickle(out); + self.auth_ban_rate.pickle(out); + self.auth_ban_period.pickle(out); + self.loiter_ban_rate.pickle(out); + self.loiter_ban_period.pickle(out); + self.scan_ban_paths.pickle(out); + self.scan_ban_rate.pickle(out); + self.scan_ban_period.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.abuse_ban_rate = Pickle::unpickle(stream)?; + this.abuse_ban_period = Pickle::unpickle(stream)?; + this.auth_ban_rate = Pickle::unpickle(stream)?; + this.auth_ban_period = Pickle::unpickle(stream)?; + this.loiter_ban_rate = Pickle::unpickle(stream)?; + this.loiter_ban_period = Pickle::unpickle(stream)?; + this.scan_ban_paths = Pickle::unpickle(stream)?; + this.scan_ban_rate = Pickle::unpickle(stream)?; + this.scan_ban_period = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Security { + fn default() -> Self { + Self { + abuse_ban_rate: Some(Rate { + count: 35u64, + period: Duration::from_millis(86400000), + }), + abuse_ban_period: Default::default(), + auth_ban_rate: Some(Rate { + count: 100u64, + period: Duration::from_millis(86400000), + }), + auth_ban_period: Default::default(), + loiter_ban_rate: Some(Rate { + count: 150u64, + period: Duration::from_millis(86400000), + }), + loiter_ban_period: Default::default(), + scan_ban_paths: Map::new(vec![ + "*.php*".to_string(), + "*.cgi*".to_string(), + "*.asp*".to_string(), + "*/wp-*".to_string(), + "*/php*".to_string(), + "*/cgi-bin*".to_string(), + "*xmlrpc*".to_string(), + "*../*".to_string(), + "*/..*".to_string(), + "*joomla*".to_string(), + "*wordpress*".to_string(), + "*drupal*".to_string(), + ]), + scan_ban_rate: Some(Rate { + count: 30u64, + period: Duration::from_millis(86400000), + }), + scan_ban_period: Default::default(), + } + } +} + +impl IntoValue for Security { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::AbuseBanRate, self.abuse_ban_rate.into_value()); + map.insert_unchecked(Property::AbuseBanPeriod, self.abuse_ban_period.into_value()); + map.insert_unchecked(Property::AuthBanRate, self.auth_ban_rate.into_value()); + map.insert_unchecked(Property::AuthBanPeriod, self.auth_ban_period.into_value()); + map.insert_unchecked(Property::LoiterBanRate, self.loiter_ban_rate.into_value()); + map.insert_unchecked( + Property::LoiterBanPeriod, + self.loiter_ban_period.into_value(), + ); + map.insert_unchecked(Property::ScanBanPaths, self.scan_ban_paths.into_value()); + map.insert_unchecked(Property::ScanBanRate, self.scan_ban_rate.into_value()); + map.insert_unchecked(Property::ScanBanPeriod, self.scan_ban_period.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Security { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AbuseBanRate) => self.abuse_ban_rate.patch(pointer, value), + Some(Property::AbuseBanPeriod) => self.abuse_ban_period.patch(pointer, value), + Some(Property::AuthBanRate) => self.auth_ban_rate.patch(pointer, value), + Some(Property::AuthBanPeriod) => self.auth_ban_period.patch(pointer, value), + Some(Property::LoiterBanRate) => self.loiter_ban_rate.patch(pointer, value), + Some(Property::LoiterBanPeriod) => self.loiter_ban_period.patch(pointer, value), + Some(Property::ScanBanPaths) => self + .scan_ban_paths + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ScanBanRate) => self.scan_ban_rate.patch(pointer, value), + Some(Property::ScanBanPeriod) => self.scan_ban_period.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SenderAuth { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SenderAuth; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.dkim_sign_domain; + value.validate(errors); + let value = &self.dkim_verify; + value.validate(errors); + let value = &self.spf_ehlo_verify; + value.validate(errors); + let value = &self.spf_from_verify; + value.validate(errors); + let value = &self.arc_verify; + value.validate(errors); + let value = &self.dmarc_verify; + value.validate(errors); + let value = &self.reverse_ip_verify; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl SenderAuth { + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "is_local_domain(sender_domain) && !is_empty(authenticated_as)" + .to_string(), + then: "sender_domain".to_string(), + }]), + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dkim_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_verify, + default: Some(Expression { + else_: "relaxed".to_string(), + match_: List::from_iter([]), + }), + property: Property::DkimVerify, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn ctx_spf_ehlo_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.spf_ehlo_verify, + default: Some(Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }), + property: Property::SpfEhloVerify, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn ctx_spf_from_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.spf_from_verify, + default: Some(Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }), + property: Property::SpfFromVerify, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn ctx_arc_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.arc_verify, + default: Some(Expression { + else_: "disable".to_string(), + match_: List::from_iter([]), + }), + property: Property::ArcVerify, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn ctx_dmarc_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dmarc_verify, + default: Some(Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }), + property: Property::DmarcVerify, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn ctx_reverse_ip_verify(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.reverse_ip_verify, + default: Some(Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }), + property: Property::ReverseIpVerify, + allowed_variables: MTA_CONNECTION_VARIABLE, + allowed_constants: MTA_VERIFY_CONSTANT, + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_dkim_sign_domain(), + self.ctx_dkim_verify(), + self.ctx_spf_ehlo_verify(), + self.ctx_spf_from_verify(), + self.ctx_arc_verify(), + self.ctx_dmarc_verify(), + self.ctx_reverse_ip_verify(), + ] + } +} + +impl Pickle for SenderAuth { + fn pickle(&self, out: &mut Vec) { + self.dkim_sign_domain.pickle(out); + self.dkim_strict.pickle(out); + self.dkim_verify.pickle(out); + self.spf_ehlo_verify.pickle(out); + self.spf_from_verify.pickle(out); + self.arc_verify.pickle(out); + self.dmarc_verify.pickle(out); + self.reverse_ip_verify.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.dkim_sign_domain = Pickle::unpickle(stream)?; + this.dkim_strict = Pickle::unpickle(stream)?; + this.dkim_verify = Pickle::unpickle(stream)?; + this.spf_ehlo_verify = Pickle::unpickle(stream)?; + this.spf_from_verify = Pickle::unpickle(stream)?; + this.arc_verify = Pickle::unpickle(stream)?; + this.dmarc_verify = Pickle::unpickle(stream)?; + this.reverse_ip_verify = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SenderAuth { + fn default() -> Self { + Self { + dkim_sign_domain: Expression { + else_: "false".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "is_local_domain(sender_domain) && !is_empty(authenticated_as)" + .to_string(), + then: "sender_domain".to_string(), + }]), + }, + dkim_strict: true, + dkim_verify: Expression { + else_: "relaxed".to_string(), + match_: List::from_iter([]), + }, + spf_ehlo_verify: Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }, + spf_from_verify: Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }, + arc_verify: Expression { + else_: "disable".to_string(), + match_: List::from_iter([]), + }, + dmarc_verify: Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }, + reverse_ip_verify: Expression { + else_: "disable".to_string(), + match_: List::from_iter([ExpressionMatch { + if_: "local_port == 25".to_string(), + then: "relaxed".to_string(), + }]), + }, + } + } +} + +impl IntoValue for SenderAuth { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + map.insert_unchecked(Property::DkimStrict, self.dkim_strict.into_value()); + map.insert_unchecked(Property::DkimVerify, self.dkim_verify.into_value()); + map.insert_unchecked(Property::SpfEhloVerify, self.spf_ehlo_verify.into_value()); + map.insert_unchecked(Property::SpfFromVerify, self.spf_from_verify.into_value()); + map.insert_unchecked(Property::ArcVerify, self.arc_verify.into_value()); + map.insert_unchecked(Property::DmarcVerify, self.dmarc_verify.into_value()); + map.insert_unchecked( + Property::ReverseIpVerify, + self.reverse_ip_verify.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SenderAuth { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::DkimStrict) => self.dkim_strict.patch(pointer, value), + Some(Property::DkimVerify) => self.dkim_verify.patch(pointer, value), + Some(Property::SpfEhloVerify) => self.spf_ehlo_verify.patch(pointer, value), + Some(Property::SpfFromVerify) => self.spf_from_verify.patch(pointer, value), + Some(Property::ArcVerify) => self.arc_verify.patch(pointer, value), + Some(Property::DmarcVerify) => self.dmarc_verify.patch(pointer, value), + Some(Property::ReverseIpVerify) => self.reverse_ip_verify.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ServerResponse { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.response_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseHostname)); + } + } + if let Some(value) = &self.response_code { + if *value < 100 { + errors.push(ValidationError::min_value(Property::ResponseCode, 100)); + } + if *value > 599 { + errors.push(ValidationError::max_value(Property::ResponseCode, 599)); + } + } + if let Some(value) = &self.response_enhanced { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseEnhanced)); + } + } + if let Some(value) = &self.response_message { + if value.is_empty() { + errors.push(ValidationError::required(Property::ResponseMessage)); + } + } + errors.len() == neb + } +} + +impl Pickle for ServerResponse { + fn pickle(&self, out: &mut Vec) { + self.response_hostname.pickle(out); + self.response_code.pickle(out); + self.response_enhanced.pickle(out); + self.response_message.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.response_hostname = Pickle::unpickle(stream)?; + this.response_code = Pickle::unpickle(stream)?; + this.response_enhanced = Pickle::unpickle(stream)?; + this.response_message = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ServerResponse { + fn default() -> Self { + Self { + response_hostname: Default::default(), + response_code: Default::default(), + response_enhanced: Default::default(), + response_message: Default::default(), + } + } +} + +impl IntoValue for ServerResponse { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked( + Property::ResponseHostname, + self.response_hostname.into_value(), + ); + map.insert_unchecked(Property::ResponseCode, self.response_code.into_value()); + map.insert_unchecked( + Property::ResponseEnhanced, + self.response_enhanced.into_value(), + ); + map.insert_unchecked( + Property::ResponseMessage, + self.response_message.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ServerResponse { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ResponseHostname) => self.response_hostname.patch(pointer, value), + Some(Property::ResponseCode) => self.response_code.patch(pointer, value), + Some(Property::ResponseEnhanced) => self.response_enhanced.patch(pointer, value), + Some(Property::ResponseMessage) => self.response_message.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl Service { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::Hostname)); + } + } + errors.len() == neb + } +} + +impl Pickle for Service { + fn pickle(&self, out: &mut Vec) { + self.hostname.pickle(out); + self.cleartext.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.hostname = Pickle::unpickle(stream)?; + this.cleartext = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Service { + fn default() -> Self { + Self { + hostname: Default::default(), + cleartext: false, + } + } +} + +impl IntoValue for Service { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Hostname, self.hostname.into_value()); + map.insert_unchecked(Property::Cleartext, self.cleartext.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Service { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Hostname) => self + .hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::Cleartext) => self.cleartext.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ShardedBlobStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.stores; + for value in value.values() { + value.validate(errors); + } + if value.len() < 2 { + errors.push(ValidationError::min_items(Property::Stores, 2)); + } + errors.len() == neb + } +} + +impl Pickle for ShardedBlobStore { + fn pickle(&self, out: &mut Vec) { + self.stores.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.stores = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ShardedBlobStore { + fn default() -> Self { + Self { + stores: Default::default(), + } + } +} + +impl IntoValue for ShardedBlobStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Stores, self.stores.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ShardedBlobStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Stores) => self.stores.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ShardedInMemoryStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.stores; + for value in value.values() { + value.validate(errors); + } + if value.len() < 2 { + errors.push(ValidationError::min_items(Property::Stores, 2)); + } + errors.len() == neb + } +} + +impl Pickle for ShardedInMemoryStore { + fn pickle(&self, out: &mut Vec) { + self.stores.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.stores = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ShardedInMemoryStore { + fn default() -> Self { + Self { + stores: Default::default(), + } + } +} + +impl IntoValue for ShardedInMemoryStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Stores, self.stores.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ShardedInMemoryStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Stores) => self.stores.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Sharing { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Sharing; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_shares; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxShares, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Sharing { + fn pickle(&self, out: &mut Vec) { + self.allow_directory_queries.pickle(out); + self.max_shares.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_directory_queries = Pickle::unpickle(stream)?; + this.max_shares = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Sharing { + fn default() -> Self { + Self { + allow_directory_queries: false, + max_shares: 10u64, + } + } +} + +impl IntoValue for Sharing { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked( + Property::AllowDirectoryQueries, + self.allow_directory_queries.into_value(), + ); + map.insert_unchecked(Property::MaxShares, self.max_shares.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Sharing { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowDirectoryQueries) => { + self.allow_directory_queries.patch(pointer, value) + } + Some(Property::MaxShares) => self.max_shares.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SieveSystemInterpreter { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SieveSystemInterpreter; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.default_from_address; + value.validate(errors); + let value = &self.default_from_name; + value.validate(errors); + if let Some(value) = &self.message_id_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::MessageIdHostname)); + } + } + let value = &self.default_return_path; + value.validate(errors); + let value = &self.dkim_sign_domain; + value.validate(errors); + let value = &self.max_cpu_cycles; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxCpuCycles, 1)); + } + let value = &self.max_nested_includes; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxNestedIncludes, 1)); + } + let value = &self.max_received_headers; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxReceivedHeaders, 1)); + } + let value = &self.max_var_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxVarSize, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl SieveSystemInterpreter { + pub fn ctx_default_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.default_from_address, + default: Some(Expression { + else_: "'MAILER-DAEMON@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::DefaultFromAddress, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_default_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.default_from_name, + default: Some(Expression { + else_: "'Automated Message'".to_string(), + ..Default::default() + }), + property: Property::DefaultFromName, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_default_return_path(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.default_return_path, + default: None, + property: Property::DefaultReturnPath, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_RCPT_TO_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_default_from_address(), + self.ctx_default_from_name(), + self.ctx_default_return_path(), + self.ctx_dkim_sign_domain(), + ] + } +} + +impl Pickle for SieveSystemInterpreter { + fn pickle(&self, out: &mut Vec) { + self.default_from_address.pickle(out); + self.default_from_name.pickle(out); + self.message_id_hostname.pickle(out); + self.duplicate_expiry.pickle(out); + self.no_capability_check.pickle(out); + self.default_return_path.pickle(out); + self.dkim_sign_domain.pickle(out); + self.max_cpu_cycles.pickle(out); + self.max_nested_includes.pickle(out); + self.max_out_messages.pickle(out); + self.max_received_headers.pickle(out); + self.max_redirects.pickle(out); + self.max_var_size.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.default_from_address = Pickle::unpickle(stream)?; + this.default_from_name = Pickle::unpickle(stream)?; + this.message_id_hostname = Pickle::unpickle(stream)?; + this.duplicate_expiry = Pickle::unpickle(stream)?; + this.no_capability_check = Pickle::unpickle(stream)?; + this.default_return_path = Pickle::unpickle(stream)?; + this.dkim_sign_domain = Pickle::unpickle(stream)?; + this.max_cpu_cycles = Pickle::unpickle(stream)?; + this.max_nested_includes = Pickle::unpickle(stream)?; + this.max_out_messages = Pickle::unpickle(stream)?; + this.max_received_headers = Pickle::unpickle(stream)?; + this.max_redirects = Pickle::unpickle(stream)?; + this.max_var_size = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SieveSystemInterpreter { + fn default() -> Self { + Self { + default_from_address: Expression { + else_: "'MAILER-DAEMON@' + system('domain')".to_string(), + ..Default::default() + }, + default_from_name: Expression { + else_: "'Automated Message'".to_string(), + ..Default::default() + }, + message_id_hostname: Default::default(), + duplicate_expiry: Duration::from_millis(604800000), + no_capability_check: true, + default_return_path: Default::default(), + dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + max_cpu_cycles: 1048576u64, + max_nested_includes: 5u64, + max_out_messages: 5u64, + max_received_headers: 50u64, + max_redirects: 3u64, + max_var_size: 52428800u64, + } + } +} + +impl IntoValue for SieveSystemInterpreter { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked( + Property::DefaultFromAddress, + self.default_from_address.into_value(), + ); + map.insert_unchecked( + Property::DefaultFromName, + self.default_from_name.into_value(), + ); + map.insert_unchecked( + Property::MessageIdHostname, + self.message_id_hostname.into_value(), + ); + map.insert_unchecked( + Property::DuplicateExpiry, + self.duplicate_expiry.into_value(), + ); + map.insert_unchecked( + Property::NoCapabilityCheck, + self.no_capability_check.into_value(), + ); + map.insert_unchecked( + Property::DefaultReturnPath, + self.default_return_path.into_value(), + ); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + map.insert_unchecked(Property::MaxCpuCycles, self.max_cpu_cycles.into_value()); + map.insert_unchecked( + Property::MaxNestedIncludes, + self.max_nested_includes.into_value(), + ); + map.insert_unchecked(Property::MaxOutMessages, self.max_out_messages.into_value()); + map.insert_unchecked( + Property::MaxReceivedHeaders, + self.max_received_headers.into_value(), + ); + map.insert_unchecked(Property::MaxRedirects, self.max_redirects.into_value()); + map.insert_unchecked(Property::MaxVarSize, self.max_var_size.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SieveSystemInterpreter { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DefaultFromAddress) => self.default_from_address.patch(pointer, value), + Some(Property::DefaultFromName) => self.default_from_name.patch(pointer, value), + Some(Property::MessageIdHostname) => self + .message_id_hostname + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DuplicateExpiry) => self.duplicate_expiry.patch(pointer, value), + Some(Property::NoCapabilityCheck) => self.no_capability_check.patch(pointer, value), + Some(Property::DefaultReturnPath) => self.default_return_path.patch(pointer, value), + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::MaxCpuCycles) => self.max_cpu_cycles.patch(pointer, value), + Some(Property::MaxNestedIncludes) => self.max_nested_includes.patch(pointer, value), + Some(Property::MaxOutMessages) => self.max_out_messages.patch(pointer, value), + Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value), + Some(Property::MaxRedirects) => self.max_redirects.patch(pointer, value), + Some(Property::MaxVarSize) => self.max_var_size.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SieveSystemScript { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SieveSystemScript; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.contents; + if value.is_empty() { + errors.push(ValidationError::required(Property::Contents)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for SieveSystemScript { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.is_active.pickle(out); + self.contents.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.is_active = Pickle::unpickle(stream)?; + this.contents = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SieveSystemScript { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + is_active: false, + contents: Default::default(), + } + } +} + +impl IntoValue for SieveSystemScript { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::IsActive, self.is_active.into_value()); + map.insert_unchecked(Property::Contents, self.contents.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SieveSystemScript { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self + .name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::IsActive) => self.is_active.patch(pointer, value), + Some(Property::Contents) => self + .contents + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SieveUserInterpreter { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SieveUserInterpreter; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.allowed_notify_uris; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::AllowedNotifyUris)); + } + } + let value = &self.protected_headers; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ProtectedHeaders)); + } + } + let value = &self.default_subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultSubject)); + } + let value = &self.default_subject_prefix; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultSubjectPrefix)); + } + let value = &self.max_cpu_cycles; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxCpuCycles, 1)); + } + let value = &self.max_header_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxHeaderSize, 1)); + } + let value = &self.max_includes; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxIncludes, 1)); + } + let value = &self.max_local_vars; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxLocalVars, 1)); + } + let value = &self.max_match_vars; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxMatchVars, 1)); + } + let value = &self.max_script_name_length; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxScriptNameLength, 1)); + } + let value = &self.max_nested_blocks; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxNestedBlocks, 1)); + } + let value = &self.max_nested_for_every; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxNestedForEvery, 1)); + } + let value = &self.max_nested_includes; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxNestedIncludes, 1)); + } + let value = &self.max_nested_tests; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxNestedTests, 1)); + } + let value = &self.max_received_headers; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxReceivedHeaders, 1)); + } + let value = &self.max_script_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxScriptSize, 1)); + } + let value = &self.max_string_length; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxStringLength, 1)); + } + let value = &self.max_var_name_length; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxVarNameLength, 1)); + } + let value = &self.max_var_size; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxVarSize, 1)); + } + if let Some(value) = &self.max_scripts { + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxScripts, 1)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for SieveUserInterpreter { + fn pickle(&self, out: &mut Vec) { + self.default_expiry_duplicate.pickle(out); + self.default_expiry_vacation.pickle(out); + self.disable_capabilities.pickle(out); + self.allowed_notify_uris.pickle(out); + self.protected_headers.pickle(out); + self.default_subject.pickle(out); + self.default_subject_prefix.pickle(out); + self.max_cpu_cycles.pickle(out); + self.max_header_size.pickle(out); + self.max_includes.pickle(out); + self.max_local_vars.pickle(out); + self.max_match_vars.pickle(out); + self.max_script_name_length.pickle(out); + self.max_nested_blocks.pickle(out); + self.max_nested_for_every.pickle(out); + self.max_nested_includes.pickle(out); + self.max_nested_tests.pickle(out); + self.max_out_messages.pickle(out); + self.max_received_headers.pickle(out); + self.max_redirects.pickle(out); + self.max_script_size.pickle(out); + self.max_string_length.pickle(out); + self.max_var_name_length.pickle(out); + self.max_var_size.pickle(out); + self.max_scripts.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.default_expiry_duplicate = Pickle::unpickle(stream)?; + this.default_expiry_vacation = Pickle::unpickle(stream)?; + this.disable_capabilities = Pickle::unpickle(stream)?; + this.allowed_notify_uris = Pickle::unpickle(stream)?; + this.protected_headers = Pickle::unpickle(stream)?; + this.default_subject = Pickle::unpickle(stream)?; + this.default_subject_prefix = Pickle::unpickle(stream)?; + this.max_cpu_cycles = Pickle::unpickle(stream)?; + this.max_header_size = Pickle::unpickle(stream)?; + this.max_includes = Pickle::unpickle(stream)?; + this.max_local_vars = Pickle::unpickle(stream)?; + this.max_match_vars = Pickle::unpickle(stream)?; + this.max_script_name_length = Pickle::unpickle(stream)?; + this.max_nested_blocks = Pickle::unpickle(stream)?; + this.max_nested_for_every = Pickle::unpickle(stream)?; + this.max_nested_includes = Pickle::unpickle(stream)?; + this.max_nested_tests = Pickle::unpickle(stream)?; + this.max_out_messages = Pickle::unpickle(stream)?; + this.max_received_headers = Pickle::unpickle(stream)?; + this.max_redirects = Pickle::unpickle(stream)?; + this.max_script_size = Pickle::unpickle(stream)?; + this.max_string_length = Pickle::unpickle(stream)?; + this.max_var_name_length = Pickle::unpickle(stream)?; + this.max_var_size = Pickle::unpickle(stream)?; + this.max_scripts = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SieveUserInterpreter { + fn default() -> Self { + Self { + default_expiry_duplicate: Duration::from_millis(604800000), + default_expiry_vacation: Duration::from_millis(2592000000), + disable_capabilities: Default::default(), + allowed_notify_uris: Map::new(vec!["mailto".to_string()]), + protected_headers: Map::new(vec![ + "Original-Subject".to_string(), + "Original-From".to_string(), + "Received".to_string(), + "Auto-Submitted".to_string(), + ]), + default_subject: "Automated reply".to_string(), + default_subject_prefix: "Auto: ".to_string(), + max_cpu_cycles: 5000u64, + max_header_size: 1024u64, + max_includes: 3u64, + max_local_vars: 128u64, + max_match_vars: 30u64, + max_script_name_length: 512u64, + max_nested_blocks: 15u64, + max_nested_for_every: 3u64, + max_nested_includes: 3u64, + max_nested_tests: 15u64, + max_out_messages: 3u64, + max_received_headers: 10u64, + max_redirects: 1u64, + max_script_size: 102400, + max_string_length: 4096u64, + max_var_name_length: 32u64, + max_var_size: 4096u64, + max_scripts: Some(100u64), + } + } +} + +impl IntoValue for SieveUserInterpreter { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(27); + map.insert_unchecked( + Property::DefaultExpiryDuplicate, + self.default_expiry_duplicate.into_value(), + ); + map.insert_unchecked( + Property::DefaultExpiryVacation, + self.default_expiry_vacation.into_value(), + ); + map.insert_unchecked( + Property::DisableCapabilities, + self.disable_capabilities.into_value(), + ); + map.insert_unchecked( + Property::AllowedNotifyUris, + self.allowed_notify_uris.into_value(), + ); + map.insert_unchecked( + Property::ProtectedHeaders, + self.protected_headers.into_value(), + ); + map.insert_unchecked(Property::DefaultSubject, self.default_subject.into_value()); + map.insert_unchecked( + Property::DefaultSubjectPrefix, + self.default_subject_prefix.into_value(), + ); + map.insert_unchecked(Property::MaxCpuCycles, self.max_cpu_cycles.into_value()); + map.insert_unchecked(Property::MaxHeaderSize, self.max_header_size.into_value()); + map.insert_unchecked(Property::MaxIncludes, self.max_includes.into_value()); + map.insert_unchecked(Property::MaxLocalVars, self.max_local_vars.into_value()); + map.insert_unchecked(Property::MaxMatchVars, self.max_match_vars.into_value()); + map.insert_unchecked( + Property::MaxScriptNameLength, + self.max_script_name_length.into_value(), + ); + map.insert_unchecked( + Property::MaxNestedBlocks, + self.max_nested_blocks.into_value(), + ); + map.insert_unchecked( + Property::MaxNestedForEvery, + self.max_nested_for_every.into_value(), + ); + map.insert_unchecked( + Property::MaxNestedIncludes, + self.max_nested_includes.into_value(), + ); + map.insert_unchecked(Property::MaxNestedTests, self.max_nested_tests.into_value()); + map.insert_unchecked(Property::MaxOutMessages, self.max_out_messages.into_value()); + map.insert_unchecked( + Property::MaxReceivedHeaders, + self.max_received_headers.into_value(), + ); + map.insert_unchecked(Property::MaxRedirects, self.max_redirects.into_value()); + map.insert_unchecked(Property::MaxScriptSize, self.max_script_size.into_value()); + map.insert_unchecked( + Property::MaxStringLength, + self.max_string_length.into_value(), + ); + map.insert_unchecked( + Property::MaxVarNameLength, + self.max_var_name_length.into_value(), + ); + map.insert_unchecked(Property::MaxVarSize, self.max_var_size.into_value()); + map.insert_unchecked(Property::MaxScripts, self.max_scripts.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SieveUserInterpreter { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DefaultExpiryDuplicate) => { + self.default_expiry_duplicate.patch(pointer, value) + } + Some(Property::DefaultExpiryVacation) => { + self.default_expiry_vacation.patch(pointer, value) + } + Some(Property::DisableCapabilities) => self.disable_capabilities.patch(pointer, value), + Some(Property::AllowedNotifyUris) => self + .allowed_notify_uris + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ProtectedHeaders) => self + .protected_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DefaultSubject) => self + .default_subject + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::DefaultSubjectPrefix) => { + self.default_subject_prefix.patch(pointer, value) + } + Some(Property::MaxCpuCycles) => self.max_cpu_cycles.patch(pointer, value), + Some(Property::MaxHeaderSize) => self.max_header_size.patch(pointer, value), + Some(Property::MaxIncludes) => self.max_includes.patch(pointer, value), + Some(Property::MaxLocalVars) => self.max_local_vars.patch(pointer, value), + Some(Property::MaxMatchVars) => self.max_match_vars.patch(pointer, value), + Some(Property::MaxScriptNameLength) => { + self.max_script_name_length.patch(pointer, value) + } + Some(Property::MaxNestedBlocks) => self.max_nested_blocks.patch(pointer, value), + Some(Property::MaxNestedForEvery) => self.max_nested_for_every.patch(pointer, value), + Some(Property::MaxNestedIncludes) => self.max_nested_includes.patch(pointer, value), + Some(Property::MaxNestedTests) => self.max_nested_tests.patch(pointer, value), + Some(Property::MaxOutMessages) => self.max_out_messages.patch(pointer, value), + Some(Property::MaxReceivedHeaders) => self.max_received_headers.patch(pointer, value), + Some(Property::MaxRedirects) => self.max_redirects.patch(pointer, value), + Some(Property::MaxScriptSize) => self.max_script_size.patch(pointer, value), + Some(Property::MaxStringLength) => self.max_string_length.patch(pointer, value), + Some(Property::MaxVarNameLength) => self.max_var_name_length.patch(pointer, value), + Some(Property::MaxVarSize) => self.max_var_size.patch(pointer, value), + Some(Property::MaxScripts) => self.max_scripts.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SieveUserScript { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SieveUserScript; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.contents; + if value.is_empty() { + errors.push(ValidationError::required(Property::Contents)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl Pickle for SieveUserScript { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.description.pickle(out); + self.is_active.pickle(out); + self.contents.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.is_active = Pickle::unpickle(stream)?; + this.contents = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SieveUserScript { + fn default() -> Self { + Self { + name: Default::default(), + description: Default::default(), + is_active: false, + contents: Default::default(), + } + } +} + +impl IntoValue for SieveUserScript { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::IsActive, self.is_active.into_value()); + map.insert_unchecked(Property::Contents, self.contents.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SieveUserScript { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self + .name + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::IsActive) => self.is_active.patch(pointer, value), + Some(Property::Contents) => self + .contents + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamClassifier { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamClassifier; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.model; + value.validate(errors); + let value = &self.learn_spam_from_rbl_hits; + if *value > 100 { + errors.push(ValidationError::max_value( + Property::LearnSpamFromRblHits, + 100, + )); + } + let value = &self.min_ham_samples; + if *value > 10000 { + errors.push(ValidationError::max_value(Property::MinHamSamples, 10000)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MinHamSamples, 1)); + } + let value = &self.min_spam_samples; + if *value > 10000 { + errors.push(ValidationError::max_value(Property::MinSpamSamples, 10000)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::MinSpamSamples, 1)); + } + let value = &self.reservoir_capacity; + if *value > 100000 { + errors.push(ValidationError::max_value( + Property::ReservoirCapacity, + 100000, + )); + } + if *value < 100 { + errors.push(ValidationError::min_value(Property::ReservoirCapacity, 100)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for SpamClassifier { + fn pickle(&self, out: &mut Vec) { + self.model.pickle(out); + self.learn_ham_from_card.pickle(out); + self.learn_spam_from_rbl_hits.pickle(out); + self.learn_spam_from_traps.pickle(out); + self.hold_samples_for.pickle(out); + self.min_ham_samples.pickle(out); + self.min_spam_samples.pickle(out); + self.reservoir_capacity.pickle(out); + self.train_frequency.pickle(out); + self.learn_ham_from_reply.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.model = Pickle::unpickle(stream)?; + this.learn_ham_from_card = Pickle::unpickle(stream)?; + this.learn_spam_from_rbl_hits = Pickle::unpickle(stream)?; + this.learn_spam_from_traps = Pickle::unpickle(stream)?; + this.hold_samples_for = Pickle::unpickle(stream)?; + this.min_ham_samples = Pickle::unpickle(stream)?; + this.min_spam_samples = Pickle::unpickle(stream)?; + this.reservoir_capacity = Pickle::unpickle(stream)?; + this.train_frequency = Pickle::unpickle(stream)?; + this.learn_ham_from_reply = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamClassifier { + fn default() -> Self { + Self { + model: Default::default(), + learn_ham_from_card: true, + learn_spam_from_rbl_hits: 2u64, + learn_spam_from_traps: true, + hold_samples_for: Duration::from_millis(15552000000), + min_ham_samples: 100u64, + min_spam_samples: 100u64, + reservoir_capacity: 1024u64, + train_frequency: Some(Duration::from_millis(43200000)), + learn_ham_from_reply: true, + } + } +} + +impl IntoValue for SpamClassifier { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::Model, self.model.into_value()); + map.insert_unchecked( + Property::LearnHamFromCard, + self.learn_ham_from_card.into_value(), + ); + map.insert_unchecked( + Property::LearnSpamFromRblHits, + self.learn_spam_from_rbl_hits.into_value(), + ); + map.insert_unchecked( + Property::LearnSpamFromTraps, + self.learn_spam_from_traps.into_value(), + ); + map.insert_unchecked(Property::HoldSamplesFor, self.hold_samples_for.into_value()); + map.insert_unchecked(Property::MinHamSamples, self.min_ham_samples.into_value()); + map.insert_unchecked(Property::MinSpamSamples, self.min_spam_samples.into_value()); + map.insert_unchecked( + Property::ReservoirCapacity, + self.reservoir_capacity.into_value(), + ); + map.insert_unchecked(Property::TrainFrequency, self.train_frequency.into_value()); + map.insert_unchecked( + Property::LearnHamFromReply, + self.learn_ham_from_reply.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamClassifier { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Model) => self.model.patch(pointer, value), + Some(Property::LearnHamFromCard) => self.learn_ham_from_card.patch(pointer, value), + Some(Property::LearnSpamFromRblHits) => { + self.learn_spam_from_rbl_hits.patch(pointer, value) + } + Some(Property::LearnSpamFromTraps) => self.learn_spam_from_traps.patch(pointer, value), + Some(Property::HoldSamplesFor) => self.hold_samples_for.patch(pointer, value), + Some(Property::MinHamSamples) => self.min_ham_samples.patch(pointer, value), + Some(Property::MinSpamSamples) => self.min_spam_samples.patch(pointer, value), + Some(Property::ReservoirCapacity) => self.reservoir_capacity.patch(pointer, value), + Some(Property::TrainFrequency) => self.train_frequency.patch(pointer, value), + Some(Property::LearnHamFromReply) => self.learn_ham_from_reply.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamClassifierFtrlCcfh { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.indicator_parameters; + value.validate(errors); + let value = &self.parameters; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for SpamClassifierFtrlCcfh { + fn pickle(&self, out: &mut Vec) { + self.indicator_parameters.pickle(out); + self.parameters.pickle(out); + self.feature_l2_normalize.pickle(out); + self.feature_log_scale.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.indicator_parameters = Pickle::unpickle(stream)?; + this.parameters = Pickle::unpickle(stream)?; + this.feature_l2_normalize = Pickle::unpickle(stream)?; + this.feature_log_scale = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamClassifierFtrlCcfh { + fn default() -> Self { + Self { + indicator_parameters: FtrlParameters { + num_features: ModelSize::V18, + ..Default::default() + }, + parameters: FtrlParameters { + num_features: ModelSize::V20, + ..Default::default() + }, + feature_l2_normalize: true, + feature_log_scale: true, + } + } +} + +impl IntoValue for SpamClassifierFtrlCcfh { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked( + Property::IndicatorParameters, + self.indicator_parameters.into_value(), + ); + map.insert_unchecked(Property::Parameters, self.parameters.into_value()); + map.insert_unchecked( + Property::FeatureL2Normalize, + self.feature_l2_normalize.into_value(), + ); + map.insert_unchecked( + Property::FeatureLogScale, + self.feature_log_scale.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamClassifierFtrlCcfh { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::IndicatorParameters) => self.indicator_parameters.patch(pointer, value), + Some(Property::Parameters) => self.parameters.patch(pointer, value), + Some(Property::FeatureL2Normalize) => self.feature_l2_normalize.patch(pointer, value), + Some(Property::FeatureLogScale) => self.feature_log_scale.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamClassifierFtrlFh { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.parameters; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for SpamClassifierFtrlFh { + fn pickle(&self, out: &mut Vec) { + self.parameters.pickle(out); + self.feature_l2_normalize.pickle(out); + self.feature_log_scale.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.parameters = Pickle::unpickle(stream)?; + this.feature_l2_normalize = Pickle::unpickle(stream)?; + this.feature_log_scale = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamClassifierFtrlFh { + fn default() -> Self { + Self { + parameters: FtrlParameters { + num_features: ModelSize::V20, + ..Default::default() + }, + feature_l2_normalize: true, + feature_log_scale: true, + } + } +} + +impl IntoValue for SpamClassifierFtrlFh { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Parameters, self.parameters.into_value()); + map.insert_unchecked( + Property::FeatureL2Normalize, + self.feature_l2_normalize.into_value(), + ); + map.insert_unchecked( + Property::FeatureLogScale, + self.feature_log_scale.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamClassifierFtrlFh { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Parameters) => self.parameters.patch(pointer, value), + Some(Property::FeatureL2Normalize) => self.feature_l2_normalize.patch(pointer, value), + Some(Property::FeatureLogScale) => self.feature_log_scale.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamClassifierModel { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SpamClassifierModel::FtrlFh(inner) => inner.validate(errors), + SpamClassifierModel::FtrlCcfh(inner) => inner.validate(errors), + SpamClassifierModel::Disabled => true, + } + } +} + +impl Default for SpamClassifierModel { + fn default() -> Self { + SpamClassifierModel::FtrlFh(Default::default()) + } +} + +impl Pickle for SpamClassifierModel { + fn pickle(&self, out: &mut Vec) { + match self { + SpamClassifierModel::FtrlFh(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SpamClassifierModel::FtrlCcfh(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SpamClassifierModel::Disabled => { + 2u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SpamClassifierModel::FtrlFh), + 1 => Pickle::unpickle(stream).map(SpamClassifierModel::FtrlCcfh), + 2 => Some(SpamClassifierModel::Disabled), + _ => None, + } + } +} + +impl IntoValue for SpamClassifierModel { + fn into_value(self) -> JmapValue<'static> { + match self { + SpamClassifierModel::FtrlFh(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FtrlFh".into())); + obj + } + SpamClassifierModel::FtrlCcfh(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FtrlCcfh".into())); + obj + } + SpamClassifierModel::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for SpamClassifierModel { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SpamClassifierModelType::FtrlFh => { + *self = SpamClassifierModel::FtrlFh(Default::default()) + } + SpamClassifierModelType::FtrlCcfh => { + *self = SpamClassifierModel::FtrlCcfh(Default::default()) + } + SpamClassifierModelType::Disabled => *self = SpamClassifierModel::Disabled, + } + } + match self { + SpamClassifierModel::FtrlFh(inner) => inner.patch(pointer, value), + SpamClassifierModel::FtrlCcfh(inner) => inner.patch(pointer, value), + SpamClassifierModel::Disabled => pointer.assert_eof(), + } + } +} + +impl SpamClassifierModel { + pub fn object_type(&self) -> SpamClassifierModelType { + match self { + SpamClassifierModel::FtrlFh(_) => SpamClassifierModelType::FtrlFh, + SpamClassifierModel::FtrlCcfh(_) => SpamClassifierModelType::FtrlCcfh, + SpamClassifierModel::Disabled => SpamClassifierModelType::Disabled, + } + } +} + +impl SpamClassify { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.message; + if value.is_empty() { + errors.push(ValidationError::required(Property::Message)); + } + let value = &self.remote_ip; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::RemoteIp, value)); + } + let value = &self.ehlo_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::EhloDomain)); + } + if let Some(value) = &self.authenticated_as { + if value.is_empty() { + errors.push(ValidationError::required(Property::AuthenticatedAs)); + } + } + let value = &self.env_from; + if value.is_empty() { + errors.push(ValidationError::required(Property::EnvFrom)); + } + let value = &self.env_rcpt_to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::EnvRcptTo)); + } + } + let value = &self.tags; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for SpamClassify { + fn pickle(&self, out: &mut Vec) { + self.message.pickle(out); + self.remote_ip.pickle(out); + self.ehlo_domain.pickle(out); + self.authenticated_as.pickle(out); + self.is_tls.pickle(out); + self.env_from.pickle(out); + self.env_from_parameters.pickle(out); + self.env_rcpt_to.pickle(out); + self.score.pickle(out); + self.tags.pickle(out); + self.result.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.message = Pickle::unpickle(stream)?; + this.remote_ip = Pickle::unpickle(stream)?; + this.ehlo_domain = Pickle::unpickle(stream)?; + this.authenticated_as = Pickle::unpickle(stream)?; + this.is_tls = Pickle::unpickle(stream)?; + this.env_from = Pickle::unpickle(stream)?; + this.env_from_parameters = Pickle::unpickle(stream)?; + this.env_rcpt_to = Pickle::unpickle(stream)?; + this.score = Pickle::unpickle(stream)?; + this.tags = Pickle::unpickle(stream)?; + this.result = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamClassify { + fn default() -> Self { + Self { + message: Default::default(), + remote_ip: Default::default(), + ehlo_domain: Default::default(), + authenticated_as: Default::default(), + is_tls: true, + env_from: Default::default(), + env_from_parameters: Default::default(), + env_rcpt_to: Default::default(), + score: Float::new(0.0f64), + tags: Default::default(), + result: Default::default(), + } + } +} + +impl IntoValue for SpamClassify { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::Message, self.message.into_value()); + map.insert_unchecked(Property::RemoteIp, self.remote_ip.into_value()); + map.insert_unchecked(Property::EhloDomain, self.ehlo_domain.into_value()); + map.insert_unchecked( + Property::AuthenticatedAs, + self.authenticated_as.into_value(), + ); + map.insert_unchecked(Property::IsTls, self.is_tls.into_value()); + map.insert_unchecked(Property::EnvFrom, self.env_from.into_value()); + map.insert_unchecked( + Property::EnvFromParameters, + self.env_from_parameters.into_value(), + ); + map.insert_unchecked(Property::EnvRcptTo, self.env_rcpt_to.into_value()); + map.insert_unchecked(Property::Score, self.score.into_value()); + map.insert_unchecked(Property::Tags, self.tags.into_value()); + map.insert_unchecked(Property::Result, self.result.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamClassify { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Message) => self.message.patch(pointer, value), + Some(Property::RemoteIp) => self.remote_ip.patch(pointer, value), + Some(Property::EhloDomain) => self.ehlo_domain.patch(pointer, value), + Some(Property::AuthenticatedAs) => self.authenticated_as.patch(pointer, value), + Some(Property::IsTls) => self.is_tls.patch(pointer, value), + Some(Property::EnvFrom) => self + .env_from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::EnvFromParameters) => self.env_from_parameters.patch(pointer, value), + Some(Property::EnvRcptTo) => self + .env_rcpt_to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Score) => pointer.assert_server_set(), + Some(Property::Tags) => pointer.assert_server_set(), + Some(Property::Result) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamClassifyTag { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for SpamClassifyTag { + fn pickle(&self, out: &mut Vec) { + self.score.pickle(out); + self.disposition.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.score = Pickle::unpickle(stream)?; + this.disposition = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamClassifyTag { + fn default() -> Self { + Self { + score: Float::new(0.0f64), + disposition: Default::default(), + } + } +} + +impl IntoValue for SpamClassifyTag { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Score, self.score.into_value()); + map.insert_unchecked(Property::Disposition, self.disposition.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamClassifyTag { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Score) => pointer.assert_server_set(), + Some(Property::Disposition) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamDnsblServer { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamDnsblServer; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SpamDnsblServer::Any(inner) => inner.validate(errors), + SpamDnsblServer::Url(inner) => inner.validate(errors), + SpamDnsblServer::Domain(inner) => inner.validate(errors), + SpamDnsblServer::Email(inner) => inner.validate(errors), + SpamDnsblServer::Ip(inner) => inner.validate(errors), + SpamDnsblServer::Header(inner) => inner.validate(errors), + SpamDnsblServer::Body(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + SpamDnsblServer::Any(object) => { + object.index(i); + } + SpamDnsblServer::Url(object) => { + object.index(i); + } + SpamDnsblServer::Domain(object) => { + object.index(i); + } + SpamDnsblServer::Email(object) => { + object.index(i); + } + SpamDnsblServer::Ip(object) => { + object.index(i); + } + SpamDnsblServer::Header(object) => { + object.index(i); + } + SpamDnsblServer::Body(object) => { + object.index(i); + } + } + } +} + +impl Default for SpamDnsblServer { + fn default() -> Self { + SpamDnsblServer::Any(Default::default()) + } +} + +impl Pickle for SpamDnsblServer { + fn pickle(&self, out: &mut Vec) { + match self { + SpamDnsblServer::Any(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Url(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Domain(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Email(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Ip(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Header(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + SpamDnsblServer::Body(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SpamDnsblServer::Any), + 1 => Pickle::unpickle(stream).map(SpamDnsblServer::Url), + 2 => Pickle::unpickle(stream).map(SpamDnsblServer::Domain), + 3 => Pickle::unpickle(stream).map(SpamDnsblServer::Email), + 4 => Pickle::unpickle(stream).map(SpamDnsblServer::Ip), + 5 => Pickle::unpickle(stream).map(SpamDnsblServer::Header), + 6 => Pickle::unpickle(stream).map(SpamDnsblServer::Body), + _ => None, + } + } +} + +impl IntoValue for SpamDnsblServer { + fn into_value(self) -> JmapValue<'static> { + match self { + SpamDnsblServer::Any(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Any".into())); + obj + } + SpamDnsblServer::Url(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Url".into())); + obj + } + SpamDnsblServer::Domain(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Domain".into())); + obj + } + SpamDnsblServer::Email(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Email".into())); + obj + } + SpamDnsblServer::Ip(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ip".into())); + obj + } + SpamDnsblServer::Header(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Header".into())); + obj + } + SpamDnsblServer::Body(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Body".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SpamDnsblServer { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SpamDnsblServerType::Any => *self = SpamDnsblServer::Any(Default::default()), + SpamDnsblServerType::Url => *self = SpamDnsblServer::Url(Default::default()), + SpamDnsblServerType::Domain => *self = SpamDnsblServer::Domain(Default::default()), + SpamDnsblServerType::Email => *self = SpamDnsblServer::Email(Default::default()), + SpamDnsblServerType::Ip => *self = SpamDnsblServer::Ip(Default::default()), + SpamDnsblServerType::Header => *self = SpamDnsblServer::Header(Default::default()), + SpamDnsblServerType::Body => *self = SpamDnsblServer::Body(Default::default()), + } + } + match self { + SpamDnsblServer::Any(inner) => inner.patch(pointer, value), + SpamDnsblServer::Url(inner) => inner.patch(pointer, value), + SpamDnsblServer::Domain(inner) => inner.patch(pointer, value), + SpamDnsblServer::Email(inner) => inner.patch(pointer, value), + SpamDnsblServer::Ip(inner) => inner.patch(pointer, value), + SpamDnsblServer::Header(inner) => inner.patch(pointer, value), + SpamDnsblServer::Body(inner) => inner.patch(pointer, value), + } + } +} + +impl SpamDnsblServer { + pub fn object_type(&self) -> SpamDnsblServerType { + match self { + SpamDnsblServer::Any(_) => SpamDnsblServerType::Any, + SpamDnsblServer::Url(_) => SpamDnsblServerType::Url, + SpamDnsblServer::Domain(_) => SpamDnsblServerType::Domain, + SpamDnsblServer::Email(_) => SpamDnsblServerType::Email, + SpamDnsblServer::Ip(_) => SpamDnsblServerType::Ip, + SpamDnsblServer::Header(_) => SpamDnsblServerType::Header, + SpamDnsblServer::Body(_) => SpamDnsblServerType::Body, + } + } + + pub fn expression_ctxs(&self) -> Vec> { + match self { + SpamDnsblServer::Any(obj) => obj.expression_ctxs(), + SpamDnsblServer::Url(obj) => obj.expression_ctxs(), + SpamDnsblServer::Domain(obj) => obj.expression_ctxs(), + SpamDnsblServer::Email(obj) => obj.expression_ctxs(), + SpamDnsblServer::Ip(obj) => obj.expression_ctxs(), + SpamDnsblServer::Header(obj) => obj.expression_ctxs(), + SpamDnsblServer::Body(obj) => obj.expression_ctxs(), + } + } +} + +impl SpamDnsblServerAny { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerAny { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerAny { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerAny { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerAny { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerAny { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerBody { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerBody { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerBody { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerBody { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerBody { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerBody { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerDomain { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerDomain { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerDomain { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerDomain { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerDomain { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerDomain { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerEmail { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerEmail { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_EMAIL_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerEmail { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerEmail { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerEmail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerEmail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerHeader { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerHeader { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_HEADER_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerHeader { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerHeader { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerHeader { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerHeader { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerIp { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerIp { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerIp { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerIp { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerIp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerIp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamDnsblServerUrl { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + value.validate(errors); + let value = &self.zone; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamDnsblServerUrl { + pub fn ctx_tag(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.tag, + default: None, + property: Property::Tag, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_zone(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.zone, + default: None, + property: Property::Zone, + allowed_variables: SPAM_URL_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_tag(), self.ctx_zone()] + } +} + +impl Pickle for SpamDnsblServerUrl { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.zone.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.zone = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblServerUrl { + fn default() -> Self { + Self { + tag: Default::default(), + zone: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + } + } +} + +impl IntoValue for SpamDnsblServerUrl { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Zone, self.zone.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblServerUrl { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch(pointer, value), + Some(Property::Zone) => self.zone.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamDnsblSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamDnsblSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.domain_limit; + if *value < 1 { + errors.push(ValidationError::min_value(Property::DomainLimit, 1)); + } + let value = &self.email_limit; + if *value < 1 { + errors.push(ValidationError::min_value(Property::EmailLimit, 1)); + } + let value = &self.ip_limit; + if *value < 1 { + errors.push(ValidationError::min_value(Property::IpLimit, 1)); + } + let value = &self.url_limit; + if *value < 1 { + errors.push(ValidationError::min_value(Property::UrlLimit, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for SpamDnsblSettings { + fn pickle(&self, out: &mut Vec) { + self.domain_limit.pickle(out); + self.email_limit.pickle(out); + self.ip_limit.pickle(out); + self.url_limit.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.domain_limit = Pickle::unpickle(stream)?; + this.email_limit = Pickle::unpickle(stream)?; + this.ip_limit = Pickle::unpickle(stream)?; + this.url_limit = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamDnsblSettings { + fn default() -> Self { + Self { + domain_limit: 50u64, + email_limit: 50u64, + ip_limit: 50u64, + url_limit: 50u64, + } + } +} + +impl IntoValue for SpamDnsblSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::DomainLimit, self.domain_limit.into_value()); + map.insert_unchecked(Property::EmailLimit, self.email_limit.into_value()); + map.insert_unchecked(Property::IpLimit, self.ip_limit.into_value()); + map.insert_unchecked(Property::UrlLimit, self.url_limit.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamDnsblSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DomainLimit) => self.domain_limit.patch(pointer, value), + Some(Property::EmailLimit) => self.email_limit.patch(pointer, value), + Some(Property::IpLimit) => self.ip_limit.patch(pointer, value), + Some(Property::UrlLimit) => self.url_limit.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamFileExtension { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamFileExtension; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.extension; + if value.is_empty() { + errors.push(ValidationError::required(Property::Extension)); + } + let value = &self.content_types; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ContentTypes)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Extension, &self.extension); + } +} + +impl Pickle for SpamFileExtension { + fn pickle(&self, out: &mut Vec) { + self.extension.pickle(out); + self.is_archive.pickle(out); + self.is_bad.pickle(out); + self.is_nz.pickle(out); + self.content_types.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.extension = Pickle::unpickle(stream)?; + this.is_archive = Pickle::unpickle(stream)?; + this.is_bad = Pickle::unpickle(stream)?; + this.is_nz = Pickle::unpickle(stream)?; + this.content_types = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamFileExtension { + fn default() -> Self { + Self { + extension: Default::default(), + is_archive: false, + is_bad: false, + is_nz: false, + content_types: Default::default(), + } + } +} + +impl IntoValue for SpamFileExtension { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Extension, self.extension.into_value()); + map.insert_unchecked(Property::IsArchive, self.is_archive.into_value()); + map.insert_unchecked(Property::IsBad, self.is_bad.into_value()); + map.insert_unchecked(Property::IsNz, self.is_nz.into_value()); + map.insert_unchecked(Property::ContentTypes, self.content_types.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamFileExtension { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Extension) => self.extension.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Lowercase]), + value, + ), + Some(Property::IsArchive) => self.is_archive.patch(pointer, value), + Some(Property::IsBad) => self.is_bad.patch(pointer, value), + Some(Property::IsNz) => self.is_nz.patch(pointer, value), + Some(Property::ContentTypes) => self + .content_types + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamLlm { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamLlm; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SpamLlm::Disable => true, + SpamLlm::Enable(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + SpamLlm::Disable => {} + SpamLlm::Enable(object) => { + object.index(i); + } + } + } +} + +impl Default for SpamLlm { + fn default() -> Self { + SpamLlm::Disable + } +} + +impl Pickle for SpamLlm { + fn pickle(&self, out: &mut Vec) { + match self { + SpamLlm::Disable => { + 0u16.pickle(out); + } + SpamLlm::Enable(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SpamLlm::Disable), + 1 => Pickle::unpickle(stream).map(SpamLlm::Enable), + _ => None, + } + } +} + +impl IntoValue for SpamLlm { + fn into_value(self) -> JmapValue<'static> { + match self { + SpamLlm::Disable => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disable".into())); + JmapValue::Object(obj) + } + SpamLlm::Enable(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Enable".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SpamLlm { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SpamLlmType::Disable => *self = SpamLlm::Disable, + SpamLlmType::Enable => *self = SpamLlm::Enable(Default::default()), + } + } + match self { + SpamLlm::Disable => pointer.assert_eof(), + SpamLlm::Enable(inner) => inner.patch(pointer, value), + } + } +} + +impl SpamLlm { + pub fn object_type(&self) -> SpamLlmType { + match self { + SpamLlm::Disable => SpamLlmType::Disable, + SpamLlm::Enable(_) => SpamLlmType::Enable, + } + } +} + +impl SpamLlmProperties { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.categories; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Categories)); + } + } + if value.len() < 2 { + errors.push(ValidationError::min_items(Property::Categories, 2)); + } + let value = &self.confidence; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::Confidence)); + } + } + let value = &self.model_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::ModelId)); + } + let value = &self.prompt; + if value.is_empty() { + errors.push(ValidationError::required(Property::Prompt)); + } + let value = &self.separator; + if value.is_empty() { + errors.push(ValidationError::required(Property::Separator)); + } + let value = &self.temperature; + if *value > Float::new(1.0) { + errors.push(ValidationError::max_value(Property::Temperature, 1)); + } + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::Temperature, 0)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::AiModel, self.model_id.into(), None); + } +} + +impl Pickle for SpamLlmProperties { + fn pickle(&self, out: &mut Vec) { + self.categories.pickle(out); + self.confidence.pickle(out); + self.response_pos_category.pickle(out); + self.response_pos_confidence.pickle(out); + self.response_pos_explanation.pickle(out); + self.model_id.pickle(out); + self.prompt.pickle(out); + self.separator.pickle(out); + self.temperature.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.categories = Pickle::unpickle(stream)?; + this.confidence = Pickle::unpickle(stream)?; + this.response_pos_category = Pickle::unpickle(stream)?; + this.response_pos_confidence = Pickle::unpickle(stream)?; + this.response_pos_explanation = Pickle::unpickle(stream)?; + this.model_id = Pickle::unpickle(stream)?; + this.prompt = Pickle::unpickle(stream)?; + this.separator = Pickle::unpickle(stream)?; + this.temperature = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamLlmProperties { + fn default() -> Self { + Self { + categories: Map::new(vec![ + "Unsolicited".to_string(), + "Commercial".to_string(), + "Harmful".to_string(), + "Legitimate".to_string(), + ]), + confidence: Map::new(vec![ + "High".to_string(), + "Medium".to_string(), + "Low".to_string(), + ]), + response_pos_category: 0u64, + response_pos_confidence: Some(1u64), + response_pos_explanation: Some(2u64), + model_id: Default::default(), + prompt: Default::default(), + separator: ",".to_string(), + temperature: Float::new(0.5f64), + } + } +} + +impl IntoValue for SpamLlmProperties { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::Categories, self.categories.into_value()); + map.insert_unchecked(Property::Confidence, self.confidence.into_value()); + map.insert_unchecked( + Property::ResponsePosCategory, + self.response_pos_category.into_value(), + ); + map.insert_unchecked( + Property::ResponsePosConfidence, + self.response_pos_confidence.into_value(), + ); + map.insert_unchecked( + Property::ResponsePosExplanation, + self.response_pos_explanation.into_value(), + ); + map.insert_unchecked(Property::ModelId, self.model_id.into_value()); + map.insert_unchecked(Property::Prompt, self.prompt.into_value()); + map.insert_unchecked(Property::Separator, self.separator.into_value()); + map.insert_unchecked(Property::Temperature, self.temperature.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamLlmProperties { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Categories) => self.categories.patch(pointer, value), + Some(Property::Confidence) => self.confidence.patch(pointer, value), + Some(Property::ResponsePosCategory) => self.response_pos_category.patch(pointer, value), + Some(Property::ResponsePosConfidence) => { + self.response_pos_confidence.patch(pointer, value) + } + Some(Property::ResponsePosExplanation) => { + self.response_pos_explanation.patch(pointer, value) + } + Some(Property::ModelId) => self.model_id.patch(pointer, value), + Some(Property::Prompt) => self.prompt.patch(pointer, value), + Some(Property::Separator) => self + .separator + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Temperature) => self.temperature.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamPyzor { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamPyzor; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.block_count; + if *value > 1000 { + errors.push(ValidationError::max_value(Property::BlockCount, 1000)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::BlockCount, 1)); + } + let value = &self.host; + if value.is_empty() { + errors.push(ValidationError::required(Property::Host)); + } + let value = &self.port; + if *value > 65535 { + errors.push(ValidationError::max_value(Property::Port, 65535)); + } + if *value < 100 { + errors.push(ValidationError::min_value(Property::Port, 100)); + } + let value = &self.ratio; + if *value > Float::new(1.0) { + errors.push(ValidationError::max_value(Property::Ratio, 1)); + } + if *value < Float::new(0.0) { + errors.push(ValidationError::min_value(Property::Ratio, 0)); + } + let value = &self.allow_count; + if *value > 1000 { + errors.push(ValidationError::max_value(Property::AllowCount, 1000)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::AllowCount, 1)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for SpamPyzor { + fn pickle(&self, out: &mut Vec) { + self.block_count.pickle(out); + self.enable.pickle(out); + self.host.pickle(out); + self.port.pickle(out); + self.ratio.pickle(out); + self.timeout.pickle(out); + self.allow_count.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.block_count = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.host = Pickle::unpickle(stream)?; + this.port = Pickle::unpickle(stream)?; + this.ratio = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.allow_count = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamPyzor { + fn default() -> Self { + Self { + block_count: 5u64, + enable: true, + host: "public.pyzor.org".to_string(), + port: 24441u64, + ratio: Float::new(0.2f64), + timeout: Duration::from_millis(5000), + allow_count: 10u64, + } + } +} + +impl IntoValue for SpamPyzor { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::BlockCount, self.block_count.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Host, self.host.into_value()); + map.insert_unchecked(Property::Port, self.port.into_value()); + map.insert_unchecked(Property::Ratio, self.ratio.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::AllowCount, self.allow_count.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamPyzor { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::BlockCount) => self.block_count.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Host) => self + .host + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Port) => self.port.patch(pointer, value), + Some(Property::Ratio) => self.ratio.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::AllowCount) => self.allow_count.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamRule { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamRule; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SpamRule::Any(inner) => inner.validate(errors), + SpamRule::Url(inner) => inner.validate(errors), + SpamRule::Domain(inner) => inner.validate(errors), + SpamRule::Email(inner) => inner.validate(errors), + SpamRule::Ip(inner) => inner.validate(errors), + SpamRule::Header(inner) => inner.validate(errors), + SpamRule::Body(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + SpamRule::Any(object) => { + object.index(i); + } + SpamRule::Url(object) => { + object.index(i); + } + SpamRule::Domain(object) => { + object.index(i); + } + SpamRule::Email(object) => { + object.index(i); + } + SpamRule::Ip(object) => { + object.index(i); + } + SpamRule::Header(object) => { + object.index(i); + } + SpamRule::Body(object) => { + object.index(i); + } + } + } +} + +impl Default for SpamRule { + fn default() -> Self { + SpamRule::Any(Default::default()) + } +} + +impl Pickle for SpamRule { + fn pickle(&self, out: &mut Vec) { + match self { + SpamRule::Any(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SpamRule::Url(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SpamRule::Domain(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SpamRule::Email(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + SpamRule::Ip(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + SpamRule::Header(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + SpamRule::Body(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SpamRule::Any), + 1 => Pickle::unpickle(stream).map(SpamRule::Url), + 2 => Pickle::unpickle(stream).map(SpamRule::Domain), + 3 => Pickle::unpickle(stream).map(SpamRule::Email), + 4 => Pickle::unpickle(stream).map(SpamRule::Ip), + 5 => Pickle::unpickle(stream).map(SpamRule::Header), + 6 => Pickle::unpickle(stream).map(SpamRule::Body), + _ => None, + } + } +} + +impl IntoValue for SpamRule { + fn into_value(self) -> JmapValue<'static> { + match self { + SpamRule::Any(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Any".into())); + obj + } + SpamRule::Url(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Url".into())); + obj + } + SpamRule::Domain(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Domain".into())); + obj + } + SpamRule::Email(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Email".into())); + obj + } + SpamRule::Ip(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Ip".into())); + obj + } + SpamRule::Header(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Header".into())); + obj + } + SpamRule::Body(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Body".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SpamRule { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SpamRuleType::Any => *self = SpamRule::Any(Default::default()), + SpamRuleType::Url => *self = SpamRule::Url(Default::default()), + SpamRuleType::Domain => *self = SpamRule::Domain(Default::default()), + SpamRuleType::Email => *self = SpamRule::Email(Default::default()), + SpamRuleType::Ip => *self = SpamRule::Ip(Default::default()), + SpamRuleType::Header => *self = SpamRule::Header(Default::default()), + SpamRuleType::Body => *self = SpamRule::Body(Default::default()), + } + } + match self { + SpamRule::Any(inner) => inner.patch(pointer, value), + SpamRule::Url(inner) => inner.patch(pointer, value), + SpamRule::Domain(inner) => inner.patch(pointer, value), + SpamRule::Email(inner) => inner.patch(pointer, value), + SpamRule::Ip(inner) => inner.patch(pointer, value), + SpamRule::Header(inner) => inner.patch(pointer, value), + SpamRule::Body(inner) => inner.patch(pointer, value), + } + } +} + +impl SpamRule { + pub fn object_type(&self) -> SpamRuleType { + match self { + SpamRule::Any(_) => SpamRuleType::Any, + SpamRule::Url(_) => SpamRuleType::Url, + SpamRule::Domain(_) => SpamRuleType::Domain, + SpamRule::Email(_) => SpamRuleType::Email, + SpamRule::Ip(_) => SpamRuleType::Ip, + SpamRule::Header(_) => SpamRuleType::Header, + SpamRule::Body(_) => SpamRuleType::Body, + } + } + + pub fn expression_ctxs(&self) -> Vec> { + match self { + SpamRule::Any(obj) => obj.expression_ctxs(), + SpamRule::Url(obj) => obj.expression_ctxs(), + SpamRule::Domain(obj) => obj.expression_ctxs(), + SpamRule::Email(obj) => obj.expression_ctxs(), + SpamRule::Ip(obj) => obj.expression_ctxs(), + SpamRule::Header(obj) => obj.expression_ctxs(), + SpamRule::Body(obj) => obj.expression_ctxs(), + } + } +} + +impl SpamRuleAny { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleAny { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleAny { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleAny { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleAny { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleAny { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleBody { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleBody { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleBody { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleBody { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleBody { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleBody { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleDomain { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleDomain { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_GENERIC_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleDomain { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleDomain { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleDomain { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleDomain { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleEmail { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleEmail { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_EMAIL_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleEmail { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleEmail { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleEmail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleEmail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleHeader { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleHeader { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_HEADER_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleHeader { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleHeader { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleHeader { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleHeader { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleIp { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleIp { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_IP_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleIp { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleIp { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleIp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleIp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamRuleUrl { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.condition; + value.validate(errors); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.priority; + if *value > (99999) { + errors.push(ValidationError::max_value(Property::Priority, 99999)); + } + if *value < (-99999) { + errors.push(ValidationError::min_value(Property::Priority, -99999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Name, &self.name); + } +} + +impl SpamRuleUrl { + pub fn ctx_condition(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.condition, + default: None, + property: Property::Condition, + allowed_variables: SPAM_URL_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_condition()] + } +} + +impl Pickle for SpamRuleUrl { + fn pickle(&self, out: &mut Vec) { + self.condition.pickle(out); + self.name.pickle(out); + self.description.pickle(out); + self.enable.pickle(out); + self.priority.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.condition = Pickle::unpickle(stream)?; + this.name = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.priority = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamRuleUrl { + fn default() -> Self { + Self { + condition: Default::default(), + name: Default::default(), + description: Default::default(), + enable: true, + priority: 500i64, + } + } +} + +impl IntoValue for SpamRuleUrl { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Condition, self.condition.into_value()); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Priority, self.priority.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamRuleUrl { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Condition) => self.condition.patch(pointer, value), + Some(Property::Name) => self.name.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Uppercase, StringValidator::RemoveSpaces]), + value, + ), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Priority) => self.priority.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.score_discard; + if *value > Float::new(100.0) { + errors.push(ValidationError::max_value(Property::ScoreDiscard, 100)); + } + if *value < Float::new(-100.0) { + errors.push(ValidationError::min_value(Property::ScoreDiscard, -100)); + } + let value = &self.score_reject; + if *value > Float::new(100.0) { + errors.push(ValidationError::max_value(Property::ScoreReject, 100)); + } + if *value < Float::new(-100.0) { + errors.push(ValidationError::min_value(Property::ScoreReject, -100)); + } + let value = &self.score_spam; + if *value > Float::new(100.0) { + errors.push(ValidationError::max_value(Property::ScoreSpam, 100)); + } + if *value < Float::new(-100.0) { + errors.push(ValidationError::min_value(Property::ScoreSpam, -100)); + } + if let Some(value) = &self.spam_filter_rules_url { + if value.is_empty() { + errors.push(ValidationError::required(Property::SpamFilterRulesUrl)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for SpamSettings { + fn pickle(&self, out: &mut Vec) { + self.trust_contacts.pickle(out); + self.enable.pickle(out); + self.greylist_for.pickle(out); + self.score_discard.pickle(out); + self.score_reject.pickle(out); + self.score_spam.pickle(out); + self.trust_replies.pickle(out); + self.spam_filter_rules_url.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.trust_contacts = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.greylist_for = Pickle::unpickle(stream)?; + this.score_discard = Pickle::unpickle(stream)?; + this.score_reject = Pickle::unpickle(stream)?; + this.score_spam = Pickle::unpickle(stream)?; + this.trust_replies = Pickle::unpickle(stream)?; + this.spam_filter_rules_url = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamSettings { + fn default() -> Self { + Self { + trust_contacts: true, + enable: true, + greylist_for: Default::default(), + score_discard: Float::new(0.0f64), + score_reject: Float::new(0.0f64), + score_spam: Float::new(5.0f64), + trust_replies: true, + spam_filter_rules_url: Some("https://github.com/stalwartlabs/spam-filter/releases/latest/download/spam-filter-rules.json.gz".to_string()), + } + } +} + +impl IntoValue for SpamSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::TrustContacts, self.trust_contacts.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::GreylistFor, self.greylist_for.into_value()); + map.insert_unchecked(Property::ScoreDiscard, self.score_discard.into_value()); + map.insert_unchecked(Property::ScoreReject, self.score_reject.into_value()); + map.insert_unchecked(Property::ScoreSpam, self.score_spam.into_value()); + map.insert_unchecked(Property::TrustReplies, self.trust_replies.into_value()); + map.insert_unchecked( + Property::SpamFilterRulesUrl, + self.spam_filter_rules_url.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::TrustContacts) => self.trust_contacts.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::GreylistFor) => self.greylist_for.patch(pointer, value), + Some(Property::ScoreDiscard) => self.score_discard.patch(pointer, value), + Some(Property::ScoreReject) => self.score_reject.patch(pointer, value), + Some(Property::ScoreSpam) => self.score_spam.patch(pointer, value), + Some(Property::TrustReplies) => self.trust_replies.patch(pointer, value), + Some(Property::SpamFilterRulesUrl) => self + .spam_filter_rules_url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamTag { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamTag; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SpamTag::Score(inner) => inner.validate(errors), + SpamTag::Discard(inner) => inner.validate(errors), + SpamTag::Reject(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + SpamTag::Score(object) => { + object.index(i); + } + SpamTag::Discard(object) => { + object.index(i); + } + SpamTag::Reject(object) => { + object.index(i); + } + } + } +} + +impl Default for SpamTag { + fn default() -> Self { + SpamTag::Score(Default::default()) + } +} + +impl Pickle for SpamTag { + fn pickle(&self, out: &mut Vec) { + match self { + SpamTag::Score(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + SpamTag::Discard(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SpamTag::Reject(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(SpamTag::Score), + 1 => Pickle::unpickle(stream).map(SpamTag::Discard), + 2 => Pickle::unpickle(stream).map(SpamTag::Reject), + _ => None, + } + } +} + +impl IntoValue for SpamTag { + fn into_value(self) -> JmapValue<'static> { + match self { + SpamTag::Score(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Score".into())); + obj + } + SpamTag::Discard(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Discard".into())); + obj + } + SpamTag::Reject(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Reject".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SpamTag { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SpamTagType::Score => *self = SpamTag::Score(Default::default()), + SpamTagType::Discard => *self = SpamTag::Discard(Default::default()), + SpamTagType::Reject => *self = SpamTag::Reject(Default::default()), + } + } + match self { + SpamTag::Score(inner) => inner.patch(pointer, value), + SpamTag::Discard(inner) => inner.patch(pointer, value), + SpamTag::Reject(inner) => inner.patch(pointer, value), + } + } +} + +impl SpamTag { + pub fn object_type(&self) -> SpamTagType { + match self { + SpamTag::Score(_) => SpamTagType::Score, + SpamTag::Discard(_) => SpamTagType::Discard, + SpamTag::Reject(_) => SpamTagType::Reject, + } + } +} + +impl SpamTagAction { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + if value.is_empty() { + errors.push(ValidationError::required(Property::Tag)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Tag, &self.tag); + } +} + +impl Pickle for SpamTagAction { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamTagAction { + fn default() -> Self { + Self { + tag: Default::default(), + } + } +} + +impl IntoValue for SpamTagAction { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamTagAction { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch( + pointer + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SpamTagScore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tag; + if value.is_empty() { + errors.push(ValidationError::required(Property::Tag)); + } + let value = &self.score; + if *value < Float::new(-999999.0) { + errors.push(ValidationError::min_value(Property::Score, -999999)); + } + if *value > Float::new(999999.0) { + errors.push(ValidationError::max_value(Property::Score, 999999)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique(Property::Tag, &self.tag); + } +} + +impl Pickle for SpamTagScore { + fn pickle(&self, out: &mut Vec) { + self.tag.pickle(out); + self.score.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tag = Pickle::unpickle(stream)?; + this.score = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamTagScore { + fn default() -> Self { + Self { + tag: Default::default(), + score: Float::new(0.0f64), + } + } +} + +impl IntoValue for SpamTagScore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Tag, self.tag.into_value()); + map.insert_unchecked(Property::Score, self.score.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamTagScore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Tag) => self.tag.patch( + pointer + .with_validators(&[StringValidator::RemoveSpaces, StringValidator::Uppercase]), + value, + ), + Some(Property::Score) => self.score.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpamTrainingSample { + const FLAGS: u64 = OBJ_FILTER_ACCOUNT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpamTrainingSample; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + if let Some(value) = &self.account_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + } + let value = &self.expires_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id, None); + if let Some(value) = &self.account_id { + i.search(Property::AccountId, value); + } + } +} + +impl Pickle for SpamTrainingSample { + fn pickle(&self, out: &mut Vec) { + self.from.pickle(out); + self.subject.pickle(out); + self.blob_id.pickle(out); + self.is_spam.pickle(out); + self.account_id.pickle(out); + self.expires_at.pickle(out); + self.delete_after_use.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.blob_id = Pickle::unpickle(stream)?; + this.is_spam = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.delete_after_use = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpamTrainingSample { + fn default() -> Self { + Self { + from: Default::default(), + subject: Default::default(), + blob_id: Default::default(), + is_spam: false, + account_id: Default::default(), + expires_at: Default::default(), + delete_after_use: false, + } + } +} + +impl IntoValue for SpamTrainingSample { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + map.insert_unchecked(Property::IsSpam, self.is_spam.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::DeleteAfterUse, self.delete_after_use.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpamTrainingSample { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::From) => pointer.assert_server_set(), + Some(Property::Subject) => pointer.assert_server_set(), + Some(Property::BlobId) => self.blob_id.patch(pointer.assert_read_only()?, value), + Some(Property::IsSpam) => self.is_spam.patch(pointer.assert_read_only()?, value), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::ExpiresAt) => pointer.assert_server_set(), + Some(Property::DeleteAfterUse) => self + .delete_after_use + .patch(pointer.assert_read_only()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SpfReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SpfReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from_address; + value.validate(errors); + let value = &self.from_name; + value.validate(errors); + let value = &self.send_frequency; + value.validate(errors); + let value = &self.dkim_sign_domain; + value.validate(errors); + let value = &self.subject; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl SpfReportSettings { + pub fn ctx_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_address, + default: Some(Expression { + else_: "'noreply-spf@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::FromAddress, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_name, + default: Some(Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }), + property: Property::FromName, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.send_frequency, + default: Some(Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }), + property: Property::SendFrequency, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_subject(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.subject, + default: Some(Expression { + else_: "'SPF Authentication Failure Report'".to_string(), + ..Default::default() + }), + property: Property::Subject, + allowed_variables: MTA_MAIL_FROM_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_from_address(), + self.ctx_from_name(), + self.ctx_send_frequency(), + self.ctx_dkim_sign_domain(), + self.ctx_subject(), + ] + } +} + +impl Pickle for SpfReportSettings { + fn pickle(&self, out: &mut Vec) { + self.from_address.pickle(out); + self.from_name.pickle(out); + self.send_frequency.pickle(out); + self.dkim_sign_domain.pickle(out); + self.subject.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from_address = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.send_frequency = Pickle::unpickle(stream)?; + this.dkim_sign_domain = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SpfReportSettings { + fn default() -> Self { + Self { + from_address: Expression { + else_: "'noreply-spf@' + system('domain')".to_string(), + ..Default::default() + }, + from_name: Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }, + send_frequency: Expression { + else_: "[1, 1d]".to_string(), + ..Default::default() + }, + dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + subject: Expression { + else_: "'SPF Authentication Failure Report'".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for SpfReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::FromAddress, self.from_address.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value()); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SpfReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::FromAddress) => self.from_address.patch(pointer, value), + Some(Property::FromName) => self.from_name.patch(pointer, value), + Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value), + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SqlAuthStore { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SqlAuthStore::Default => true, + SqlAuthStore::PostgreSql(inner) => inner.validate(errors), + SqlAuthStore::MySql(inner) => inner.validate(errors), + SqlAuthStore::Sqlite(inner) => inner.validate(errors), + } + } +} + +impl Default for SqlAuthStore { + fn default() -> Self { + SqlAuthStore::Default + } +} + +impl Pickle for SqlAuthStore { + fn pickle(&self, out: &mut Vec) { + match self { + SqlAuthStore::Default => { + 0u16.pickle(out); + } + SqlAuthStore::PostgreSql(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SqlAuthStore::MySql(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + SqlAuthStore::Sqlite(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SqlAuthStore::Default), + 1 => Pickle::unpickle(stream).map(SqlAuthStore::PostgreSql), + 2 => Pickle::unpickle(stream).map(SqlAuthStore::MySql), + 3 => Pickle::unpickle(stream).map(SqlAuthStore::Sqlite), + _ => None, + } + } +} + +impl IntoValue for SqlAuthStore { + fn into_value(self) -> JmapValue<'static> { + match self { + SqlAuthStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + SqlAuthStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + SqlAuthStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + SqlAuthStore::Sqlite(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Sqlite".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for SqlAuthStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SqlAuthStoreType::Default => *self = SqlAuthStore::Default, + SqlAuthStoreType::PostgreSql => { + *self = SqlAuthStore::PostgreSql(Default::default()) + } + SqlAuthStoreType::MySql => *self = SqlAuthStore::MySql(Default::default()), + SqlAuthStoreType::Sqlite => *self = SqlAuthStore::Sqlite(Default::default()), + } + } + match self { + SqlAuthStore::Default => pointer.assert_eof(), + SqlAuthStore::PostgreSql(inner) => inner.patch(pointer, value), + SqlAuthStore::MySql(inner) => inner.patch(pointer, value), + SqlAuthStore::Sqlite(inner) => inner.patch(pointer, value), + } + } +} + +impl SqlAuthStore { + pub fn object_type(&self) -> SqlAuthStoreType { + match self { + SqlAuthStore::Default => SqlAuthStoreType::Default, + SqlAuthStore::PostgreSql(_) => SqlAuthStoreType::PostgreSql, + SqlAuthStore::MySql(_) => SqlAuthStoreType::MySql, + SqlAuthStore::Sqlite(_) => SqlAuthStoreType::Sqlite, + } + } +} + +impl SqlDirectory { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.description; + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + let value = &self.store; + value.validate(errors); + let value = &self.column_email; + if value.is_empty() { + errors.push(ValidationError::required(Property::ColumnEmail)); + } + let value = &self.column_secret; + if value.is_empty() { + errors.push(ValidationError::required(Property::ColumnSecret)); + } + if let Some(value) = &self.column_class { + if value.is_empty() { + errors.push(ValidationError::required(Property::ColumnClass)); + } + } + if let Some(value) = &self.column_description { + if value.is_empty() { + errors.push(ValidationError::required(Property::ColumnDescription)); + } + } + let value = &self.query_login; + if value.is_empty() { + errors.push(ValidationError::required(Property::QueryLogin)); + } + let value = &self.query_recipient; + if value.is_empty() { + errors.push(ValidationError::required(Property::QueryRecipient)); + } + if let Some(value) = &self.query_member_of { + if value.is_empty() { + errors.push(ValidationError::required(Property::QueryMemberOf)); + } + } + if let Some(value) = &self.query_email_aliases { + if value.is_empty() { + errors.push(ValidationError::required(Property::QueryEmailAliases)); + } + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + } +} + +impl Pickle for SqlDirectory { + fn pickle(&self, out: &mut Vec) { + self.description.pickle(out); + self.store.pickle(out); + self.column_email.pickle(out); + self.column_secret.pickle(out); + self.column_class.pickle(out); + self.column_description.pickle(out); + self.query_login.pickle(out); + self.query_recipient.pickle(out); + self.query_member_of.pickle(out); + self.query_email_aliases.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.description = Pickle::unpickle(stream)?; + this.store = Pickle::unpickle(stream)?; + this.column_email = Pickle::unpickle(stream)?; + this.column_secret = Pickle::unpickle(stream)?; + this.column_class = Pickle::unpickle(stream)?; + this.column_description = Pickle::unpickle(stream)?; + this.query_login = Pickle::unpickle(stream)?; + this.query_recipient = Pickle::unpickle(stream)?; + this.query_member_of = Pickle::unpickle(stream)?; + this.query_email_aliases = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SqlDirectory { + fn default() -> Self { + Self { + description: Default::default(), + store: Default::default(), + column_email: "name".to_string(), + column_secret: "secret".to_string(), + column_class: Some("type".to_string()), + column_description: Some("description".to_string()), + query_login: "SELECT name, secret, description, type FROM accounts WHERE name = $1".to_string(), + query_recipient: "SELECT name, secret, description, type FROM accounts WHERE name = $1 AND active = true".to_string(), + query_member_of: Some("SELECT member_of FROM group_members WHERE name = $1".to_string()), + query_email_aliases: Some("SELECT address FROM emails WHERE name = $1".to_string()), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for SqlDirectory { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(13); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Store, self.store.into_value()); + map.insert_unchecked(Property::ColumnEmail, self.column_email.into_value()); + map.insert_unchecked(Property::ColumnSecret, self.column_secret.into_value()); + map.insert_unchecked(Property::ColumnClass, self.column_class.into_value()); + map.insert_unchecked( + Property::ColumnDescription, + self.column_description.into_value(), + ); + map.insert_unchecked(Property::QueryLogin, self.query_login.into_value()); + map.insert_unchecked(Property::QueryRecipient, self.query_recipient.into_value()); + map.insert_unchecked(Property::QueryMemberOf, self.query_member_of.into_value()); + map.insert_unchecked( + Property::QueryEmailAliases, + self.query_email_aliases.into_value(), + ); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SqlDirectory { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Description) => self + .description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Store) => self.store.patch(pointer, value), + Some(Property::ColumnEmail) => self + .column_email + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ColumnSecret) => self + .column_secret + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ColumnClass) => self + .column_class + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::ColumnDescription) => self + .column_description + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::QueryLogin) => self + .query_login + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::QueryRecipient) => self + .query_recipient + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::QueryMemberOf) => self + .query_member_of + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::QueryEmailAliases) => self + .query_email_aliases + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SqliteStore { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.path; + if value.is_empty() { + errors.push(ValidationError::required(Property::Path)); + } + if let Some(value) = &self.pool_workers { + if *value > 64 { + errors.push(ValidationError::max_value(Property::PoolWorkers, 64)); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolWorkers, 1)); + } + } + let value = &self.pool_max_connections; + if *value > 8192 { + errors.push(ValidationError::max_value( + Property::PoolMaxConnections, + 8192, + )); + } + if *value < 1 { + errors.push(ValidationError::min_value(Property::PoolMaxConnections, 1)); + } + errors.len() == neb + } +} + +impl Pickle for SqliteStore { + fn pickle(&self, out: &mut Vec) { + self.path.pickle(out); + self.pool_workers.pickle(out); + self.pool_max_connections.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.path = Pickle::unpickle(stream)?; + this.pool_workers = Pickle::unpickle(stream)?; + this.pool_max_connections = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SqliteStore { + fn default() -> Self { + Self { + path: Default::default(), + pool_workers: Default::default(), + pool_max_connections: 10u64, + } + } +} + +impl IntoValue for SqliteStore { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Path, self.path.into_value()); + map.insert_unchecked(Property::PoolWorkers, self.pool_workers.into_value()); + map.insert_unchecked( + Property::PoolMaxConnections, + self.pool_max_connections.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SqliteStore { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Path) => self + .path + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::PoolWorkers) => self.pool_workers.patch(pointer, value), + Some(Property::PoolMaxConnections) => self.pool_max_connections.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for StoreLookup { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::StoreLookup; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.namespace; + if value.is_empty() { + errors.push(ValidationError::required(Property::Namespace)); + } + let value = &self.store; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global(Property::Namespace, &self.namespace); + } +} + +impl Pickle for StoreLookup { + fn pickle(&self, out: &mut Vec) { + self.namespace.pickle(out); + self.store.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.namespace = Pickle::unpickle(stream)?; + this.store = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for StoreLookup { + fn default() -> Self { + Self { + namespace: Default::default(), + store: Default::default(), + } + } +} + +impl IntoValue for StoreLookup { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Namespace, self.namespace.into_value()); + map.insert_unchecked(Property::Store, self.store.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for StoreLookup { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Namespace) => self.namespace.patch( + pointer + .assert_read_only()? + .with_validators(&[StringValidator::Trim]), + value, + ), + Some(Property::Store) => self.store.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl SubAddressing { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + SubAddressing::Enabled => true, + SubAddressing::Custom(inner) => inner.validate(errors), + SubAddressing::Disabled => true, + } + } +} + +impl Default for SubAddressing { + fn default() -> Self { + SubAddressing::Enabled + } +} + +impl Pickle for SubAddressing { + fn pickle(&self, out: &mut Vec) { + match self { + SubAddressing::Enabled => { + 0u16.pickle(out); + } + SubAddressing::Custom(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + SubAddressing::Disabled => { + 2u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(SubAddressing::Enabled), + 1 => Pickle::unpickle(stream).map(SubAddressing::Custom), + 2 => Some(SubAddressing::Disabled), + _ => None, + } + } +} + +impl IntoValue for SubAddressing { + fn into_value(self) -> JmapValue<'static> { + match self { + SubAddressing::Enabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Enabled".into())); + JmapValue::Object(obj) + } + SubAddressing::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + SubAddressing::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for SubAddressing { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + SubAddressingType::Enabled => *self = SubAddressing::Enabled, + SubAddressingType::Custom => *self = SubAddressing::Custom(Default::default()), + SubAddressingType::Disabled => *self = SubAddressing::Disabled, + } + } + match self { + SubAddressing::Enabled => pointer.assert_eof(), + SubAddressing::Custom(inner) => inner.patch(pointer, value), + SubAddressing::Disabled => pointer.assert_eof(), + } + } +} + +impl SubAddressing { + pub fn object_type(&self) -> SubAddressingType { + match self { + SubAddressing::Enabled => SubAddressingType::Enabled, + SubAddressing::Custom(_) => SubAddressingType::Custom, + SubAddressing::Disabled => SubAddressingType::Disabled, + } + } + + pub fn expression_ctxs(&self) -> Vec> { + match self { + SubAddressing::Custom(obj) => obj.expression_ctxs(), + _ => vec![], + } + } +} + +impl SubAddressingCustom { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.custom_rule; + value.validate(errors); + errors.len() == neb + } +} + +impl SubAddressingCustom { + pub fn ctx_custom_rule(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.custom_rule, + default: None, + property: Property::CustomRule, + allowed_variables: MTA_RCPT_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![self.ctx_custom_rule()] + } +} + +impl Pickle for SubAddressingCustom { + fn pickle(&self, out: &mut Vec) { + self.custom_rule.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.custom_rule = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SubAddressingCustom { + fn default() -> Self { + Self { + custom_rule: Default::default(), + } + } +} + +impl IntoValue for SubAddressingCustom { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::CustomRule, self.custom_rule.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SubAddressingCustom { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CustomRule) => self.custom_rule.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for SystemSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::SystemSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.default_hostname; + if value.is_empty() { + errors.push(ValidationError::required(Property::DefaultHostname)); + } + let value = &self.default_domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultDomainId)); + } + if let Some(value) = &self.default_certificate_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::DefaultCertificateId)); + } + } + if let Some(value) = &self.thread_pool_size { + if *value < 1 { + errors.push(ValidationError::min_value(Property::ThreadPoolSize, 1)); + } + } + let value = &self.max_connections; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxConnections, 1)); + } + let value = &self.proxy_trusted_networks; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::invalid( + Property::ProxyTrustedNetworks, + value, + )); + } + } + let value = &self.mail_exchangers; + for value in value.values() { + value.validate(errors); + } + let value = &self.services; + for value in value.values() { + value.validate(errors); + } + let value = &self.provider_info; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::ProviderInfo)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Domain, self.default_domain_id.into(), None); + i.foreign_key(ObjectType::Certificate, self.default_certificate_id, None); + } +} + +impl Pickle for SystemSettings { + fn pickle(&self, out: &mut Vec) { + self.default_hostname.pickle(out); + self.default_domain_id.pickle(out); + self.default_certificate_id.pickle(out); + self.thread_pool_size.pickle(out); + self.max_connections.pickle(out); + self.proxy_trusted_networks.pickle(out); + self.mail_exchangers.pickle(out); + self.services.pickle(out); + self.provider_info.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.default_hostname = Pickle::unpickle(stream)?; + this.default_domain_id = Pickle::unpickle(stream)?; + this.default_certificate_id = Pickle::unpickle(stream)?; + this.thread_pool_size = Pickle::unpickle(stream)?; + this.max_connections = Pickle::unpickle(stream)?; + this.proxy_trusted_networks = Pickle::unpickle(stream)?; + this.mail_exchangers = Pickle::unpickle(stream)?; + this.services = Pickle::unpickle(stream)?; + this.provider_info = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for SystemSettings { + fn default() -> Self { + Self { + default_hostname: Default::default(), + default_domain_id: Default::default(), + default_certificate_id: Default::default(), + thread_pool_size: Default::default(), + max_connections: 8192u64, + proxy_trusted_networks: Default::default(), + mail_exchangers: List::from_iter([MailExchanger { + priority: 10u64, + ..Default::default() + }]), + services: VecMap::from_iter([ + ( + ServiceProtocol::Caldav, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Carddav, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Imap, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Jmap, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Managesieve, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Pop3, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Smtp, + Service { + cleartext: false, + ..Default::default() + }, + ), + ( + ServiceProtocol::Webdav, + Service { + cleartext: false, + ..Default::default() + }, + ), + ]), + provider_info: Default::default(), + } + } +} + +impl IntoValue for SystemSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked( + Property::DefaultHostname, + self.default_hostname.into_value(), + ); + map.insert_unchecked( + Property::DefaultDomainId, + self.default_domain_id.into_value(), + ); + map.insert_unchecked( + Property::DefaultCertificateId, + self.default_certificate_id.into_value(), + ); + map.insert_unchecked(Property::ThreadPoolSize, self.thread_pool_size.into_value()); + map.insert_unchecked(Property::MaxConnections, self.max_connections.into_value()); + map.insert_unchecked( + Property::ProxyTrustedNetworks, + self.proxy_trusted_networks.into_value(), + ); + map.insert_unchecked(Property::MailExchangers, self.mail_exchangers.into_value()); + map.insert_unchecked(Property::Services, self.services.into_value()); + map.insert_unchecked(Property::ProviderInfo, self.provider_info.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for SystemSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DefaultHostname) => self + .default_hostname + .patch(pointer.with_validators(&[StringValidator::Hostname]), value), + Some(Property::DefaultDomainId) => self.default_domain_id.patch(pointer, value), + Some(Property::DefaultCertificateId) => { + self.default_certificate_id.patch(pointer, value) + } + Some(Property::ThreadPoolSize) => self.thread_pool_size.patch(pointer, value), + Some(Property::MaxConnections) => self.max_connections.patch(pointer, value), + Some(Property::ProxyTrustedNetworks) => self + .proxy_trusted_networks + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::MailExchangers) => self.mail_exchangers.patch(pointer, value), + Some(Property::Services) => self.services.patch(pointer, value), + Some(Property::ProviderInfo) => self.provider_info.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Task { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Task; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Task::IndexDocument(inner) => inner.validate(errors), + Task::UnindexDocument(inner) => inner.validate(errors), + Task::IndexTrace(inner) => inner.validate(errors), + Task::CalendarAlarmEmail(inner) => inner.validate(errors), + Task::CalendarAlarmNotification(inner) => inner.validate(errors), + Task::CalendarItipMessage(inner) => inner.validate(errors), + Task::MergeThreads(inner) => inner.validate(errors), + Task::DmarcReport(inner) => inner.validate(errors), + Task::TlsReport(inner) => inner.validate(errors), + Task::RestoreArchivedItem(inner) => inner.validate(errors), + Task::DestroyAccount(inner) => inner.validate(errors), + Task::AccountMaintenance(inner) => inner.validate(errors), + Task::TenantMaintenance(inner) => inner.validate(errors), + Task::StoreMaintenance(inner) => inner.validate(errors), + Task::SpamFilterMaintenance(inner) => inner.validate(errors), + Task::AcmeRenewal(inner) => inner.validate(errors), + Task::DkimManagement(inner) => inner.validate(errors), + Task::DnsManagement(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + Task::IndexDocument(object) => { + object.index(i); + } + Task::UnindexDocument(object) => { + object.index(i); + } + Task::IndexTrace(object) => { + object.index(i); + } + Task::CalendarAlarmEmail(object) => { + object.index(i); + } + Task::CalendarAlarmNotification(object) => { + object.index(i); + } + Task::CalendarItipMessage(object) => { + object.index(i); + } + Task::MergeThreads(object) => { + object.index(i); + } + Task::DmarcReport(object) => { + object.index(i); + } + Task::TlsReport(object) => { + object.index(i); + } + Task::RestoreArchivedItem(object) => { + object.index(i); + } + Task::DestroyAccount(object) => { + object.index(i); + } + Task::AccountMaintenance(object) => { + object.index(i); + } + Task::TenantMaintenance(object) => { + object.index(i); + } + Task::StoreMaintenance(_) => {} + Task::SpamFilterMaintenance(_) => {} + Task::AcmeRenewal(object) => { + object.index(i); + } + Task::DkimManagement(object) => { + object.index(i); + } + Task::DnsManagement(object) => { + object.index(i); + } + } + } +} + +impl Default for Task { + fn default() -> Self { + Task::IndexDocument(Default::default()) + } +} + +impl Pickle for Task { + fn pickle(&self, out: &mut Vec) { + match self { + Task::IndexDocument(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Task::UnindexDocument(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Task::IndexTrace(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + Task::CalendarAlarmEmail(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + Task::CalendarAlarmNotification(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + Task::CalendarItipMessage(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + Task::MergeThreads(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + Task::DmarcReport(inner) => { + 7u16.pickle(out); + inner.pickle(out); + } + Task::TlsReport(inner) => { + 8u16.pickle(out); + inner.pickle(out); + } + Task::RestoreArchivedItem(inner) => { + 9u16.pickle(out); + inner.pickle(out); + } + Task::DestroyAccount(inner) => { + 10u16.pickle(out); + inner.pickle(out); + } + Task::AccountMaintenance(inner) => { + 11u16.pickle(out); + inner.pickle(out); + } + Task::TenantMaintenance(inner) => { + 12u16.pickle(out); + inner.pickle(out); + } + Task::StoreMaintenance(inner) => { + 13u16.pickle(out); + inner.pickle(out); + } + Task::SpamFilterMaintenance(inner) => { + 14u16.pickle(out); + inner.pickle(out); + } + Task::AcmeRenewal(inner) => { + 15u16.pickle(out); + inner.pickle(out); + } + Task::DkimManagement(inner) => { + 16u16.pickle(out); + inner.pickle(out); + } + Task::DnsManagement(inner) => { + 17u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Task::IndexDocument), + 1 => Pickle::unpickle(stream).map(Task::UnindexDocument), + 2 => Pickle::unpickle(stream).map(Task::IndexTrace), + 3 => Pickle::unpickle(stream).map(Task::CalendarAlarmEmail), + 4 => Pickle::unpickle(stream).map(Task::CalendarAlarmNotification), + 5 => Pickle::unpickle(stream).map(Task::CalendarItipMessage), + 6 => Pickle::unpickle(stream).map(Task::MergeThreads), + 7 => Pickle::unpickle(stream).map(Task::DmarcReport), + 8 => Pickle::unpickle(stream).map(Task::TlsReport), + 9 => Pickle::unpickle(stream).map(Task::RestoreArchivedItem), + 10 => Pickle::unpickle(stream).map(Task::DestroyAccount), + 11 => Pickle::unpickle(stream).map(Task::AccountMaintenance), + 12 => Pickle::unpickle(stream).map(Task::TenantMaintenance), + 13 => Pickle::unpickle(stream).map(Task::StoreMaintenance), + 14 => Pickle::unpickle(stream).map(Task::SpamFilterMaintenance), + 15 => Pickle::unpickle(stream).map(Task::AcmeRenewal), + 16 => Pickle::unpickle(stream).map(Task::DkimManagement), + 17 => Pickle::unpickle(stream).map(Task::DnsManagement), + _ => None, + } + } +} + +impl IntoValue for Task { + fn into_value(self) -> JmapValue<'static> { + match self { + Task::IndexDocument(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("IndexDocument".into())); + obj + } + Task::UnindexDocument(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("UnindexDocument".into())); + obj + } + Task::IndexTrace(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("IndexTrace".into())); + obj + } + Task::CalendarAlarmEmail(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("CalendarAlarmEmail".into())); + obj + } + Task::CalendarAlarmNotification(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut().unwrap().insert_unchecked( + Property::Type, + JmapValue::Str("CalendarAlarmNotification".into()), + ); + obj + } + Task::CalendarItipMessage(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("CalendarItipMessage".into())); + obj + } + Task::MergeThreads(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MergeThreads".into())); + obj + } + Task::DmarcReport(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DmarcReport".into())); + obj + } + Task::TlsReport(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("TlsReport".into())); + obj + } + Task::RestoreArchivedItem(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("RestoreArchivedItem".into())); + obj + } + Task::DestroyAccount(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DestroyAccount".into())); + obj + } + Task::AccountMaintenance(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("AccountMaintenance".into())); + obj + } + Task::TenantMaintenance(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("TenantMaintenance".into())); + obj + } + Task::StoreMaintenance(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("StoreMaintenance".into())); + obj + } + Task::SpamFilterMaintenance(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut().unwrap().insert_unchecked( + Property::Type, + JmapValue::Str("SpamFilterMaintenance".into()), + ); + obj + } + Task::AcmeRenewal(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("AcmeRenewal".into())); + obj + } + Task::DkimManagement(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DkimManagement".into())); + obj + } + Task::DnsManagement(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("DnsManagement".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Task { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TaskType::IndexDocument => *self = Task::IndexDocument(Default::default()), + TaskType::UnindexDocument => *self = Task::UnindexDocument(Default::default()), + TaskType::IndexTrace => *self = Task::IndexTrace(Default::default()), + TaskType::CalendarAlarmEmail => { + *self = Task::CalendarAlarmEmail(Default::default()) + } + TaskType::CalendarAlarmNotification => { + *self = Task::CalendarAlarmNotification(Default::default()) + } + TaskType::CalendarItipMessage => { + *self = Task::CalendarItipMessage(Default::default()) + } + TaskType::MergeThreads => *self = Task::MergeThreads(Default::default()), + TaskType::DmarcReport => *self = Task::DmarcReport(Default::default()), + TaskType::TlsReport => *self = Task::TlsReport(Default::default()), + TaskType::RestoreArchivedItem => { + *self = Task::RestoreArchivedItem(Default::default()) + } + TaskType::DestroyAccount => *self = Task::DestroyAccount(Default::default()), + TaskType::AccountMaintenance => { + *self = Task::AccountMaintenance(Default::default()) + } + TaskType::TenantMaintenance => *self = Task::TenantMaintenance(Default::default()), + TaskType::StoreMaintenance => *self = Task::StoreMaintenance(Default::default()), + TaskType::SpamFilterMaintenance => { + *self = Task::SpamFilterMaintenance(Default::default()) + } + TaskType::AcmeRenewal => *self = Task::AcmeRenewal(Default::default()), + TaskType::DkimManagement => *self = Task::DkimManagement(Default::default()), + TaskType::DnsManagement => *self = Task::DnsManagement(Default::default()), + } + } + match self { + Task::IndexDocument(inner) => inner.patch(pointer, value), + Task::UnindexDocument(inner) => inner.patch(pointer, value), + Task::IndexTrace(inner) => inner.patch(pointer, value), + Task::CalendarAlarmEmail(inner) => inner.patch(pointer, value), + Task::CalendarAlarmNotification(inner) => inner.patch(pointer, value), + Task::CalendarItipMessage(inner) => inner.patch(pointer, value), + Task::MergeThreads(inner) => inner.patch(pointer, value), + Task::DmarcReport(inner) => inner.patch(pointer, value), + Task::TlsReport(inner) => inner.patch(pointer, value), + Task::RestoreArchivedItem(inner) => inner.patch(pointer, value), + Task::DestroyAccount(inner) => inner.patch(pointer, value), + Task::AccountMaintenance(inner) => inner.patch(pointer, value), + Task::TenantMaintenance(inner) => inner.patch(pointer, value), + Task::StoreMaintenance(inner) => inner.patch(pointer, value), + Task::SpamFilterMaintenance(inner) => inner.patch(pointer, value), + Task::AcmeRenewal(inner) => inner.patch(pointer, value), + Task::DkimManagement(inner) => inner.patch(pointer, value), + Task::DnsManagement(inner) => inner.patch(pointer, value), + } + } +} + +impl Task { + pub fn object_type(&self) -> TaskType { + match self { + Task::IndexDocument(_) => TaskType::IndexDocument, + Task::UnindexDocument(_) => TaskType::UnindexDocument, + Task::IndexTrace(_) => TaskType::IndexTrace, + Task::CalendarAlarmEmail(_) => TaskType::CalendarAlarmEmail, + Task::CalendarAlarmNotification(_) => TaskType::CalendarAlarmNotification, + Task::CalendarItipMessage(_) => TaskType::CalendarItipMessage, + Task::MergeThreads(_) => TaskType::MergeThreads, + Task::DmarcReport(_) => TaskType::DmarcReport, + Task::TlsReport(_) => TaskType::TlsReport, + Task::RestoreArchivedItem(_) => TaskType::RestoreArchivedItem, + Task::DestroyAccount(_) => TaskType::DestroyAccount, + Task::AccountMaintenance(_) => TaskType::AccountMaintenance, + Task::TenantMaintenance(_) => TaskType::TenantMaintenance, + Task::StoreMaintenance(_) => TaskType::StoreMaintenance, + Task::SpamFilterMaintenance(_) => TaskType::SpamFilterMaintenance, + Task::AcmeRenewal(_) => TaskType::AcmeRenewal, + Task::DkimManagement(_) => TaskType::DkimManagement, + Task::DnsManagement(_) => TaskType::DnsManagement, + } + } +} + +impl TaskAccountMaintenance { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskAccountMaintenance { + fn pickle(&self, out: &mut Vec) { + self.account_id.pickle(out); + self.maintenance_type.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.account_id = Pickle::unpickle(stream)?; + this.maintenance_type = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskAccountMaintenance { + fn default() -> Self { + Self { + account_id: Default::default(), + maintenance_type: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskAccountMaintenance { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked( + Property::MaintenanceType, + self.maintenance_type.into_value(), + ); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskAccountMaintenance { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::MaintenanceType) => self + .maintenance_type + .patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskCalendarAlarmEmail { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.event_start; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::EventStart, value)); + } + let value = &self.event_end; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::EventEnd, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.document_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DocumentId, value)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskCalendarAlarmEmail { + fn pickle(&self, out: &mut Vec) { + self.alarm_id.pickle(out); + self.event_id.pickle(out); + self.event_start.pickle(out); + self.event_end.pickle(out); + self.event_start_tz.pickle(out); + self.event_end_tz.pickle(out); + self.account_id.pickle(out); + self.document_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.alarm_id = Pickle::unpickle(stream)?; + this.event_id = Pickle::unpickle(stream)?; + this.event_start = Pickle::unpickle(stream)?; + this.event_end = Pickle::unpickle(stream)?; + this.event_start_tz = Pickle::unpickle(stream)?; + this.event_end_tz = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.document_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskCalendarAlarmEmail { + fn default() -> Self { + Self { + alarm_id: 0u64, + event_id: 0u64, + event_start: Default::default(), + event_end: Default::default(), + event_start_tz: 0u64, + event_end_tz: 0u64, + account_id: Default::default(), + document_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskCalendarAlarmEmail { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(11); + map.insert_unchecked(Property::AlarmId, self.alarm_id.into_value()); + map.insert_unchecked(Property::EventId, self.event_id.into_value()); + map.insert_unchecked(Property::EventStart, self.event_start.into_value()); + map.insert_unchecked(Property::EventEnd, self.event_end.into_value()); + map.insert_unchecked(Property::EventStartTz, self.event_start_tz.into_value()); + map.insert_unchecked(Property::EventEndTz, self.event_end_tz.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::DocumentId, self.document_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskCalendarAlarmEmail { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AlarmId) => pointer.assert_server_set(), + Some(Property::EventId) => pointer.assert_server_set(), + Some(Property::EventStart) => pointer.assert_server_set(), + Some(Property::EventEnd) => pointer.assert_server_set(), + Some(Property::EventStartTz) => pointer.assert_server_set(), + Some(Property::EventEndTz) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::DocumentId) => { + self.document_id.patch(pointer.assert_read_only()?, value) + } + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskCalendarAlarmNotification { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.document_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DocumentId, value)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskCalendarAlarmNotification { + fn pickle(&self, out: &mut Vec) { + self.alarm_id.pickle(out); + self.event_id.pickle(out); + self.recurrence_id.pickle(out); + self.account_id.pickle(out); + self.document_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.alarm_id = Pickle::unpickle(stream)?; + this.event_id = Pickle::unpickle(stream)?; + this.recurrence_id = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.document_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskCalendarAlarmNotification { + fn default() -> Self { + Self { + alarm_id: 0u64, + event_id: 0u64, + recurrence_id: Default::default(), + account_id: Default::default(), + document_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskCalendarAlarmNotification { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::AlarmId, self.alarm_id.into_value()); + map.insert_unchecked(Property::EventId, self.event_id.into_value()); + map.insert_unchecked(Property::RecurrenceId, self.recurrence_id.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::DocumentId, self.document_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskCalendarAlarmNotification { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AlarmId) => pointer.assert_server_set(), + Some(Property::EventId) => pointer.assert_server_set(), + Some(Property::RecurrenceId) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::DocumentId) => { + self.document_id.patch(pointer.assert_read_only()?, value) + } + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskCalendarItipContents { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::To)); + } + } + let value = &self.i_calendar_data; + if value.is_empty() { + errors.push(ValidationError::required(Property::ICalendarData)); + } + let value = &self.summary; + if value.is_empty() { + errors.push(ValidationError::required(Property::Summary)); + } + errors.len() == neb + } +} + +impl Pickle for TaskCalendarItipContents { + fn pickle(&self, out: &mut Vec) { + self.from.pickle(out); + self.to.pickle(out); + self.is_from_organizer.pickle(out); + self.i_calendar_data.pickle(out); + self.summary.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.from = Pickle::unpickle(stream)?; + this.to = Pickle::unpickle(stream)?; + this.is_from_organizer = Pickle::unpickle(stream)?; + this.i_calendar_data = Pickle::unpickle(stream)?; + this.summary = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskCalendarItipContents { + fn default() -> Self { + Self { + from: Default::default(), + to: Default::default(), + is_from_organizer: false, + i_calendar_data: Default::default(), + summary: Default::default(), + } + } +} + +impl IntoValue for TaskCalendarItipContents { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::To, self.to.into_value()); + map.insert_unchecked( + Property::IsFromOrganizer, + self.is_from_organizer.into_value(), + ); + map.insert_unchecked(Property::ICalendarData, self.i_calendar_data.into_value()); + map.insert_unchecked(Property::Summary, self.summary.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskCalendarItipContents { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::From) => pointer.assert_server_set(), + Some(Property::To) => pointer.assert_server_set(), + Some(Property::IsFromOrganizer) => pointer.assert_server_set(), + Some(Property::ICalendarData) => pointer.assert_server_set(), + Some(Property::Summary) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskCalendarItipMessage { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.messages; + for value in value.values() { + value.validate(errors); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.document_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DocumentId, value)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskCalendarItipMessage { + fn pickle(&self, out: &mut Vec) { + self.messages.pickle(out); + self.account_id.pickle(out); + self.document_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.messages = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.document_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskCalendarItipMessage { + fn default() -> Self { + Self { + messages: Default::default(), + account_id: Default::default(), + document_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskCalendarItipMessage { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Messages, self.messages.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::DocumentId, self.document_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskCalendarItipMessage { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Messages) => pointer.assert_server_set(), + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::DocumentId) => { + self.document_id.patch(pointer.assert_read_only()?, value) + } + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskDestroyAccount { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.account_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::AccountName)); + } + let value = &self.account_domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountDomainId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + i.foreign_key(ObjectType::Domain, self.account_domain_id.into(), None); + } +} + +impl Pickle for TaskDestroyAccount { + fn pickle(&self, out: &mut Vec) { + self.account_id.pickle(out); + self.account_name.pickle(out); + self.account_domain_id.pickle(out); + self.account_type.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.account_id = Pickle::unpickle(stream)?; + this.account_name = Pickle::unpickle(stream)?; + this.account_domain_id = Pickle::unpickle(stream)?; + this.account_type = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskDestroyAccount { + fn default() -> Self { + Self { + account_id: Default::default(), + account_name: Default::default(), + account_domain_id: Default::default(), + account_type: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskDestroyAccount { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::AccountName, self.account_name.into_value()); + map.insert_unchecked( + Property::AccountDomainId, + self.account_domain_id.into_value(), + ); + map.insert_unchecked(Property::AccountType, self.account_type.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskDestroyAccount { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccountId) => pointer.assert_server_set(), + Some(Property::AccountName) => self.account_name.patch(pointer, value), + Some(Property::AccountDomainId) => self.account_domain_id.patch(pointer, value), + Some(Property::AccountType) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskDmarcReport { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.report_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::ReportId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::DmarcInternalReport, self.report_id.into(), None); + } +} + +impl Pickle for TaskDmarcReport { + fn pickle(&self, out: &mut Vec) { + self.report_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.report_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskDmarcReport { + fn default() -> Self { + Self { + report_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskDmarcReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::ReportId, self.report_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskDmarcReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ReportId) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskDnsManagement { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + } +} + +impl Pickle for TaskDnsManagement { + fn pickle(&self, out: &mut Vec) { + self.update_records.pickle(out); + self.on_success_renew_certificate.pickle(out); + self.domain_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.update_records = Pickle::unpickle(stream)?; + this.on_success_renew_certificate = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskDnsManagement { + fn default() -> Self { + Self { + update_records: Default::default(), + on_success_renew_certificate: false, + domain_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskDnsManagement { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::UpdateRecords, self.update_records.into_value()); + map.insert_unchecked( + Property::OnSuccessRenewCertificate, + self.on_success_renew_certificate.into_value(), + ); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskDnsManagement { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::UpdateRecords) => self.update_records.patch(pointer, value), + Some(Property::OnSuccessRenewCertificate) => { + self.on_success_renew_certificate.patch(pointer, value) + } + Some(Property::DomainId) => self.domain_id.patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskDomainManagement { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + } +} + +impl Pickle for TaskDomainManagement { + fn pickle(&self, out: &mut Vec) { + self.domain_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.domain_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskDomainManagement { + fn default() -> Self { + Self { + domain_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskDomainManagement { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskDomainManagement { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DomainId) => self.domain_id.patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskIndexDocument { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.document_id; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DocumentId, value)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskIndexDocument { + fn pickle(&self, out: &mut Vec) { + self.document_type.pickle(out); + self.account_id.pickle(out); + self.document_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.document_type = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.document_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskIndexDocument { + fn default() -> Self { + Self { + document_type: Default::default(), + account_id: Default::default(), + document_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskIndexDocument { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::DocumentType, self.document_type.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::DocumentId, self.document_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskIndexDocument { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::DocumentType) => { + self.document_type.patch(pointer.assert_read_only()?, value) + } + Some(Property::AccountId) => self + .account_id + .patch(pointer.assert_read_only()?.assert_can_set_account()?, value), + Some(Property::DocumentId) => { + self.document_id.patch(pointer.assert_read_only()?, value) + } + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskIndexTrace { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.trace_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::TraceId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Trace, self.trace_id.into(), None); + } +} + +impl Pickle for TaskIndexTrace { + fn pickle(&self, out: &mut Vec) { + self.trace_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.trace_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskIndexTrace { + fn default() -> Self { + Self { + trace_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskIndexTrace { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::TraceId, self.trace_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskIndexTrace { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::TraceId) => self.trace_id.patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for TaskManager { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::TaskManager; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.max_attempts; + if *value < 1 { + errors.push(ValidationError::min_value(Property::MaxAttempts, 1)); + } + let value = &self.strategy; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for TaskManager { + fn pickle(&self, out: &mut Vec) { + self.max_attempts.pickle(out); + self.strategy.pickle(out); + self.total_deadline.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.max_attempts = Pickle::unpickle(stream)?; + this.strategy = Pickle::unpickle(stream)?; + this.total_deadline = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskManager { + fn default() -> Self { + Self { + max_attempts: 3u64, + strategy: Default::default(), + total_deadline: Duration::from_millis(21600000), + } + } +} + +impl IntoValue for TaskManager { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::MaxAttempts, self.max_attempts.into_value()); + map.insert_unchecked(Property::Strategy, self.strategy.into_value()); + map.insert_unchecked(Property::TotalDeadline, self.total_deadline.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskManager { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaxAttempts) => self.max_attempts.patch(pointer, value), + Some(Property::Strategy) => self.strategy.patch(pointer, value), + Some(Property::TotalDeadline) => self.total_deadline.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskMergeThreads { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.thread_name; + if value.is_empty() { + errors.push(ValidationError::required(Property::ThreadName)); + } + let value = &self.message_ids; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::MessageIds)); + } + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskMergeThreads { + fn pickle(&self, out: &mut Vec) { + self.account_id.pickle(out); + self.thread_name.pickle(out); + self.message_ids.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.account_id = Pickle::unpickle(stream)?; + this.thread_name = Pickle::unpickle(stream)?; + this.message_ids = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskMergeThreads { + fn default() -> Self { + Self { + account_id: Default::default(), + thread_name: Default::default(), + message_ids: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskMergeThreads { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::ThreadName, self.thread_name.into_value()); + map.insert_unchecked(Property::MessageIds, self.message_ids.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskMergeThreads { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AccountId) => pointer.assert_server_set(), + Some(Property::ThreadName) => pointer.assert_server_set(), + Some(Property::MessageIds) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskRestoreArchivedItem { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.blob_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::BlobId)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.archived_until; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ArchivedUntil, value)); + } + let value = &self.account_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::AccountId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Account, self.account_id.into(), None); + } +} + +impl Pickle for TaskRestoreArchivedItem { + fn pickle(&self, out: &mut Vec) { + self.blob_id.pickle(out); + self.archived_item_type.pickle(out); + self.created_at.pickle(out); + self.archived_until.pickle(out); + self.account_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.blob_id = Pickle::unpickle(stream)?; + this.archived_item_type = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.archived_until = Pickle::unpickle(stream)?; + this.account_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskRestoreArchivedItem { + fn default() -> Self { + Self { + blob_id: Default::default(), + archived_item_type: Default::default(), + created_at: Default::default(), + archived_until: Default::default(), + account_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskRestoreArchivedItem { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::BlobId, self.blob_id.into_value()); + map.insert_unchecked( + Property::ArchivedItemType, + self.archived_item_type.into_value(), + ); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::ArchivedUntil, self.archived_until.into_value()); + map.insert_unchecked(Property::AccountId, self.account_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskRestoreArchivedItem { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::BlobId) => pointer.assert_server_set(), + Some(Property::ArchivedItemType) => pointer.assert_server_set(), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::ArchivedUntil) => pointer.assert_server_set(), + Some(Property::AccountId) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskRetryStrategy { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + TaskRetryStrategy::ExponentialBackoff(inner) => inner.validate(errors), + TaskRetryStrategy::FixedDelay(inner) => inner.validate(errors), + } + } +} + +impl Default for TaskRetryStrategy { + fn default() -> Self { + TaskRetryStrategy::ExponentialBackoff(Default::default()) + } +} + +impl Pickle for TaskRetryStrategy { + fn pickle(&self, out: &mut Vec) { + match self { + TaskRetryStrategy::ExponentialBackoff(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + TaskRetryStrategy::FixedDelay(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(TaskRetryStrategy::ExponentialBackoff), + 1 => Pickle::unpickle(stream).map(TaskRetryStrategy::FixedDelay), + _ => None, + } + } +} + +impl IntoValue for TaskRetryStrategy { + fn into_value(self) -> JmapValue<'static> { + match self { + TaskRetryStrategy::ExponentialBackoff(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("ExponentialBackoff".into())); + obj + } + TaskRetryStrategy::FixedDelay(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FixedDelay".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for TaskRetryStrategy { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TaskRetryStrategyType::ExponentialBackoff => { + *self = TaskRetryStrategy::ExponentialBackoff(Default::default()) + } + TaskRetryStrategyType::FixedDelay => { + *self = TaskRetryStrategy::FixedDelay(Default::default()) + } + } + } + match self { + TaskRetryStrategy::ExponentialBackoff(inner) => inner.patch(pointer, value), + TaskRetryStrategy::FixedDelay(inner) => inner.patch(pointer, value), + } + } +} + +impl TaskRetryStrategy { + pub fn object_type(&self) -> TaskRetryStrategyType { + match self { + TaskRetryStrategy::ExponentialBackoff(_) => TaskRetryStrategyType::ExponentialBackoff, + TaskRetryStrategy::FixedDelay(_) => TaskRetryStrategyType::FixedDelay, + } + } +} + +impl TaskRetryStrategyBackoff { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.factor; + if *value < Float::new(1.0) { + errors.push(ValidationError::min_value(Property::Factor, 1)); + } + errors.len() == neb + } +} + +impl Pickle for TaskRetryStrategyBackoff { + fn pickle(&self, out: &mut Vec) { + self.factor.pickle(out); + self.initial_delay.pickle(out); + self.max_delay.pickle(out); + self.jitter.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.factor = Pickle::unpickle(stream)?; + this.initial_delay = Pickle::unpickle(stream)?; + this.max_delay = Pickle::unpickle(stream)?; + this.jitter = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskRetryStrategyBackoff { + fn default() -> Self { + Self { + factor: Float::new(2.0f64), + initial_delay: Duration::from_millis(60000), + max_delay: Duration::from_millis(1800000), + jitter: true, + } + } +} + +impl IntoValue for TaskRetryStrategyBackoff { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::Factor, self.factor.into_value()); + map.insert_unchecked(Property::InitialDelay, self.initial_delay.into_value()); + map.insert_unchecked(Property::MaxDelay, self.max_delay.into_value()); + map.insert_unchecked(Property::Jitter, self.jitter.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskRetryStrategyBackoff { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Factor) => self.factor.patch(pointer, value), + Some(Property::InitialDelay) => self.initial_delay.patch(pointer, value), + Some(Property::MaxDelay) => self.max_delay.patch(pointer, value), + Some(Property::Jitter) => self.jitter.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskRetryStrategyFixed { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TaskRetryStrategyFixed { + fn pickle(&self, out: &mut Vec) { + self.delay.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.delay = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskRetryStrategyFixed { + fn default() -> Self { + Self { + delay: Duration::from_millis(300000), + } + } +} + +impl IntoValue for TaskRetryStrategyFixed { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Delay, self.delay.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskRetryStrategyFixed { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Delay) => self.delay.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskSpamFilterMaintenance { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.status; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for TaskSpamFilterMaintenance { + fn pickle(&self, out: &mut Vec) { + self.maintenance_type.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.maintenance_type = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskSpamFilterMaintenance { + fn default() -> Self { + Self { + maintenance_type: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskSpamFilterMaintenance { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked( + Property::MaintenanceType, + self.maintenance_type.into_value(), + ); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskSpamFilterMaintenance { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaintenanceType) => self + .maintenance_type + .patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskStatus { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + TaskStatus::Pending(inner) => inner.validate(errors), + TaskStatus::Retry(inner) => inner.validate(errors), + TaskStatus::Failed(inner) => inner.validate(errors), + } + } +} + +impl Default for TaskStatus { + fn default() -> Self { + TaskStatus::Pending(Default::default()) + } +} + +impl Pickle for TaskStatus { + fn pickle(&self, out: &mut Vec) { + match self { + TaskStatus::Pending(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + TaskStatus::Retry(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + TaskStatus::Failed(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(TaskStatus::Pending), + 1 => Pickle::unpickle(stream).map(TaskStatus::Retry), + 2 => Pickle::unpickle(stream).map(TaskStatus::Failed), + _ => None, + } + } +} + +impl IntoValue for TaskStatus { + fn into_value(self) -> JmapValue<'static> { + match self { + TaskStatus::Pending(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Pending".into())); + obj + } + TaskStatus::Retry(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Retry".into())); + obj + } + TaskStatus::Failed(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Failed".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for TaskStatus { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TaskStatusType::Pending => *self = TaskStatus::Pending(Default::default()), + TaskStatusType::Retry => *self = TaskStatus::Retry(Default::default()), + TaskStatusType::Failed => *self = TaskStatus::Failed(Default::default()), + } + } + match self { + TaskStatus::Pending(inner) => inner.patch(pointer, value), + TaskStatus::Retry(inner) => inner.patch(pointer, value), + TaskStatus::Failed(inner) => inner.patch(pointer, value), + } + } +} + +impl TaskStatus { + pub fn object_type(&self) -> TaskStatusType { + match self { + TaskStatus::Pending(_) => TaskStatusType::Pending, + TaskStatus::Retry(_) => TaskStatusType::Retry, + TaskStatus::Failed(_) => TaskStatusType::Failed, + } + } +} + +impl TaskStatusFailed { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.failed_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::FailedAt, value)); + } + let value = &self.failure_reason; + if value.is_empty() { + errors.push(ValidationError::required(Property::FailureReason)); + } + errors.len() == neb + } +} + +impl Pickle for TaskStatusFailed { + fn pickle(&self, out: &mut Vec) { + self.created_at.pickle(out); + self.failed_at.pickle(out); + self.failed_attempt_number.pickle(out); + self.failure_reason.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.created_at = Pickle::unpickle(stream)?; + this.failed_at = Pickle::unpickle(stream)?; + this.failed_attempt_number = Pickle::unpickle(stream)?; + this.failure_reason = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskStatusFailed { + fn default() -> Self { + Self { + created_at: Default::default(), + failed_at: Default::default(), + failed_attempt_number: 0u64, + failure_reason: Default::default(), + } + } +} + +impl IntoValue for TaskStatusFailed { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::FailedAt, self.failed_at.into_value()); + map.insert_unchecked( + Property::FailedAttemptNumber, + self.failed_attempt_number.into_value(), + ); + map.insert_unchecked(Property::FailureReason, self.failure_reason.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskStatusFailed { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::FailedAt) => self.failed_at.patch(pointer, value), + Some(Property::FailedAttemptNumber) => self.failed_attempt_number.patch(pointer, value), + Some(Property::FailureReason) => self.failure_reason.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskStatusPending { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.due; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Due, value)); + } + errors.len() == neb + } +} + +impl Pickle for TaskStatusPending { + fn pickle(&self, out: &mut Vec) { + self.created_at.pickle(out); + self.due.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.created_at = Pickle::unpickle(stream)?; + this.due = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskStatusPending { + fn default() -> Self { + Self { + created_at: Default::default(), + due: Default::default(), + } + } +} + +impl IntoValue for TaskStatusPending { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::Due, self.due.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskStatusPending { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::Due) => self.due.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskStatusRetry { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.due; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Due, value)); + } + let value = &self.failure_reason; + if value.is_empty() { + errors.push(ValidationError::required(Property::FailureReason)); + } + errors.len() == neb + } +} + +impl Pickle for TaskStatusRetry { + fn pickle(&self, out: &mut Vec) { + self.created_at.pickle(out); + self.due.pickle(out); + self.attempt_number.pickle(out); + self.failure_reason.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.created_at = Pickle::unpickle(stream)?; + this.due = Pickle::unpickle(stream)?; + this.attempt_number = Pickle::unpickle(stream)?; + this.failure_reason = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskStatusRetry { + fn default() -> Self { + Self { + created_at: Default::default(), + due: Default::default(), + attempt_number: 1u64, + failure_reason: Default::default(), + } + } +} + +impl IntoValue for TaskStatusRetry { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(6); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::Due, self.due.into_value()); + map.insert_unchecked(Property::AttemptNumber, self.attempt_number.into_value()); + map.insert_unchecked(Property::FailureReason, self.failure_reason.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskStatusRetry { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::Due) => self.due.patch(pointer, value), + Some(Property::AttemptNumber) => self.attempt_number.patch(pointer, value), + Some(Property::FailureReason) => self.failure_reason.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskStoreMaintenance { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.status; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for TaskStoreMaintenance { + fn pickle(&self, out: &mut Vec) { + self.maintenance_type.pickle(out); + self.shard_index.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.maintenance_type = Pickle::unpickle(stream)?; + this.shard_index = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskStoreMaintenance { + fn default() -> Self { + Self { + maintenance_type: Default::default(), + shard_index: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskStoreMaintenance { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked( + Property::MaintenanceType, + self.maintenance_type.into_value(), + ); + map.insert_unchecked(Property::ShardIndex, self.shard_index.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskStoreMaintenance { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::MaintenanceType) => self + .maintenance_type + .patch(pointer.assert_read_only()?, value), + Some(Property::ShardIndex) => self.shard_index.patch(pointer, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskTenantMaintenance { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.tenant_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::TenantId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.tenant_id.into(), None); + } +} + +impl Pickle for TaskTenantMaintenance { + fn pickle(&self, out: &mut Vec) { + self.tenant_id.pickle(out); + self.maintenance_type.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.tenant_id = Pickle::unpickle(stream)?; + this.maintenance_type = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskTenantMaintenance { + fn default() -> Self { + Self { + tenant_id: Default::default(), + maintenance_type: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskTenantMaintenance { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::TenantId, self.tenant_id.into_value()); + map.insert_unchecked( + Property::MaintenanceType, + self.maintenance_type.into_value(), + ); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskTenantMaintenance { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::TenantId) => self.tenant_id.patch(pointer.assert_read_only()?, value), + Some(Property::MaintenanceType) => self + .maintenance_type + .patch(pointer.assert_read_only()?, value), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TaskTlsReport { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.report_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::ReportId)); + } + let value = &self.status; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::TlsInternalReport, self.report_id.into(), None); + } +} + +impl Pickle for TaskTlsReport { + fn pickle(&self, out: &mut Vec) { + self.report_id.pickle(out); + self.status.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.report_id = Pickle::unpickle(stream)?; + this.status = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TaskTlsReport { + fn default() -> Self { + Self { + report_id: Default::default(), + status: Default::default(), + } + } +} + +impl IntoValue for TaskTlsReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::ReportId, self.report_id.into_value()); + map.insert_unchecked(Property::Status, self.status.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TaskTlsReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ReportId) => pointer.assert_server_set(), + Some(Property::Status) => self.status.patch(pointer, value), + Some(Property::Due) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Tenant { + const FLAGS: u64 = OBJ_SEQ_ID; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Tenant; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + if let Some(value) = &self.logo { + if value.is_empty() { + errors.push(ValidationError::required(Property::Logo)); + } + } + let value = &self.roles; + value.validate(errors); + let value = &self.permissions; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.text(Property::Text, &self.name); + self.roles.index(i); + } +} + +impl Pickle for Tenant { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.created_at.pickle(out); + self.logo.pickle(out); + self.roles.pickle(out); + self.permissions.pickle(out); + self.quotas.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.logo = Pickle::unpickle(stream)?; + this.roles = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.quotas = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Tenant { + fn default() -> Self { + Self { + name: Default::default(), + created_at: Default::default(), + logo: Default::default(), + roles: Default::default(), + permissions: Default::default(), + quotas: Default::default(), + } + } +} + +impl IntoValue for Tenant { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::Logo, self.logo.into_value()); + map.insert_unchecked(Property::Roles, self.roles.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::Quotas, self.quotas.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Tenant { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::Logo) => self.logo.patch(pointer, value), + Some(Property::Roles) => self.roles.patch(pointer, value), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::Quotas) => self.quotas.patch(pointer, value), + Some(Property::UsedDiskQuota) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for TlsExternalReport { + const FLAGS: u64 = OBJ_FILTER_TENANT; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::TlsExternalReport; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.report; + value.validate(errors); + let value = &self.from; + if value.is_empty() { + errors.push(ValidationError::required(Property::From)); + } + let value = &self.subject; + if value.is_empty() { + errors.push(ValidationError::required(Property::Subject)); + } + let value = &self.to; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::To)); + } + } + let value = &self.received_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivedAt, value)); + } + let value = &self.expires_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ExpiresAt, value)); + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + } +} + +impl Pickle for TlsExternalReport { + fn pickle(&self, out: &mut Vec) { + self.report.pickle(out); + self.from.pickle(out); + self.subject.pickle(out); + self.to.pickle(out); + self.received_at.pickle(out); + self.expires_at.pickle(out); + self.member_tenant_id.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.report = Pickle::unpickle(stream)?; + this.from = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + this.to = Pickle::unpickle(stream)?; + this.received_at = Pickle::unpickle(stream)?; + this.expires_at = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsExternalReport { + fn default() -> Self { + Self { + report: Default::default(), + from: Default::default(), + subject: Default::default(), + to: Default::default(), + received_at: Default::default(), + expires_at: Default::default(), + member_tenant_id: Default::default(), + } + } +} + +impl IntoValue for TlsExternalReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::From, self.from.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + map.insert_unchecked(Property::To, self.to.into_value()); + map.insert_unchecked(Property::ReceivedAt, self.received_at.into_value()); + map.insert_unchecked(Property::ExpiresAt, self.expires_at.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsExternalReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::From) => self + .from + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::To) => self + .to + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::ReceivedAt) => self.received_at.patch(pointer, value), + Some(Property::ExpiresAt) => self.expires_at.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TlsFailureDetails { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.sending_mta_ip { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::SendingMtaIp, value)); + } + } + if let Some(value) = &self.receiving_mx_hostname { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReceivingMxHostname)); + } + } + if let Some(value) = &self.receiving_mx_helo { + if value.is_empty() { + errors.push(ValidationError::required(Property::ReceivingMxHelo)); + } + } + if let Some(value) = &self.receiving_ip { + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::ReceivingIp, value)); + } + } + if let Some(value) = &self.additional_information { + if value.is_empty() { + errors.push(ValidationError::required(Property::AdditionalInformation)); + } + } + if let Some(value) = &self.failure_reason_code { + if value.is_empty() { + errors.push(ValidationError::required(Property::FailureReasonCode)); + } + } + errors.len() == neb + } +} + +impl Pickle for TlsFailureDetails { + fn pickle(&self, out: &mut Vec) { + self.result_type.pickle(out); + self.sending_mta_ip.pickle(out); + self.receiving_mx_hostname.pickle(out); + self.receiving_mx_helo.pickle(out); + self.receiving_ip.pickle(out); + self.failed_session_count.pickle(out); + self.additional_information.pickle(out); + self.failure_reason_code.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.result_type = Pickle::unpickle(stream)?; + this.sending_mta_ip = Pickle::unpickle(stream)?; + this.receiving_mx_hostname = Pickle::unpickle(stream)?; + this.receiving_mx_helo = Pickle::unpickle(stream)?; + this.receiving_ip = Pickle::unpickle(stream)?; + this.failed_session_count = Pickle::unpickle(stream)?; + this.additional_information = Pickle::unpickle(stream)?; + this.failure_reason_code = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsFailureDetails { + fn default() -> Self { + Self { + result_type: Default::default(), + sending_mta_ip: Default::default(), + receiving_mx_hostname: Default::default(), + receiving_mx_helo: Default::default(), + receiving_ip: Default::default(), + failed_session_count: 0u64, + additional_information: Default::default(), + failure_reason_code: Default::default(), + } + } +} + +impl IntoValue for TlsFailureDetails { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::ResultType, self.result_type.into_value()); + map.insert_unchecked(Property::SendingMtaIp, self.sending_mta_ip.into_value()); + map.insert_unchecked( + Property::ReceivingMxHostname, + self.receiving_mx_hostname.into_value(), + ); + map.insert_unchecked( + Property::ReceivingMxHelo, + self.receiving_mx_helo.into_value(), + ); + map.insert_unchecked(Property::ReceivingIp, self.receiving_ip.into_value()); + map.insert_unchecked( + Property::FailedSessionCount, + self.failed_session_count.into_value(), + ); + map.insert_unchecked( + Property::AdditionalInformation, + self.additional_information.into_value(), + ); + map.insert_unchecked( + Property::FailureReasonCode, + self.failure_reason_code.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsFailureDetails { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ResultType) => self.result_type.patch(pointer, value), + Some(Property::SendingMtaIp) => self.sending_mta_ip.patch(pointer, value), + Some(Property::ReceivingMxHostname) => self.receiving_mx_hostname.patch(pointer, value), + Some(Property::ReceivingMxHelo) => self.receiving_mx_helo.patch(pointer, value), + Some(Property::ReceivingIp) => self.receiving_ip.patch(pointer, value), + Some(Property::FailedSessionCount) => self.failed_session_count.patch(pointer, value), + Some(Property::AdditionalInformation) => { + self.additional_information.patch(pointer, value) + } + Some(Property::FailureReasonCode) => self.failure_reason_code.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for TlsInternalReport { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::TlsInternalReport; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.mail_rua; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::MailRua)); + } + } + let value = &self.http_rua; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpRua)); + } + } + let value = &self.report; + value.validate(errors); + let value = &self.domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::Domain)); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.deliver_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DeliverAt, value)); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for TlsInternalReport { + fn pickle(&self, out: &mut Vec) { + self.policy_identifiers.pickle(out); + self.mail_rua.pickle(out); + self.http_rua.pickle(out); + self.report.pickle(out); + self.domain.pickle(out); + self.created_at.pickle(out); + self.deliver_at.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.policy_identifiers = Pickle::unpickle(stream)?; + this.mail_rua = Pickle::unpickle(stream)?; + this.http_rua = Pickle::unpickle(stream)?; + this.report = Pickle::unpickle(stream)?; + this.domain = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.deliver_at = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsInternalReport { + fn default() -> Self { + Self { + policy_identifiers: Default::default(), + mail_rua: Default::default(), + http_rua: Default::default(), + report: Default::default(), + domain: Default::default(), + created_at: Default::default(), + deliver_at: Default::default(), + } + } +} + +impl IntoValue for TlsInternalReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked( + Property::PolicyIdentifiers, + self.policy_identifiers.into_value(), + ); + map.insert_unchecked(Property::MailRua, self.mail_rua.into_value()); + map.insert_unchecked(Property::HttpRua, self.http_rua.into_value()); + map.insert_unchecked(Property::Report, self.report.into_value()); + map.insert_unchecked(Property::Domain, self.domain.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::DeliverAt, self.deliver_at.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsInternalReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::PolicyIdentifiers) => self.policy_identifiers.patch(pointer, value), + Some(Property::MailRua) => self + .mail_rua + .patch(pointer.with_validators(&[StringValidator::Email]), value), + Some(Property::HttpRua) => self.http_rua.patch(pointer, value), + Some(Property::Report) => self.report.patch(pointer, value), + Some(Property::Domain) => self + .domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::CreatedAt) => self.created_at.patch(pointer, value), + Some(Property::DeliverAt) => self.deliver_at.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TlsReport { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.organization_name { + if value.is_empty() { + errors.push(ValidationError::required(Property::OrganizationName)); + } + } + if let Some(value) = &self.contact_info { + if value.is_empty() { + errors.push(ValidationError::required(Property::ContactInfo)); + } + } + let value = &self.report_id; + if value.is_empty() { + errors.push(ValidationError::required(Property::ReportId)); + } + let value = &self.date_range_start; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DateRangeStart, value)); + } + let value = &self.date_range_end; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::DateRangeEnd, value)); + } + let value = &self.policies; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for TlsReport { + fn pickle(&self, out: &mut Vec) { + self.organization_name.pickle(out); + self.contact_info.pickle(out); + self.report_id.pickle(out); + self.date_range_start.pickle(out); + self.date_range_end.pickle(out); + self.policies.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.organization_name = Pickle::unpickle(stream)?; + this.contact_info = Pickle::unpickle(stream)?; + this.report_id = Pickle::unpickle(stream)?; + this.date_range_start = Pickle::unpickle(stream)?; + this.date_range_end = Pickle::unpickle(stream)?; + this.policies = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsReport { + fn default() -> Self { + Self { + organization_name: Default::default(), + contact_info: Default::default(), + report_id: Default::default(), + date_range_start: Default::default(), + date_range_end: Default::default(), + policies: Default::default(), + } + } +} + +impl IntoValue for TlsReport { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(8); + map.insert_unchecked( + Property::OrganizationName, + self.organization_name.into_value(), + ); + map.insert_unchecked(Property::ContactInfo, self.contact_info.into_value()); + map.insert_unchecked(Property::ReportId, self.report_id.into_value()); + map.insert_unchecked(Property::DateRangeStart, self.date_range_start.into_value()); + map.insert_unchecked(Property::DateRangeEnd, self.date_range_end.into_value()); + map.insert_unchecked(Property::Policies, self.policies.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsReport { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::OrganizationName) => self.organization_name.patch(pointer, value), + Some(Property::ContactInfo) => self.contact_info.patch(pointer, value), + Some(Property::ReportId) => self.report_id.patch(pointer, value), + Some(Property::DateRangeStart) => self.date_range_start.patch(pointer, value), + Some(Property::DateRangeEnd) => self.date_range_end.patch(pointer, value), + Some(Property::Policies) => self.policies.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TlsReportPolicy { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.policy_strings; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::PolicyStrings)); + } + } + let value = &self.policy_domain; + if value.is_empty() { + errors.push(ValidationError::required(Property::PolicyDomain)); + } + let value = &self.mx_hosts; + for value in value.iter() { + if value.is_empty() { + errors.push(ValidationError::required(Property::MxHosts)); + } + } + let value = &self.failure_details; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for TlsReportPolicy { + fn pickle(&self, out: &mut Vec) { + self.policy_type.pickle(out); + self.policy_strings.pickle(out); + self.policy_domain.pickle(out); + self.mx_hosts.pickle(out); + self.total_successful_sessions.pickle(out); + self.total_failed_sessions.pickle(out); + self.failure_details.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.policy_type = Pickle::unpickle(stream)?; + this.policy_strings = Pickle::unpickle(stream)?; + this.policy_domain = Pickle::unpickle(stream)?; + this.mx_hosts = Pickle::unpickle(stream)?; + this.total_successful_sessions = Pickle::unpickle(stream)?; + this.total_failed_sessions = Pickle::unpickle(stream)?; + this.failure_details = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsReportPolicy { + fn default() -> Self { + Self { + policy_type: Default::default(), + policy_strings: Default::default(), + policy_domain: Default::default(), + mx_hosts: Default::default(), + total_successful_sessions: 0u64, + total_failed_sessions: 0u64, + failure_details: Default::default(), + } + } +} + +impl IntoValue for TlsReportPolicy { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked(Property::PolicyType, self.policy_type.into_value()); + map.insert_unchecked(Property::PolicyStrings, self.policy_strings.into_value()); + map.insert_unchecked(Property::PolicyDomain, self.policy_domain.into_value()); + map.insert_unchecked(Property::MxHosts, self.mx_hosts.into_value()); + map.insert_unchecked( + Property::TotalSuccessfulSessions, + self.total_successful_sessions.into_value(), + ); + map.insert_unchecked( + Property::TotalFailedSessions, + self.total_failed_sessions.into_value(), + ); + map.insert_unchecked(Property::FailureDetails, self.failure_details.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsReportPolicy { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::PolicyType) => self.policy_type.patch(pointer, value), + Some(Property::PolicyStrings) => self.policy_strings.patch(pointer, value), + Some(Property::PolicyDomain) => self + .policy_domain + .patch(pointer.with_validators(&[StringValidator::Domain]), value), + Some(Property::MxHosts) => self.mx_hosts.patch(pointer, value), + Some(Property::TotalSuccessfulSessions) => { + self.total_successful_sessions.patch(pointer, value) + } + Some(Property::TotalFailedSessions) => self.total_failed_sessions.patch(pointer, value), + Some(Property::FailureDetails) => self.failure_details.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for TlsReportSettings { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::TlsReportSettings; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.contact_info; + value.validate(errors); + let value = &self.from_address; + value.validate(errors); + let value = &self.from_name; + value.validate(errors); + let value = &self.max_report_size; + value.validate(errors); + let value = &self.org_name; + value.validate(errors); + let value = &self.send_frequency; + value.validate(errors); + let value = &self.dkim_sign_domain; + value.validate(errors); + let value = &self.subject; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl TlsReportSettings { + pub fn ctx_contact_info(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.contact_info, + default: Some(Expression { + else_: "false".to_string(), + ..Default::default() + }), + property: Property::ContactInfo, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_from_address(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_address, + default: Some(Expression { + else_: "'noreply-tls@' + system('domain')".to_string(), + ..Default::default() + }), + property: Property::FromAddress, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_from_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.from_name, + default: Some(Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }), + property: Property::FromName, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_max_report_size(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.max_report_size, + default: Some(Expression { + else_: "5242880".to_string(), + ..Default::default() + }), + property: Property::MaxReportSize, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_org_name(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.org_name, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::OrgName, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_send_frequency(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.send_frequency, + default: Some(Expression { + else_: "daily".to_string(), + ..Default::default() + }), + property: Property::SendFrequency, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: MTA_AGGREGATE_CONSTANT, + } + } + + pub fn ctx_dkim_sign_domain(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.dkim_sign_domain, + default: Some(Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }), + property: Property::DkimSignDomain, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn ctx_subject(&self) -> ExpressionContext<'_> { + ExpressionContext { + expr: &self.subject, + default: Some(Expression { + else_: "'TLS Aggregate Report'".to_string(), + ..Default::default() + }), + property: Property::Subject, + allowed_variables: MTA_QUEUE_HOST_VARIABLE, + allowed_constants: &[], + } + } + + pub fn expression_ctxs(&self) -> Vec> { + vec![ + self.ctx_contact_info(), + self.ctx_from_address(), + self.ctx_from_name(), + self.ctx_max_report_size(), + self.ctx_org_name(), + self.ctx_send_frequency(), + self.ctx_dkim_sign_domain(), + self.ctx_subject(), + ] + } +} + +impl Pickle for TlsReportSettings { + fn pickle(&self, out: &mut Vec) { + self.contact_info.pickle(out); + self.from_address.pickle(out); + self.from_name.pickle(out); + self.max_report_size.pickle(out); + self.org_name.pickle(out); + self.send_frequency.pickle(out); + self.dkim_sign_domain.pickle(out); + self.subject.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.contact_info = Pickle::unpickle(stream)?; + this.from_address = Pickle::unpickle(stream)?; + this.from_name = Pickle::unpickle(stream)?; + this.max_report_size = Pickle::unpickle(stream)?; + this.org_name = Pickle::unpickle(stream)?; + this.send_frequency = Pickle::unpickle(stream)?; + this.dkim_sign_domain = Pickle::unpickle(stream)?; + this.subject = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TlsReportSettings { + fn default() -> Self { + Self { + contact_info: Expression { + else_: "false".to_string(), + ..Default::default() + }, + from_address: Expression { + else_: "'noreply-tls@' + system('domain')".to_string(), + ..Default::default() + }, + from_name: Expression { + else_: "'Report Subsystem'".to_string(), + ..Default::default() + }, + max_report_size: Expression { + else_: "5242880".to_string(), + ..Default::default() + }, + org_name: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + send_frequency: Expression { + else_: "daily".to_string(), + ..Default::default() + }, + dkim_sign_domain: Expression { + else_: "system('domain')".to_string(), + ..Default::default() + }, + subject: Expression { + else_: "'TLS Aggregate Report'".to_string(), + ..Default::default() + }, + } + } +} + +impl IntoValue for TlsReportSettings { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::ContactInfo, self.contact_info.into_value()); + map.insert_unchecked(Property::FromAddress, self.from_address.into_value()); + map.insert_unchecked(Property::FromName, self.from_name.into_value()); + map.insert_unchecked(Property::MaxReportSize, self.max_report_size.into_value()); + map.insert_unchecked(Property::OrgName, self.org_name.into_value()); + map.insert_unchecked(Property::SendFrequency, self.send_frequency.into_value()); + map.insert_unchecked(Property::DkimSignDomain, self.dkim_sign_domain.into_value()); + map.insert_unchecked(Property::Subject, self.subject.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TlsReportSettings { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::ContactInfo) => self.contact_info.patch(pointer, value), + Some(Property::FromAddress) => self.from_address.patch(pointer, value), + Some(Property::FromName) => self.from_name.patch(pointer, value), + Some(Property::MaxReportSize) => self.max_report_size.patch(pointer, value), + Some(Property::OrgName) => self.org_name.patch(pointer, value), + Some(Property::SendFrequency) => self.send_frequency.patch(pointer, value), + Some(Property::DkimSignDomain) => self.dkim_sign_domain.patch(pointer, value), + Some(Property::Subject) => self.subject.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Trace { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Trace; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.events; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for Trace { + fn pickle(&self, out: &mut Vec) { + self.events.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.events = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for Trace { + fn default() -> Self { + Self { + events: Default::default(), + } + } +} + +impl IntoValue for Trace { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Events, self.events.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for Trace { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::Timestamp) => pointer.assert_server_set(), + Some(Property::From) => pointer.assert_server_set(), + Some(Property::To) => pointer.assert_server_set(), + Some(Property::Size) => pointer.assert_server_set(), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceEvent { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.timestamp; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Timestamp, value)); + } + let value = &self.key_values; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for TraceEvent { + fn pickle(&self, out: &mut Vec) { + self.event.pickle(out); + self.timestamp.pickle(out); + self.key_values.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.event = Pickle::unpickle(stream)?; + this.timestamp = Pickle::unpickle(stream)?; + this.key_values = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceEvent { + fn default() -> Self { + Self { + event: Default::default(), + timestamp: Default::default(), + key_values: Default::default(), + } + } +} + +impl IntoValue for TraceEvent { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(5); + map.insert_unchecked(Property::Event, self.event.into_value()); + map.insert_unchecked(Property::Timestamp, self.timestamp.into_value()); + map.insert_unchecked(Property::KeyValues, self.key_values.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceEvent { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Event) => self.event.patch(pointer, value), + Some(Property::Timestamp) => self.timestamp.patch(pointer, value), + Some(Property::KeyValues) => self.key_values.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceKeyValue { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + value.validate(errors); + errors.len() == neb + } +} + +impl Pickle for TraceKeyValue { + fn pickle(&self, out: &mut Vec) { + self.key.pickle(out); + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.key = Pickle::unpickle(stream)?; + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceKeyValue { + fn default() -> Self { + Self { + key: Default::default(), + value: Default::default(), + } + } +} + +impl IntoValue for TraceKeyValue { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Key, self.key.into_value()); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceKeyValue { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Key) => self.key.patch(pointer, value), + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValue { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + TraceValue::String(inner) => inner.validate(errors), + TraceValue::UnsignedInt(inner) => inner.validate(errors), + TraceValue::Integer(inner) => inner.validate(errors), + TraceValue::Boolean(inner) => inner.validate(errors), + TraceValue::Float(inner) => inner.validate(errors), + TraceValue::UTCDateTime(inner) => inner.validate(errors), + TraceValue::Duration(inner) => inner.validate(errors), + TraceValue::IpAddr(inner) => inner.validate(errors), + TraceValue::List(inner) => inner.validate(errors), + TraceValue::Event(inner) => inner.validate(errors), + TraceValue::Null => true, + } + } +} + +impl Default for TraceValue { + fn default() -> Self { + TraceValue::String(Default::default()) + } +} + +impl Pickle for TraceValue { + fn pickle(&self, out: &mut Vec) { + match self { + TraceValue::String(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + TraceValue::UnsignedInt(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + TraceValue::Integer(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + TraceValue::Boolean(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + TraceValue::Float(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + TraceValue::UTCDateTime(inner) => { + 5u16.pickle(out); + inner.pickle(out); + } + TraceValue::Duration(inner) => { + 6u16.pickle(out); + inner.pickle(out); + } + TraceValue::IpAddr(inner) => { + 7u16.pickle(out); + inner.pickle(out); + } + TraceValue::List(inner) => { + 8u16.pickle(out); + inner.pickle(out); + } + TraceValue::Event(inner) => { + 9u16.pickle(out); + inner.pickle(out); + } + TraceValue::Null => { + 10u16.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(TraceValue::String), + 1 => Pickle::unpickle(stream).map(TraceValue::UnsignedInt), + 2 => Pickle::unpickle(stream).map(TraceValue::Integer), + 3 => Pickle::unpickle(stream).map(TraceValue::Boolean), + 4 => Pickle::unpickle(stream).map(TraceValue::Float), + 5 => Pickle::unpickle(stream).map(TraceValue::UTCDateTime), + 6 => Pickle::unpickle(stream).map(TraceValue::Duration), + 7 => Pickle::unpickle(stream).map(TraceValue::IpAddr), + 8 => Pickle::unpickle(stream).map(TraceValue::List), + 9 => Pickle::unpickle(stream).map(TraceValue::Event), + 10 => Some(TraceValue::Null), + _ => None, + } + } +} + +impl IntoValue for TraceValue { + fn into_value(self) -> JmapValue<'static> { + match self { + TraceValue::String(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("String".into())); + obj + } + TraceValue::UnsignedInt(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("UnsignedInt".into())); + obj + } + TraceValue::Integer(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Integer".into())); + obj + } + TraceValue::Boolean(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Boolean".into())); + obj + } + TraceValue::Float(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Float".into())); + obj + } + TraceValue::UTCDateTime(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("UTCDateTime".into())); + obj + } + TraceValue::Duration(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Duration".into())); + obj + } + TraceValue::IpAddr(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("IpAddr".into())); + obj + } + TraceValue::List(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("List".into())); + obj + } + TraceValue::Event(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Event".into())); + obj + } + TraceValue::Null => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Null".into())); + JmapValue::Object(obj) + } + } + } +} + +impl RegistryJsonPatch for TraceValue { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TraceValueType::String => *self = TraceValue::String(Default::default()), + TraceValueType::UnsignedInt => *self = TraceValue::UnsignedInt(Default::default()), + TraceValueType::Integer => *self = TraceValue::Integer(Default::default()), + TraceValueType::Boolean => *self = TraceValue::Boolean(Default::default()), + TraceValueType::Float => *self = TraceValue::Float(Default::default()), + TraceValueType::UTCDateTime => *self = TraceValue::UTCDateTime(Default::default()), + TraceValueType::Duration => *self = TraceValue::Duration(Default::default()), + TraceValueType::IpAddr => *self = TraceValue::IpAddr(Default::default()), + TraceValueType::List => *self = TraceValue::List(Default::default()), + TraceValueType::Event => *self = TraceValue::Event(Default::default()), + TraceValueType::Null => *self = TraceValue::Null, + } + } + match self { + TraceValue::String(inner) => inner.patch(pointer, value), + TraceValue::UnsignedInt(inner) => inner.patch(pointer, value), + TraceValue::Integer(inner) => inner.patch(pointer, value), + TraceValue::Boolean(inner) => inner.patch(pointer, value), + TraceValue::Float(inner) => inner.patch(pointer, value), + TraceValue::UTCDateTime(inner) => inner.patch(pointer, value), + TraceValue::Duration(inner) => inner.patch(pointer, value), + TraceValue::IpAddr(inner) => inner.patch(pointer, value), + TraceValue::List(inner) => inner.patch(pointer, value), + TraceValue::Event(inner) => inner.patch(pointer, value), + TraceValue::Null => pointer.assert_eof(), + } + } +} + +impl TraceValue { + pub fn object_type(&self) -> TraceValueType { + match self { + TraceValue::String(_) => TraceValueType::String, + TraceValue::UnsignedInt(_) => TraceValueType::UnsignedInt, + TraceValue::Integer(_) => TraceValueType::Integer, + TraceValue::Boolean(_) => TraceValueType::Boolean, + TraceValue::Float(_) => TraceValueType::Float, + TraceValue::UTCDateTime(_) => TraceValueType::UTCDateTime, + TraceValue::Duration(_) => TraceValueType::Duration, + TraceValue::IpAddr(_) => TraceValueType::IpAddr, + TraceValue::List(_) => TraceValueType::List, + TraceValue::Event(_) => TraceValueType::Event, + TraceValue::Null => TraceValueType::Null, + } + } +} + +impl TraceValueBoolean { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TraceValueBoolean { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueBoolean { + fn default() -> Self { + Self { value: false } + } +} + +impl IntoValue for TraceValueBoolean { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueBoolean { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueDuration { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TraceValueDuration { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueDuration { + fn default() -> Self { + Self { value: 0u64 } + } +} + +impl IntoValue for TraceValueDuration { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueDuration { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueEvent { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for TraceValueEvent { + fn pickle(&self, out: &mut Vec) { + self.event.pickle(out); + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.event = Pickle::unpickle(stream)?; + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueEvent { + fn default() -> Self { + Self { + event: Default::default(), + value: Default::default(), + } + } +} + +impl IntoValue for TraceValueEvent { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(4); + map.insert_unchecked(Property::Event, self.event.into_value()); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueEvent { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Event) => self.event.patch(pointer, value), + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueFloat { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TraceValueFloat { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueFloat { + fn default() -> Self { + Self { + value: Float::new(0.0f64), + } + } +} + +impl IntoValue for TraceValueFloat { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueFloat { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueInteger { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TraceValueInteger { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueInteger { + fn default() -> Self { + Self { value: 0i64 } + } +} + +impl IntoValue for TraceValueInteger { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueInteger { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueIpAddr { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Value, value)); + } + errors.len() == neb + } +} + +impl Pickle for TraceValueIpAddr { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueIpAddr { + fn default() -> Self { + Self { + value: Default::default(), + } + } +} + +impl IntoValue for TraceValueIpAddr { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueIpAddr { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueList { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + for value in value.values() { + value.validate(errors); + } + errors.len() == neb + } +} + +impl Pickle for TraceValueList { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueList { + fn default() -> Self { + Self { + value: Default::default(), + } + } +} + +impl IntoValue for TraceValueList { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueList { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueString { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + if value.is_empty() { + errors.push(ValidationError::required(Property::Value)); + } + errors.len() == neb + } +} + +impl Pickle for TraceValueString { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueString { + fn default() -> Self { + Self { + value: Default::default(), + } + } +} + +impl IntoValue for TraceValueString { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueString { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueUTCDateTime { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.value; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::Value, value)); + } + errors.len() == neb + } +} + +impl Pickle for TraceValueUTCDateTime { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueUTCDateTime { + fn default() -> Self { + Self { + value: Default::default(), + } + } +} + +impl IntoValue for TraceValueUTCDateTime { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueUTCDateTime { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TraceValueUnsignedInt { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TraceValueUnsignedInt { + fn pickle(&self, out: &mut Vec) { + self.value.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.value = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TraceValueUnsignedInt { + fn default() -> Self { + Self { value: 0u64 } + } +} + +impl IntoValue for TraceValueUnsignedInt { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Value, self.value.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TraceValueUnsignedInt { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Value) => self.value.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for Tracer { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::Tracer; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + Tracer::Log(inner) => inner.validate(errors), + Tracer::Stdout(inner) => inner.validate(errors), + Tracer::Journal(inner) => inner.validate(errors), + Tracer::OtelHttp(inner) => inner.validate(errors), + Tracer::OtelGrpc(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for Tracer { + fn default() -> Self { + Tracer::Log(Default::default()) + } +} + +impl Pickle for Tracer { + fn pickle(&self, out: &mut Vec) { + match self { + Tracer::Log(inner) => { + 0u16.pickle(out); + inner.pickle(out); + } + Tracer::Stdout(inner) => { + 1u16.pickle(out); + inner.pickle(out); + } + Tracer::Journal(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + Tracer::OtelHttp(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + Tracer::OtelGrpc(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Pickle::unpickle(stream).map(Tracer::Log), + 1 => Pickle::unpickle(stream).map(Tracer::Stdout), + 2 => Pickle::unpickle(stream).map(Tracer::Journal), + 3 => Pickle::unpickle(stream).map(Tracer::OtelHttp), + 4 => Pickle::unpickle(stream).map(Tracer::OtelGrpc), + _ => None, + } + } +} + +impl IntoValue for Tracer { + fn into_value(self) -> JmapValue<'static> { + match self { + Tracer::Log(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Log".into())); + obj + } + Tracer::Stdout(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Stdout".into())); + obj + } + Tracer::Journal(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Journal".into())); + obj + } + Tracer::OtelHttp(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("OtelHttp".into())); + obj + } + Tracer::OtelGrpc(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("OtelGrpc".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for Tracer { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TracerType::Log => *self = Tracer::Log(Default::default()), + TracerType::Stdout => *self = Tracer::Stdout(Default::default()), + TracerType::Journal => *self = Tracer::Journal(Default::default()), + TracerType::OtelHttp => *self = Tracer::OtelHttp(Default::default()), + TracerType::OtelGrpc => *self = Tracer::OtelGrpc(Default::default()), + } + } + match self { + Tracer::Log(inner) => inner.patch(pointer, value), + Tracer::Stdout(inner) => inner.patch(pointer, value), + Tracer::Journal(inner) => inner.patch(pointer, value), + Tracer::OtelHttp(inner) => inner.patch(pointer, value), + Tracer::OtelGrpc(inner) => inner.patch(pointer, value), + } + } +} + +impl Tracer { + pub fn object_type(&self) -> TracerType { + match self { + Tracer::Log(_) => TracerType::Log, + Tracer::Stdout(_) => TracerType::Stdout, + Tracer::Journal(_) => TracerType::Journal, + Tracer::OtelHttp(_) => TracerType::OtelHttp, + Tracer::OtelGrpc(_) => TracerType::OtelGrpc, + } + } +} + +impl TracerCommon { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TracerCommon { + fn pickle(&self, out: &mut Vec) { + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TracerCommon { + fn default() -> Self { + Self { + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for TracerCommon { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(7); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TracerCommon { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TracerLog { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.path; + if value.is_empty() { + errors.push(ValidationError::required(Property::Path)); + } + let value = &self.prefix; + if value.is_empty() { + errors.push(ValidationError::required(Property::Prefix)); + } + errors.len() == neb + } +} + +impl Pickle for TracerLog { + fn pickle(&self, out: &mut Vec) { + self.path.pickle(out); + self.prefix.pickle(out); + self.rotate.pickle(out); + self.ansi.pickle(out); + self.multiline.pickle(out); + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.path = Pickle::unpickle(stream)?; + this.prefix = Pickle::unpickle(stream)?; + this.rotate = Pickle::unpickle(stream)?; + this.ansi = Pickle::unpickle(stream)?; + this.multiline = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TracerLog { + fn default() -> Self { + Self { + path: Default::default(), + prefix: "stalwart".to_string(), + rotate: LogRotateFrequency::Daily, + ansi: false, + multiline: false, + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for TracerLog { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(12); + map.insert_unchecked(Property::Path, self.path.into_value()); + map.insert_unchecked(Property::Prefix, self.prefix.into_value()); + map.insert_unchecked(Property::Rotate, self.rotate.into_value()); + map.insert_unchecked(Property::Ansi, self.ansi.into_value()); + map.insert_unchecked(Property::Multiline, self.multiline.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TracerLog { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Path) => self + .path + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Prefix) => self + .prefix + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Rotate) => self.rotate.patch(pointer, value), + Some(Property::Ansi) => self.ansi.patch(pointer, value), + Some(Property::Multiline) => self.multiline.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TracerOtelGrpc { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + if let Some(value) = &self.endpoint { + if value.is_empty() { + errors.push(ValidationError::required(Property::Endpoint)); + } + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for TracerOtelGrpc { + fn pickle(&self, out: &mut Vec) { + self.endpoint.pickle(out); + self.enable_log_exporter.pickle(out); + self.enable_span_exporter.pickle(out); + self.throttle.pickle(out); + self.timeout.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.endpoint = Pickle::unpickle(stream)?; + this.enable_log_exporter = Pickle::unpickle(stream)?; + this.enable_span_exporter = Pickle::unpickle(stream)?; + this.throttle = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TracerOtelGrpc { + fn default() -> Self { + Self { + endpoint: Default::default(), + enable_log_exporter: true, + enable_span_exporter: true, + throttle: Duration::from_millis(1000), + timeout: Duration::from_millis(10000), + http_auth: Default::default(), + http_headers: Default::default(), + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for TracerOtelGrpc { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::Endpoint, self.endpoint.into_value()); + map.insert_unchecked( + Property::EnableLogExporter, + self.enable_log_exporter.into_value(), + ); + map.insert_unchecked( + Property::EnableSpanExporter, + self.enable_span_exporter.into_value(), + ); + map.insert_unchecked(Property::Throttle, self.throttle.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TracerOtelGrpc { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Endpoint) => self + .endpoint + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::EnableLogExporter) => self.enable_log_exporter.patch(pointer, value), + Some(Property::EnableSpanExporter) => self.enable_span_exporter.patch(pointer, value), + Some(Property::Throttle) => self.throttle.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TracerOtelHttp { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.endpoint; + if value.is_empty() { + errors.push(ValidationError::required(Property::Endpoint)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } +} + +impl Pickle for TracerOtelHttp { + fn pickle(&self, out: &mut Vec) { + self.endpoint.pickle(out); + self.enable_log_exporter.pickle(out); + self.enable_span_exporter.pickle(out); + self.throttle.pickle(out); + self.timeout.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.endpoint = Pickle::unpickle(stream)?; + this.enable_log_exporter = Pickle::unpickle(stream)?; + this.enable_span_exporter = Pickle::unpickle(stream)?; + this.throttle = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TracerOtelHttp { + fn default() -> Self { + Self { + endpoint: Default::default(), + enable_log_exporter: true, + enable_span_exporter: true, + throttle: Duration::from_millis(1000), + timeout: Duration::from_millis(10000), + http_auth: Default::default(), + http_headers: Default::default(), + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for TracerOtelHttp { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(14); + map.insert_unchecked(Property::Endpoint, self.endpoint.into_value()); + map.insert_unchecked( + Property::EnableLogExporter, + self.enable_log_exporter.into_value(), + ); + map.insert_unchecked( + Property::EnableSpanExporter, + self.enable_span_exporter.into_value(), + ); + map.insert_unchecked(Property::Throttle, self.throttle.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TracerOtelHttp { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Endpoint) => self + .endpoint + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::EnableLogExporter) => self.enable_log_exporter.patch(pointer, value), + Some(Property::EnableSpanExporter) => self.enable_span_exporter.patch(pointer, value), + Some(Property::Throttle) => self.throttle.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl TracerStdout { + fn validate(&self, _: &mut Vec) -> bool { + true + } +} + +impl Pickle for TracerStdout { + fn pickle(&self, out: &mut Vec) { + self.buffered.pickle(out); + self.ansi.pickle(out); + self.multiline.pickle(out); + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.buffered = Pickle::unpickle(stream)?; + this.ansi = Pickle::unpickle(stream)?; + this.multiline = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for TracerStdout { + fn default() -> Self { + Self { + buffered: true, + ansi: false, + multiline: false, + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for TracerStdout { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(10); + map.insert_unchecked(Property::Buffered, self.buffered.into_value()); + map.insert_unchecked(Property::Ansi, self.ansi.into_value()); + map.insert_unchecked(Property::Multiline, self.multiline.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for TracerStdout { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Buffered) => self.buffered.patch(pointer, value), + Some(Property::Ansi) => self.ansi.patch(pointer, value), + Some(Property::Multiline) => self.multiline.patch(pointer, value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for TracingStore { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::TracingStore; + + fn validate(&self, errors: &mut Vec) -> bool { + match self { + TracingStore::Disabled => true, + TracingStore::Default => true, + TracingStore::FoundationDb(inner) => inner.validate(errors), + TracingStore::PostgreSql(inner) => inner.validate(errors), + TracingStore::MySql(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Default for TracingStore { + fn default() -> Self { + TracingStore::Disabled + } +} + +impl Pickle for TracingStore { + fn pickle(&self, out: &mut Vec) { + match self { + TracingStore::Disabled => { + 0u16.pickle(out); + } + TracingStore::Default => { + 1u16.pickle(out); + } + TracingStore::FoundationDb(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + TracingStore::PostgreSql(inner) => { + 3u16.pickle(out); + inner.pickle(out); + } + TracingStore::MySql(inner) => { + 4u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(TracingStore::Disabled), + 1 => Some(TracingStore::Default), + 2 => Pickle::unpickle(stream).map(TracingStore::FoundationDb), + 3 => Pickle::unpickle(stream).map(TracingStore::PostgreSql), + 4 => Pickle::unpickle(stream).map(TracingStore::MySql), + _ => None, + } + } +} + +impl IntoValue for TracingStore { + fn into_value(self) -> JmapValue<'static> { + match self { + TracingStore::Disabled => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Disabled".into())); + JmapValue::Object(obj) + } + TracingStore::Default => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Default".into())); + JmapValue::Object(obj) + } + TracingStore::FoundationDb(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("FoundationDb".into())); + obj + } + TracingStore::PostgreSql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("PostgreSql".into())); + obj + } + TracingStore::MySql(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("MySql".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for TracingStore { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + TracingStoreType::Disabled => *self = TracingStore::Disabled, + TracingStoreType::Default => *self = TracingStore::Default, + TracingStoreType::FoundationDb => { + *self = TracingStore::FoundationDb(Default::default()) + } + TracingStoreType::PostgreSql => { + *self = TracingStore::PostgreSql(Default::default()) + } + TracingStoreType::MySql => *self = TracingStore::MySql(Default::default()), + } + } + match self { + TracingStore::Disabled => pointer.assert_eof(), + TracingStore::Default => pointer.assert_eof(), + TracingStore::FoundationDb(inner) => inner.patch(pointer, value), + TracingStore::PostgreSql(inner) => inner.patch(pointer, value), + TracingStore::MySql(inner) => inner.patch(pointer, value), + } + } +} + +impl TracingStore { + pub fn object_type(&self) -> TracingStoreType { + match self { + TracingStore::Disabled => TracingStoreType::Disabled, + TracingStore::Default => TracingStoreType::Default, + TracingStore::FoundationDb(_) => TracingStoreType::FoundationDb, + TracingStore::PostgreSql(_) => TracingStoreType::PostgreSql, + TracingStore::MySql(_) => TracingStoreType::MySql, + } + } +} + +impl UserAccount { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.name; + if value.is_empty() { + errors.push(ValidationError::required(Property::Name)); + } + let value = &self.domain_id; + if !value.is_valid() { + errors.push(ValidationError::required(Property::DomainId)); + } + let value = &self.credentials; + for value in value.values() { + value.validate(errors); + } + let value = &self.created_at; + if !value.is_valid() { + errors.push(ValidationError::invalid(Property::CreatedAt, value)); + } + let value = &self.member_group_ids; + for value in value.iter() { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberGroupIds)); + } + } + if let Some(value) = &self.member_tenant_id { + if !value.is_valid() { + errors.push(ValidationError::required(Property::MemberTenantId)); + } + } + let value = &self.roles; + value.validate(errors); + let value = &self.permissions; + value.validate(errors); + let value = &self.aliases; + for value in value.values() { + value.validate(errors); + } + if let Some(value) = &self.description { + if value.is_empty() { + errors.push(ValidationError::required(Property::Description)); + } + } + let value = &self.encryption_at_rest; + value.validate(errors); + errors.len() == neb + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + i.unique_global_composite(Property::Email, &self.name, &self.domain_id); + i.text(Property::Text, &self.name); + i.search(Property::Name, &self.name); + i.foreign_key(ObjectType::Domain, self.domain_id.into(), None); + i.search(Property::DomainId, &self.domain_id); + for id in self.member_group_ids.iter() { + i.foreign_key( + ObjectType::Account, + Some(*id), + Some(AccountType::Group.to_id()), + ); + } + for value in self.member_group_ids.iter() { + i.search(Property::MemberGroupIds, value); + } + i.foreign_key(ObjectType::Tenant, self.member_tenant_id, None); + if let Some(value) = &self.member_tenant_id { + i.search(Property::MemberTenantId, value); + } + self.roles.index(i); + for item in self.aliases.values() { + item.index(i); + } + if let Some(value) = &self.description { + i.text(Property::Text, value); + } + self.encryption_at_rest.index(i); + } +} + +impl Pickle for UserAccount { + fn pickle(&self, out: &mut Vec) { + self.name.pickle(out); + self.domain_id.pickle(out); + self.credentials.pickle(out); + self.created_at.pickle(out); + self.member_group_ids.pickle(out); + self.member_tenant_id.pickle(out); + self.roles.pickle(out); + self.permissions.pickle(out); + self.quotas.pickle(out); + self.aliases.pickle(out); + self.description.pickle(out); + self.locale.pickle(out); + self.time_zone.pickle(out); + self.encryption_at_rest.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.name = Pickle::unpickle(stream)?; + this.domain_id = Pickle::unpickle(stream)?; + this.credentials = Pickle::unpickle(stream)?; + this.created_at = Pickle::unpickle(stream)?; + this.member_group_ids = Pickle::unpickle(stream)?; + this.member_tenant_id = Pickle::unpickle(stream)?; + this.roles = Pickle::unpickle(stream)?; + this.permissions = Pickle::unpickle(stream)?; + this.quotas = Pickle::unpickle(stream)?; + this.aliases = Pickle::unpickle(stream)?; + this.description = Pickle::unpickle(stream)?; + this.locale = Pickle::unpickle(stream)?; + this.time_zone = Pickle::unpickle(stream)?; + this.encryption_at_rest = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for UserAccount { + fn default() -> Self { + Self { + name: Default::default(), + domain_id: Default::default(), + credentials: Default::default(), + created_at: Default::default(), + member_group_ids: Default::default(), + member_tenant_id: Default::default(), + roles: Default::default(), + permissions: Default::default(), + quotas: Default::default(), + aliases: Default::default(), + description: Default::default(), + locale: Locale::EnUS, + time_zone: Default::default(), + encryption_at_rest: Default::default(), + } + } +} + +impl IntoValue for UserAccount { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(16); + map.insert_unchecked(Property::Name, self.name.into_value()); + map.insert_unchecked(Property::DomainId, self.domain_id.into_value()); + map.insert_unchecked(Property::Credentials, self.credentials.into_value()); + map.insert_unchecked(Property::CreatedAt, self.created_at.into_value()); + map.insert_unchecked(Property::MemberGroupIds, self.member_group_ids.into_value()); + map.insert_unchecked(Property::MemberTenantId, self.member_tenant_id.into_value()); + map.insert_unchecked(Property::Roles, self.roles.into_value()); + map.insert_unchecked(Property::Permissions, self.permissions.into_value()); + map.insert_unchecked(Property::Quotas, self.quotas.into_value()); + map.insert_unchecked(Property::Aliases, self.aliases.into_value()); + map.insert_unchecked(Property::Description, self.description.into_value()); + map.insert_unchecked(Property::Locale, self.locale.into_value()); + map.insert_unchecked(Property::TimeZone, self.time_zone.into_value()); + map.insert_unchecked( + Property::EncryptionAtRest, + self.encryption_at_rest.into_value(), + ); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for UserAccount { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Name) => self.name.patch( + pointer.with_validators(&[StringValidator::EmailLocalPart]), + value, + ), + Some(Property::DomainId) => self.domain_id.patch(pointer, value), + Some(Property::EmailAddress) => pointer.assert_server_set(), + Some(Property::Credentials) => self.credentials.patch(pointer, value), + Some(Property::CreatedAt) => pointer.assert_server_set(), + Some(Property::MemberGroupIds) => self.member_group_ids.patch(pointer, value), + Some(Property::MemberTenantId) => self + .member_tenant_id + .patch(pointer.assert_can_set_tenant()?, value), + Some(Property::Roles) => self.roles.patch(pointer, value), + Some(Property::Permissions) => self.permissions.patch(pointer, value), + Some(Property::Quotas) => self.quotas.patch(pointer, value), + Some(Property::UsedDiskQuota) => pointer.assert_server_set(), + Some(Property::Aliases) => self.aliases.patch(pointer, value), + Some(Property::Description) => self.description.patch(pointer, value), + Some(Property::Locale) => self.locale.patch(pointer, value), + Some(Property::TimeZone) => self.time_zone.patch(pointer, value), + Some(Property::EncryptionAtRest) => self.encryption_at_rest.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl UserRoles { + fn validate(&self, errors: &mut Vec) -> bool { + match self { + UserRoles::User => true, + UserRoles::Admin => true, + UserRoles::Custom(inner) => inner.validate(errors), + } + } + + fn index<'x>(&'x self, i: &mut IndexBuilder<'x>) { + match self { + UserRoles::User => {} + UserRoles::Admin => {} + UserRoles::Custom(object) => { + object.index(i); + } + } + } +} + +impl Default for UserRoles { + fn default() -> Self { + UserRoles::User + } +} + +impl Pickle for UserRoles { + fn pickle(&self, out: &mut Vec) { + match self { + UserRoles::User => { + 0u16.pickle(out); + } + UserRoles::Admin => { + 1u16.pickle(out); + } + UserRoles::Custom(inner) => { + 2u16.pickle(out); + inner.pickle(out); + } + } + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + match u16::unpickle(stream)? { + 0 => Some(UserRoles::User), + 1 => Some(UserRoles::Admin), + 2 => Pickle::unpickle(stream).map(UserRoles::Custom), + _ => None, + } + } +} + +impl IntoValue for UserRoles { + fn into_value(self) -> JmapValue<'static> { + match self { + UserRoles::User => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("User".into())); + JmapValue::Object(obj) + } + UserRoles::Admin => { + let mut obj = jmap_tools::Map::new(); + obj.insert_unchecked(Property::Type, JmapValue::Str("Admin".into())); + JmapValue::Object(obj) + } + UserRoles::Custom(obj) => { + let mut obj = obj.into_value(); + obj.as_object_mut() + .unwrap() + .insert_unchecked(Property::Type, JmapValue::Str("Custom".into())); + obj + } + } + } +} + +impl RegistryJsonPatch for UserRoles { + fn patch<'x>( + &mut self, + pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + if !pointer.has_next() { + match object_type(&pointer, &value)? { + UserRolesType::User => *self = UserRoles::User, + UserRolesType::Admin => *self = UserRoles::Admin, + UserRolesType::Custom => *self = UserRoles::Custom(Default::default()), + } + } + match self { + UserRoles::User => pointer.assert_eof(), + UserRoles::Admin => pointer.assert_eof(), + UserRoles::Custom(inner) => inner.patch(pointer, value), + } + } +} + +impl UserRoles { + pub fn object_type(&self) -> UserRolesType { + match self { + UserRoles::User => UserRolesType::User, + UserRoles::Admin => UserRolesType::Admin, + UserRoles::Custom(_) => UserRolesType::Custom, + } + } +} + +impl ObjectImpl for WebDav { + const FLAGS: u64 = OBJ_SINGLETON; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::WebDav; + + fn validate(&self, _: &mut Vec) -> bool { + true + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for WebDav { + fn pickle(&self, out: &mut Vec) { + self.enable_assisted_discovery.pickle(out); + self.max_lock_timeout.pickle(out); + self.max_locks.pickle(out); + self.dead_property_max_size.pickle(out); + self.live_property_max_size.pickle(out); + self.request_max_size.pickle(out); + self.max_results.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.enable_assisted_discovery = Pickle::unpickle(stream)?; + this.max_lock_timeout = Pickle::unpickle(stream)?; + this.max_locks = Pickle::unpickle(stream)?; + this.dead_property_max_size = Pickle::unpickle(stream)?; + this.live_property_max_size = Pickle::unpickle(stream)?; + this.request_max_size = Pickle::unpickle(stream)?; + this.max_results = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for WebDav { + fn default() -> Self { + Self { + enable_assisted_discovery: true, + max_lock_timeout: Duration::from_millis(3600000), + max_locks: 10u64, + dead_property_max_size: Some(1024u64), + live_property_max_size: 250u64, + request_max_size: 26214400, + max_results: 2000u64, + } + } +} + +impl IntoValue for WebDav { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(9); + map.insert_unchecked( + Property::EnableAssistedDiscovery, + self.enable_assisted_discovery.into_value(), + ); + map.insert_unchecked(Property::MaxLockTimeout, self.max_lock_timeout.into_value()); + map.insert_unchecked(Property::MaxLocks, self.max_locks.into_value()); + map.insert_unchecked( + Property::DeadPropertyMaxSize, + self.dead_property_max_size.into_value(), + ); + map.insert_unchecked( + Property::LivePropertyMaxSize, + self.live_property_max_size.into_value(), + ); + map.insert_unchecked(Property::RequestMaxSize, self.request_max_size.into_value()); + map.insert_unchecked(Property::MaxResults, self.max_results.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for WebDav { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::EnableAssistedDiscovery) => { + self.enable_assisted_discovery.patch(pointer, value) + } + Some(Property::MaxLockTimeout) => self.max_lock_timeout.patch(pointer, value), + Some(Property::MaxLocks) => self.max_locks.patch(pointer, value), + Some(Property::DeadPropertyMaxSize) => { + self.dead_property_max_size.patch(pointer, value) + } + Some(Property::LivePropertyMaxSize) => { + self.live_property_max_size.patch(pointer, value) + } + Some(Property::RequestMaxSize) => self.request_max_size.patch(pointer, value), + Some(Property::MaxResults) => self.max_results.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ObjectImpl for WebHook { + const FLAGS: u64 = 0; + const VERSION: u8 = 0; + const OBJECT: ObjectType = ObjectType::WebHook; + + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.signature_key; + value.validate(errors); + let value = &self.url; + if value.is_empty() { + errors.push(ValidationError::required(Property::Url)); + } + let value = &self.http_auth; + value.validate(errors); + let value = &self.http_headers; + for value in value.values() { + if value.is_empty() { + errors.push(ValidationError::required(Property::HttpHeaders)); + } + } + errors.len() == neb + } + + fn index<'x>(&'x self, _: &mut IndexBuilder<'x>) {} +} + +impl Pickle for WebHook { + fn pickle(&self, out: &mut Vec) { + self.allow_invalid_certs.pickle(out); + self.signature_key.pickle(out); + self.throttle.pickle(out); + self.timeout.pickle(out); + self.discard_after.pickle(out); + self.url.pickle(out); + self.http_auth.pickle(out); + self.http_headers.pickle(out); + self.enable.pickle(out); + self.level.pickle(out); + self.lossy.pickle(out); + self.events.pickle(out); + self.events_policy.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.allow_invalid_certs = Pickle::unpickle(stream)?; + this.signature_key = Pickle::unpickle(stream)?; + this.throttle = Pickle::unpickle(stream)?; + this.timeout = Pickle::unpickle(stream)?; + this.discard_after = Pickle::unpickle(stream)?; + this.url = Pickle::unpickle(stream)?; + this.http_auth = Pickle::unpickle(stream)?; + this.http_headers = Pickle::unpickle(stream)?; + this.enable = Pickle::unpickle(stream)?; + this.level = Pickle::unpickle(stream)?; + this.lossy = Pickle::unpickle(stream)?; + this.events = Pickle::unpickle(stream)?; + this.events_policy = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for WebHook { + fn default() -> Self { + Self { + allow_invalid_certs: false, + signature_key: Default::default(), + throttle: Duration::from_millis(1000), + timeout: Duration::from_millis(30000), + discard_after: Duration::from_millis(300000), + url: Default::default(), + http_auth: Default::default(), + http_headers: Default::default(), + enable: true, + level: TracingLevel::Info, + lossy: false, + events: Default::default(), + events_policy: EventPolicy::Exclude, + } + } +} + +impl IntoValue for WebHook { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(15); + map.insert_unchecked( + Property::AllowInvalidCerts, + self.allow_invalid_certs.into_value(), + ); + map.insert_unchecked(Property::SignatureKey, self.signature_key.into_value()); + map.insert_unchecked(Property::Throttle, self.throttle.into_value()); + map.insert_unchecked(Property::Timeout, self.timeout.into_value()); + map.insert_unchecked(Property::DiscardAfter, self.discard_after.into_value()); + map.insert_unchecked(Property::Url, self.url.into_value()); + map.insert_unchecked(Property::HttpAuth, self.http_auth.into_value()); + map.insert_unchecked(Property::HttpHeaders, self.http_headers.into_value()); + map.insert_unchecked(Property::Enable, self.enable.into_value()); + map.insert_unchecked(Property::Level, self.level.into_value()); + map.insert_unchecked(Property::Lossy, self.lossy.into_value()); + map.insert_unchecked(Property::Events, self.events.into_value()); + map.insert_unchecked(Property::EventsPolicy, self.events_policy.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for WebHook { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::AllowInvalidCerts) => self.allow_invalid_certs.patch(pointer, value), + Some(Property::SignatureKey) => self.signature_key.patch(pointer, value), + Some(Property::Throttle) => self.throttle.patch(pointer, value), + Some(Property::Timeout) => self.timeout.patch(pointer, value), + Some(Property::DiscardAfter) => self.discard_after.patch(pointer, value), + Some(Property::Url) => self + .url + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::HttpAuth) => self.http_auth.patch(pointer, value), + Some(Property::HttpHeaders) => self + .http_headers + .patch(pointer.with_validators(&[StringValidator::Trim]), value), + Some(Property::Enable) => self.enable.patch(pointer, value), + Some(Property::Level) => self.level.patch(pointer, value), + Some(Property::Lossy) => self.lossy.patch(pointer, value), + Some(Property::Events) => self.events.patch(pointer, value), + Some(Property::EventsPolicy) => self.events_policy.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} + +impl ZenohCoordinator { + fn validate(&self, errors: &mut Vec) -> bool { + let neb = errors.len(); + let value = &self.config; + if value.is_empty() { + errors.push(ValidationError::required(Property::Config)); + } + errors.len() == neb + } +} + +impl Pickle for ZenohCoordinator { + fn pickle(&self, out: &mut Vec) { + self.config.pickle(out); + } + + fn unpickle(stream: &mut crate::pickle::PickledStream<'_>) -> Option { + let mut this = Self::default(); + this.config = Pickle::unpickle(stream)?; + Some(this) + } +} + +impl Default for ZenohCoordinator { + fn default() -> Self { + Self { + config: Default::default(), + } + } +} + +impl IntoValue for ZenohCoordinator { + fn into_value(self) -> JmapValue<'static> { + let mut map = jmap_tools::Map::with_capacity(3); + map.insert_unchecked(Property::Config, self.config.into_value()); + JmapValue::Object(map) + } +} + +impl RegistryJsonPropertyPatch for ZenohCoordinator { + fn patch_property<'x>( + &mut self, + mut pointer: JsonPointerPatch<'_>, + value: JmapValue<'x>, + ) -> PatchResult<'x> { + match pointer.next_property() { + Some(Property::Config) => self.config.patch(pointer, value), + Some(Property::Type) => Ok(MaybeUnpatched::Unpatched { + property: Property::Type, + value, + }), + _ => Err(PatchError::new(pointer, "Invalid property")), + } + } +} diff --git a/crates/registry/src/types/datetime.rs b/crates/registry/src/types/datetime.rs index 98fcef55..5df91134 100644 --- a/crates/registry/src/types/datetime.rs +++ b/crates/registry/src/types/datetime.rs @@ -75,34 +75,18 @@ impl FromStr for UTCDateTime { break; } } - b'T' => { - if pos == 2 { - pos += 1; - } else { - break; - } + b'T' if pos == 2 => { + pos += 1; } - b':' => { - if [3, 4, 6].contains(&pos) { - pos += 1; - } else { - break; - } + b':' if [3, 4, 6].contains(&pos) => { + pos += 1; } - b'+' => { - if pos == 5 { - pos += 1; - skip_digits = false; - } else { - break; - } + b'+' if pos == 5 => { + pos += 1; + skip_digits = false; } - b'.' => { - if pos == 5 { - skip_digits = true; - } else { - break; - } + b'.' if pos == 5 => { + skip_digits = true; } b'Z' | b'z' => (), _ => { diff --git a/crates/registry/src/types/list.rs b/crates/registry/src/types/list.rs index dc8b5bb1..8c5d6c7c 100644 --- a/crates/registry/src/types/list.rs +++ b/crates/registry/src/types/list.rs @@ -95,10 +95,10 @@ impl RegistryJsonPatch for List { value: JmapValue<'x>, ) -> PatchResult<'x> { match (pointer.next(), value) { - (Some(JsonPointerItem::Number(key)), Value::Null) => { - if self.0.remove(&(*key as u32)).is_some() { - return Ok(MaybeUnpatched::Patched); - } + (Some(JsonPointerItem::Number(key)), Value::Null) + if self.0.remove(&(*key as u32)).is_some() => + { + return Ok(MaybeUnpatched::Patched); } (Some(JsonPointerItem::Key(key)), Value::Null) => { if let Ok(key) = key.to_string().parse::() diff --git a/crates/services/Cargo.toml b/crates/services/Cargo.toml index ddf125eb..466e91f5 100644 --- a/crates/services/Cargo.toml +++ b/crates/services/Cargo.toml @@ -34,7 +34,7 @@ sha2 = "0.11" reqwest = { version = "0.13", default-features = false, features = ["rustls", "http2"]} base64 = "0.22" compact_str = "0.9.0" -dns-update = { path = "/Users/me/code/dns-update" } +dns-update = { version = "0.2.0" } [dev-dependencies] diff --git a/crates/services/src/broadcast/subscriber.rs b/crates/services/src/broadcast/subscriber.rs index 84baa34a..f5107b79 100644 --- a/crates/services/src/broadcast/subscriber.rs +++ b/crates/services/src/broadcast/subscriber.rs @@ -17,7 +17,7 @@ use trc::{ClusterEvent, ServerEvent}; pub fn spawn_broadcast_subscriber(inner: Arc, mut shutdown_rx: watch::Receiver) { let this_node_id = { let _core = inner.shared_core.load(); - if _core.storage.coordinator.is_none() { + if _core.storage.coordinator.is_none() || _core.storage.registry.is_recovery_mode() { return; } _core.network.node_id as u16 diff --git a/crates/services/src/lib.rs b/crates/services/src/lib.rs index 7d507662..00323709 100644 --- a/crates/services/src/lib.rs +++ b/crates/services/src/lib.rs @@ -28,32 +28,37 @@ pub trait SpawnServices { impl StartServices for BootManager { async fn start_services(&mut self) { + let server = self.inner.build_server(); // Unpack webadmin self.inner .data .applications - .unpack_all(&self.inner.build_server(), false) + .unpack_all(&server, false) .await; - self.ipc_rxs.spawn_services(self.inner.clone()); + if !server.registry().is_recovery_mode() { + self.ipc_rxs.spawn_services(self.inner.clone()); + } } } impl SpawnServices for IpcReceivers { fn spawn_services(&mut self, inner: Arc) { - // Spawn push manager - spawn_push_router(inner.clone(), self.push_rx.take().unwrap()); + if !inner.shared_core.load().storage.registry.is_recovery_mode() { + // Spawn push manager + spawn_push_router(inner.clone(), self.push_rx.take().unwrap()); - // Spawn broadcast publisher - if let Some(event_rx) = self.broadcast_rx.take() { // Spawn broadcast publisher - spawn_broadcast_publisher(inner.clone(), event_rx); + if let Some(event_rx) = self.broadcast_rx.take() { + // Spawn broadcast publisher + spawn_broadcast_publisher(inner.clone(), event_rx); + } + + // Spawn task manager + spawn_task_manager(inner.clone()); + + // Spawn task scheduler + spawn_task_scheduler(inner); } - - // Spawn task manager - spawn_task_manager(inner.clone()); - - // Spawn task scheduler - spawn_task_scheduler(inner); } } diff --git a/crates/services/src/task_manager/imip.rs b/crates/services/src/task_manager/imip.rs index 05eb2387..a7bb3301 100644 --- a/crates/services/src/task_manager/imip.rs +++ b/crates/services/src/task_manager/imip.rs @@ -530,8 +530,7 @@ pub async fn build_itip_template( CalendarTemplateVariable::Key, locale.calendar_imip_footer_2.to_string(), )], - ] - .into_iter(), + ], ); Details { diff --git a/crates/services/src/task_manager/manager.rs b/crates/services/src/task_manager/manager.rs index 204d6998..8686ab8f 100644 --- a/crates/services/src/task_manager/manager.rs +++ b/crates/services/src/task_manager/manager.rs @@ -491,7 +491,7 @@ async fn update_tasks( ) { let mut batch = BatchBuilder::new(); - for (task, result) in tasks.iter_mut().zip(results.into_iter()) { + for (task, result) in tasks.iter_mut().zip(results) { let id = task.info.id; batch.clear(ValueClass::TaskQueue(TaskQueueClass::Due { id, diff --git a/crates/smtp/src/inbound/auth.rs b/crates/smtp/src/inbound/auth.rs index 0ba7be49..bbb20c44 100644 --- a/crates/smtp/src/inbound/auth.rs +++ b/crates/smtp/src/inbound/auth.rs @@ -59,11 +59,9 @@ impl Session { Credentials::Basic { username, secret, .. }, - ) => { - if username.is_empty() && secret.is_empty() { - self.write(b"334 VXNlcm5hbWU6\r\n").await?; - return Ok(true); - } + ) if username.is_empty() && secret.is_empty() => { + self.write(b"334 VXNlcm5hbWU6\r\n").await?; + return Ok(true); } _ => (), } @@ -71,7 +69,7 @@ impl Session { match (token.mechanism, &mut token.credentials) { (AUTH_PLAIN, _) => { if let Some(credentials) = Credentials::decode_sasl_challenge_plain(&response) { - return self.authenticate(credentials).await; + return Box::pin(self.authenticate(credentials)).await; } } ( @@ -86,20 +84,20 @@ impl Session { Ok(true) } else { *secret = response.into_string(); - self.authenticate(std::mem::replace( + Box::pin(self.authenticate(std::mem::replace( &mut token.credentials, Credentials::Basic { username: String::new(), secret: String::new(), mfa_token: None, }, - )) + ))) .await }; } (AUTH_OAUTHBEARER | AUTH_XOAUTH2, _) => { if let Some(credentials) = Credentials::decode_sasl_challenge_oauth(&response) { - return self.authenticate(credentials).await; + return Box::pin(self.authenticate(credentials)).await; } } _ => (), diff --git a/crates/smtp/src/inbound/mail.rs b/crates/smtp/src/inbound/mail.rs index 7dccede0..301d5cc5 100644 --- a/crates/smtp/src/inbound/mail.rs +++ b/crates/smtp/src/inbound/mail.rs @@ -171,12 +171,10 @@ impl Session { ) .await { - ScriptResult::Accept { modifications } => { - if !modifications.is_empty() { - for modification in modifications { - if let ScriptModification::SetEnvelope { name, value } = modification { - self.data.apply_envelope_modification(name, value); - } + ScriptResult::Accept { modifications } if !modifications.is_empty() => { + for modification in modifications { + if let ScriptModification::SetEnvelope { name, value } = modification { + self.data.apply_envelope_modification(name, value); } } } diff --git a/crates/smtp/src/inbound/rcpt.rs b/crates/smtp/src/inbound/rcpt.rs index dbd7cf96..850ed5ed 100644 --- a/crates/smtp/src/inbound/rcpt.rs +++ b/crates/smtp/src/inbound/rcpt.rs @@ -124,14 +124,10 @@ impl Session { ) .await { - ScriptResult::Accept { modifications } => { - if !modifications.is_empty() { - for modification in modifications { - if let ScriptModification::SetEnvelope { name, value } = - modification - { - self.data.apply_envelope_modification(name, value); - } + ScriptResult::Accept { modifications } if !modifications.is_empty() => { + for modification in modifications { + if let ScriptModification::SetEnvelope { name, value } = modification { + self.data.apply_envelope_modification(name, value); } } } diff --git a/crates/smtp/src/inbound/spawn.rs b/crates/smtp/src/inbound/spawn.rs index b0e9df59..4b80df23 100644 --- a/crates/smtp/src/inbound/spawn.rs +++ b/crates/smtp/src/inbound/spawn.rs @@ -153,7 +153,7 @@ impl Session { if bytes_read > 0 { if Instant::now() < self.data.valid_until && bytes_read <= self.data.bytes_left { self.data.bytes_left -= bytes_read; - match self.ingest(&buf[..bytes_read]).await { + match Box::pin(self.ingest(&buf[..bytes_read])).await { Ok(true) => (), Ok(false) => { return true; diff --git a/crates/smtp/src/lib.rs b/crates/smtp/src/lib.rs index 957d4dce..bf1cb5b0 100644 --- a/crates/smtp/src/lib.rs +++ b/crates/smtp/src/lib.rs @@ -7,7 +7,7 @@ #![warn(clippy::large_futures)] use common::{ - BuildServer, Inner, + Inner, manager::boot::{BootManager, IpcReceivers}, }; use queue::manager::SpawnQueue; @@ -37,7 +37,8 @@ impl StartQueueManager for BootManager { impl SpawnQueueManager for IpcReceivers { fn spawn_queue_manager(&mut self, inner: Arc) { - if inner.build_server().core.network.roles.outbound_mta { + let core = inner.shared_core.load(); + if !core.storage.registry.is_recovery_mode() && core.network.roles.outbound_mta { // Spawn queue manager self.queue_rx.take().unwrap().spawn(inner.clone()); diff --git a/crates/smtp/src/queue/manager.rs b/crates/smtp/src/queue/manager.rs index 91885292..eb733410 100644 --- a/crates/smtp/src/queue/manager.rs +++ b/crates/smtp/src/queue/manager.rs @@ -168,6 +168,7 @@ impl Queue { match status { QueueEventStatus::Completed => { + self.core.ipc.task_tx.notify_one(); self.locked.remove(&(queue_id, queue_name)); !self.locked.is_empty() || !queue_stats.has_capacity() } diff --git a/crates/spam-filter/src/analysis/mime.rs b/crates/spam-filter/src/analysis/mime.rs index 4046f21a..d458ed18 100644 --- a/crates/spam-filter/src/analysis/mime.rs +++ b/crates/spam-filter/src/analysis/mime.rs @@ -342,16 +342,15 @@ impl SpamFilterAnalyzeMime for Server { ctx.result.add_tag("SIGNED_PGP"); is_attachment = false; } - "octet-stream" => { + "octet-stream" if !is_encrypted && !has_content_id && cd.is_none_or(|cd| { !cd.c_type.eq_ignore_ascii_case("attachment") && !cd.has_attribute("filename") - }) - { - ctx.result.add_tag("CTYPE_MISSING_DISPOSITION"); - } + }) => + { + ctx.result.add_tag("CTYPE_MISSING_DISPOSITION"); } _ => (), }, diff --git a/crates/spam-filter/src/analysis/replyto.rs b/crates/spam-filter/src/analysis/replyto.rs index 360a0b0c..dd6697a2 100644 --- a/crates/spam-filter/src/analysis/replyto.rs +++ b/crates/spam-filter/src/analysis/replyto.rs @@ -37,12 +37,10 @@ impl SpamFilterAnalyzeReplyTo for Server { is_from_list = true; } - HeaderName::Other(name) => { - if !is_from_list { - is_from_list = name.eq_ignore_ascii_case("X-To-Get-Off-This-List") - || name.eq_ignore_ascii_case("X-List") - || name.eq_ignore_ascii_case("Auto-Submitted"); - } + HeaderName::Other(name) if !is_from_list => { + is_from_list = name.eq_ignore_ascii_case("X-To-Get-Off-This-List") + || name.eq_ignore_ascii_case("X-List") + || name.eq_ignore_ascii_case("Auto-Submitted"); } _ => {} } diff --git a/crates/spam-filter/src/modules/classifier.rs b/crates/spam-filter/src/modules/classifier.rs index d54e5955..7002b7df 100644 --- a/crates/spam-filter/src/modules/classifier.rs +++ b/crates/spam-filter/src/modules/classifier.rs @@ -881,7 +881,7 @@ async fn delete_samples( ) -> trc::Result<()> { let object_id = ObjectType::SpamTrainingSample.to_id(); let mut batch = BatchBuilder::new(); - for sample in samples.into_iter().chain(duplicate_samples.into_iter()) { + for sample in samples.into_iter().chain(duplicate_samples) { if let Some(until) = sample.remove { batch .with_account_id(sample.sample.account_id) diff --git a/crates/spam-filter/src/modules/html.rs b/crates/spam-filter/src/modules/html.rs index 93808c85..3e9431c6 100644 --- a/crates/spam-filter/src/modules/html.rs +++ b/crates/spam-filter/src/modules/html.rs @@ -247,16 +247,14 @@ pub fn html_to_tokens(input: &str) -> Vec { } } } - b' ' | b'\t' | b'\r' | b'\n' => { - if shift != 0 { - if tag == 0 { - tag = key; - } else { - attributes.push((key, None)); - } - key = 0; - shift = 0; + b' ' | b'\t' | b'\r' | b'\n' if shift != 0 => { + if tag == 0 { + tag = key; + } else { + attributes.push((key, None)); } + key = 0; + shift = 0; } _ => {} } diff --git a/crates/store/src/backend/composite/sharded_blob.rs b/crates/store/src/backend/composite/sharded_blob.rs index a54b2c68..ddfb46c3 100644 --- a/crates/store/src/backend/composite/sharded_blob.rs +++ b/crates/store/src/backend/composite/sharded_blob.rs @@ -89,6 +89,7 @@ impl ShardedBlob { Store::MySQL(store) => store.get_blob(key, read_range).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.get_blob(key, read_range).await, + Store::Ephemeral(store) => store.get_blob(key, read_range).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -125,6 +126,7 @@ impl ShardedBlob { Store::MySQL(store) => store.put_blob(key, data).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.put_blob(key, data).await, + Store::Ephemeral(store) => store.put_blob(key, data).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -161,6 +163,7 @@ impl ShardedBlob { Store::MySQL(store) => store.delete_blob(key).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.delete_blob(key).await, + Store::Ephemeral(store) => store.delete_blob(key).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL diff --git a/crates/store/src/backend/ephemeral/blob.rs b/crates/store/src/backend/ephemeral/blob.rs new file mode 100644 index 00000000..3ea62afb --- /dev/null +++ b/crates/store/src/backend/ephemeral/blob.rs @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use super::EphemeralStore; +use crate::SUBSPACE_BLOBS; +use std::ops::Range; + +impl EphemeralStore { + pub(crate) async fn get_blob( + &self, + key: &[u8], + range: Range, + ) -> trc::Result>> { + let state = self.state.read(); + Ok(state + .subspaces + .get(&SUBSPACE_BLOBS) + .and_then(|m| m.get(key)) + .map(|bytes| { + if range.start == 0 && range.end == usize::MAX { + bytes.clone() + } else { + bytes + .get(range.start..std::cmp::min(bytes.len(), range.end)) + .unwrap_or_default() + .to_vec() + } + })) + } + + pub(crate) async fn put_blob(&self, key: &[u8], data: &[u8]) -> trc::Result<()> { + let mut state = self.state.write(); + state + .subspaces + .entry(SUBSPACE_BLOBS) + .or_default() + .insert(key.to_vec(), data.to_vec()); + Ok(()) + } + + pub(crate) async fn delete_blob(&self, key: &[u8]) -> trc::Result { + let mut state = self.state.write(); + if let Some(map) = state.subspaces.get_mut(&SUBSPACE_BLOBS) { + map.remove(key); + } + Ok(true) + } +} diff --git a/crates/store/src/backend/ephemeral/main.rs b/crates/store/src/backend/ephemeral/main.rs new file mode 100644 index 00000000..665a5cd0 --- /dev/null +++ b/crates/store/src/backend/ephemeral/main.rs @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use super::{EphemeralState, EphemeralStore}; +use crate::Store; +use ahash::AHashMap; +use parking_lot::RwLock; +use std::sync::Arc; + +impl EphemeralStore { + pub fn open() -> Store { + Store::Ephemeral(Arc::new(EphemeralStore { + state: RwLock::new(EphemeralState { + subspaces: AHashMap::new(), + }), + })) + } +} diff --git a/crates/store/src/backend/ephemeral/mod.rs b/crates/store/src/backend/ephemeral/mod.rs new file mode 100644 index 00000000..f5945bef --- /dev/null +++ b/crates/store/src/backend/ephemeral/mod.rs @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +pub mod blob; +pub mod main; +pub mod read; +pub mod write; + +use ahash::AHashMap; +use parking_lot::RwLock; +use std::collections::BTreeMap; + +pub struct EphemeralStore { + pub(crate) state: RwLock, +} + +pub(crate) struct EphemeralState { + pub(crate) subspaces: AHashMap, Vec>>, +} diff --git a/crates/store/src/backend/ephemeral/read.rs b/crates/store/src/backend/ephemeral/read.rs new file mode 100644 index 00000000..9fbe30b0 --- /dev/null +++ b/crates/store/src/backend/ephemeral/read.rs @@ -0,0 +1,90 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use super::EphemeralStore; +use crate::{Deserialize, IterateParams, Key, ValueKey, write::ValueClass}; + +impl EphemeralStore { + pub(crate) async fn get_value(&self, key: impl Key) -> trc::Result> + where + U: Deserialize + 'static, + { + let subspace = key.subspace(); + let key_bytes = key.serialize(0); + let state = self.state.read(); + match state + .subspaces + .get(&subspace) + .and_then(|m| m.get(&key_bytes)) + { + Some(value) => U::deserialize_with_key(&key_bytes, value).map(Some), + None => Ok(None), + } + } + + pub(crate) async fn key_exists(&self, key: impl Key) -> trc::Result { + let subspace = key.subspace(); + let key_bytes = key.serialize(0); + let state = self.state.read(); + Ok(state + .subspaces + .get(&subspace) + .is_some_and(|m| m.contains_key(&key_bytes))) + } + + pub(crate) async fn iterate( + &self, + params: IterateParams, + mut cb: impl for<'x> FnMut(&'x [u8], &'x [u8]) -> trc::Result + Sync + Send, + ) -> trc::Result<()> { + let subspace = params.begin.subspace(); + let begin = params.begin.serialize(0); + let end = params.end.serialize(0); + let state = self.state.read(); + let Some(map) = state.subspaces.get(&subspace) else { + return Ok(()); + }; + + if params.ascending { + for (k, v) in map.range(begin..=end) { + if !cb(k.as_slice(), v.as_slice())? || params.first { + break; + } + } + } else { + for (k, v) in map.range(begin..=end).rev() { + if !cb(k.as_slice(), v.as_slice())? || params.first { + break; + } + } + } + Ok(()) + } + + pub(crate) async fn get_counter( + &self, + key: impl Into> + Sync + Send, + ) -> trc::Result { + let key = key.into(); + let subspace = key.subspace(); + let key_bytes = key.serialize(0); + let state = self.state.read(); + match state + .subspaces + .get(&subspace) + .and_then(|m| m.get(&key_bytes)) + { + Some(bytes) => Ok(i64::from_le_bytes(bytes[..].try_into().map_err(|_| { + trc::Error::corrupted_key( + &key_bytes, + Some(bytes.as_slice()), + trc::location!(), + ) + })?)), + None => Ok(0), + } + } +} diff --git a/crates/store/src/backend/ephemeral/write.rs b/crates/store/src/backend/ephemeral/write.rs new file mode 100644 index 00000000..ae4e4260 --- /dev/null +++ b/crates/store/src/backend/ephemeral/write.rs @@ -0,0 +1,197 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +use super::EphemeralStore; +use crate::{ + IndexKey, Key, LogKey, SUBSPACE_COUNTER, SUBSPACE_IN_MEMORY_COUNTER, SUBSPACE_INDEXES, + SUBSPACE_LOGS, SUBSPACE_QUOTA, + backend::deserialize_i64_le, + write::{AssignedIds, Batch, MergeResult, Operation, ValueClass, ValueOp}, +}; + +impl EphemeralStore { + pub(crate) async fn write(&self, batch: Batch<'_>) -> trc::Result { + let mut account_id = u32::MAX; + let mut collection = u8::MAX; + let mut document_id = u32::MAX; + let mut change_id = 0u64; + let mut result = AssignedIds::default(); + let has_changes = !batch.changes.is_empty(); + + let mut state = self.state.write(); + + if has_changes { + let map = state.subspaces.entry(SUBSPACE_COUNTER).or_default(); + for &account_id in batch.changes.keys() { + let key = ValueClass::ChangeId.serialize(account_id, 0, 0, 0); + let next = match map.get(&key) { + Some(bytes) => deserialize_i64_le(&key, bytes)? + 1, + None => 1, + }; + map.insert(key, next.to_le_bytes().to_vec()); + result.push_change_id(account_id, next as u64); + } + } + + for op in batch.ops.iter_mut() { + match op { + Operation::AccountId { + account_id: account_id_, + } => { + account_id = *account_id_; + if has_changes { + change_id = result.set_current_change_id(account_id)?; + } + } + Operation::Collection { + collection: collection_, + } => { + collection = u8::from(*collection_); + } + Operation::DocumentId { + document_id: document_id_, + } => { + document_id = *document_id_; + } + Operation::Value { class, op } => { + let subspace = class.subspace(collection); + let key = class.serialize(account_id, collection, document_id, 0); + let map = state.subspaces.entry(subspace).or_default(); + + match op { + ValueOp::Set(value) => { + map.insert(key, std::mem::take(value)); + } + ValueOp::SetFnc(set_op) => { + let value = (set_op.fnc)(&set_op.params, &result)?; + map.insert(key, value); + } + ValueOp::MergeFnc(merge_op) => { + let merge_result = (merge_op.fnc)( + &merge_op.params, + &result, + map.get(&key).map(|v| v.as_slice()), + )?; + + match merge_result { + MergeResult::Update(value) => { + map.insert(key, value); + } + MergeResult::Delete => { + map.remove(&key); + } + MergeResult::Skip => (), + } + } + ValueOp::AtomicAdd(by) => { + let current = match map.get(&key) { + Some(bytes) => deserialize_i64_le(&key, bytes)?, + None => 0, + }; + let next = current + *by; + map.insert(key, next.to_le_bytes().to_vec()); + } + ValueOp::AddAndGet(by) => { + let current = match map.get(&key) { + Some(bytes) => deserialize_i64_le(&key, bytes)?, + None => 0, + }; + let next = current + *by; + map.insert(key, next.to_le_bytes().to_vec()); + result.push_counter_id(next); + } + ValueOp::Clear => { + map.remove(&key); + } + } + } + Operation::Index { field, key, set } => { + let index_key = IndexKey { + account_id, + collection, + document_id, + field: *field, + key: key.as_slice(), + } + .serialize(0); + let map = state.subspaces.entry(SUBSPACE_INDEXES).or_default(); + if *set { + map.insert(index_key, Vec::new()); + } else { + map.remove(&index_key); + } + } + Operation::Log { collection, set } => { + let log_key = LogKey { + account_id, + collection: u8::from(*collection), + change_id, + } + .serialize(0); + let map = state.subspaces.entry(SUBSPACE_LOGS).or_default(); + map.insert(log_key, std::mem::take(set)); + } + Operation::AssertValue { + class, + assert_value, + } => { + let subspace = class.subspace(collection); + let key = class.serialize(account_id, collection, document_id, 0); + let matches = state + .subspaces + .get(&subspace) + .and_then(|m| m.get(&key)) + .map(|v| assert_value.matches(v.as_slice())) + .unwrap_or_else(|| assert_value.is_none()); + + if !matches { + return Err(trc::StoreEvent::AssertValueFailed.into()); + } + } + } + } + + Ok(result) + } + + pub(crate) async fn delete_range(&self, from: impl Key, to: impl Key) -> trc::Result<()> { + let subspace = from.subspace(); + let from_key = from.serialize(0); + let to_key = to.serialize(0); + let mut state = self.state.write(); + if let Some(map) = state.subspaces.get_mut(&subspace) { + let keys: Vec> = map.range(from_key..to_key).map(|(k, _)| k.clone()).collect(); + for k in keys { + map.remove(&k); + } + } + Ok(()) + } + + pub(crate) async fn purge_store(&self) -> trc::Result<()> { + let mut state = self.state.write(); + for subspace in [SUBSPACE_QUOTA, SUBSPACE_COUNTER, SUBSPACE_IN_MEMORY_COUNTER] { + if let Some(map) = state.subspaces.get_mut(&subspace) { + let keys: Vec> = map + .iter() + .filter_map(|(k, v)| { + if v.len() == std::mem::size_of::() + && i64::from_le_bytes(v[..].try_into().unwrap()) == 0 + { + Some(k.clone()) + } else { + None + } + }) + .collect(); + for k in keys { + map.remove(&k); + } + } + } + Ok(()) + } +} diff --git a/crates/store/src/backend/mod.rs b/crates/store/src/backend/mod.rs index 7f691f81..33ff36ae 100644 --- a/crates/store/src/backend/mod.rs +++ b/crates/store/src/backend/mod.rs @@ -7,6 +7,7 @@ #[cfg(feature = "azure")] pub mod azure; pub mod elastic; +pub mod ephemeral; #[cfg(feature = "foundation")] pub mod foundationdb; pub mod fs; diff --git a/crates/store/src/backend/redis/mod.rs b/crates/store/src/backend/redis/mod.rs index f32d1dd7..108e538e 100644 --- a/crates/store/src/backend/redis/mod.rs +++ b/crates/store/src/backend/redis/mod.rs @@ -60,7 +60,7 @@ impl RedisStore { } pub async fn open_cluster(config: structs::RedisClusterStore) -> Result { - let mut builder = ClusterClientBuilder::new(config.urls.into_iter()); + let mut builder = ClusterClientBuilder::new(config.urls); if let Some(value) = config.auth_username { builder = builder.username(value); } diff --git a/crates/store/src/build/registry.rs b/crates/store/src/build/registry.rs index 9581c062..f725399c 100644 --- a/crates/store/src/build/registry.rs +++ b/crates/store/src/build/registry.rs @@ -6,6 +6,8 @@ use crate::{ IterateParams, RegistryStore, RegistryStoreInner, Store, U16_LEN, U32_LEN, U64_LEN, ValueKey, + backend::ephemeral::EphemeralStore, + registry::local::RegistryInit, write::{ BatchBuilder, ValueClass, assert::AssertValue, @@ -29,11 +31,22 @@ impl RegistryStore { let mut inner = RegistryStoreInner::new(local); // Build store - inner.store = Store::build(inner.read_data_store().await?).await?; + inner.store = match inner.read_data_store().await { + RegistryInit::Ok(data_store) => Store::build(data_store).await?, + RegistryInit::Err(err) => return Err(err), + RegistryInit::Bootstrap => { + inner.env_recovery_mode = true; + EphemeralStore::open() + } + }; Self::from_inner(inner).await } + pub fn from_inner_bootstrapped(inner: RegistryStoreInner) -> Self { + Self(inner.into()) + } + pub async fn from_inner(mut inner: RegistryStoreInner) -> Result { // Create tables (SQL only) inner @@ -239,6 +252,11 @@ impl RegistryStore { self.0.env_recovery_mode } + #[inline(always)] + pub fn is_bootstrap_mode(&self) -> bool { + self.0.store.is_ephemeral() + } + #[inline(always)] pub fn path(&self) -> &PathBuf { &self.0.local_path @@ -249,6 +267,12 @@ impl RegistryStore { &self.0.store } + pub fn initialize_inner(&self, store: Store) -> RegistryStoreInner { + let mut inner = self.0.as_ref().clone(); + inner.store = store; + inner + } + #[cfg(feature = "test_mode")] pub async fn new( path: &str, diff --git a/crates/store/src/dispatch/blob.rs b/crates/store/src/dispatch/blob.rs index 8a2141f1..1845c1c0 100644 --- a/crates/store/src/dispatch/blob.rs +++ b/crates/store/src/dispatch/blob.rs @@ -28,6 +28,7 @@ impl BlobStore { Store::MySQL(store) => store.get_blob(key, 0..usize::MAX).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.get_blob(key, 0..usize::MAX).await, + Store::Ephemeral(store) => store.get_blob(key, 0..usize::MAX).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -149,6 +150,7 @@ impl BlobStore { Store::MySQL(store) => store.put_blob(key, &data).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.put_blob(key, &data).await, + Store::Ephemeral(store) => store.put_blob(key, &data).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -195,6 +197,7 @@ impl BlobStore { Store::MySQL(store) => store.delete_blob(key).await, #[cfg(feature = "rocks")] Store::RocksDb(store) => store.delete_blob(key).await, + Store::Ephemeral(store) => store.delete_blob(key).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL diff --git a/crates/store/src/dispatch/mod.rs b/crates/store/src/dispatch/mod.rs index 17228ca2..98b25dd8 100644 --- a/crates/store/src/dispatch/mod.rs +++ b/crates/store/src/dispatch/mod.rs @@ -25,6 +25,7 @@ impl Store { Self::MySQL(_) => "mysql", #[cfg(feature = "rocks")] Self::RocksDb(_) => "rocksdb", + Self::Ephemeral(_) => "ephemeral", // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL diff --git a/crates/store/src/dispatch/search.rs b/crates/store/src/dispatch/search.rs index 013160aa..7f4a701b 100644 --- a/crates/store/src/dispatch/search.rs +++ b/crates/store/src/dispatch/search.rs @@ -165,7 +165,7 @@ impl SearchStore { } } // Add any remaining results not yet in the index - ordered_results.extend(results.into_iter()); + ordered_results.extend(results); if local.is_empty() { return Ok(ordered_results); diff --git a/crates/store/src/dispatch/store.rs b/crates/store/src/dispatch/store.rs index 4e598555..a5d898e2 100644 --- a/crates/store/src/dispatch/store.rs +++ b/crates/store/src/dispatch/store.rs @@ -34,6 +34,7 @@ impl Store { Self::MySQL(store) => store.get_value(key).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.get_value(key).await, + Self::Ephemeral(store) => store.get_value(key).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -57,6 +58,7 @@ impl Store { Self::MySQL(store) => store.key_exists(key).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.key_exists(key).await, + Self::Ephemeral(store) => store.key_exists(key).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -85,6 +87,7 @@ impl Store { Self::MySQL(store) => store.iterate(params, cb).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.iterate(params, cb).await, + Self::Ephemeral(store) => store.iterate(params, cb).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -118,6 +121,7 @@ impl Store { Self::MySQL(store) => store.get_counter(key).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.get_counter(key).await, + Self::Ephemeral(store) => store.get_counter(key).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -171,6 +175,7 @@ impl Store { Self::MySQL(store) => store.write(batch).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.write(batch).await, + Self::Ephemeral(store) => store.write(batch).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -221,6 +226,7 @@ impl Store { Self::MySQL(store) => store.purge_store().await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.purge_store().await, + Self::Ephemeral(store) => store.purge_store().await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -244,6 +250,7 @@ impl Store { Self::MySQL(store) => store.delete_range(from, to).await, #[cfg(feature = "rocks")] Self::RocksDb(store) => store.delete_range(from, to).await, + Self::Ephemeral(store) => store.delete_range(from, to).await, // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL diff --git a/crates/store/src/lib.rs b/crates/store/src/lib.rs index 6428b672..e98ac962 100644 --- a/crates/store/src/lib.rs +++ b/crates/store/src/lib.rs @@ -24,7 +24,7 @@ pub use xxhash_rust; use crate::backend::{elastic::ElasticSearchStore, meili::MeiliSearchStore}; use ahash::AHashMap; -use backend::{fs::FsStore, http::HttpStore, memory::StaticMemoryStore}; +use backend::{ephemeral::EphemeralStore, fs::FsStore, http::HttpStore, memory::StaticMemoryStore}; use std::{borrow::Cow, path::PathBuf, sync::Arc}; use write::ValueClass; @@ -153,6 +153,7 @@ pub enum Store { MySQL(Arc), #[cfg(feature = "rocks")] RocksDb(Arc), + Ephemeral(Arc), // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -204,6 +205,7 @@ pub enum InMemoryStore { #[derive(Clone)] pub struct RegistryStore(pub(crate) Arc); +#[derive(Clone)] pub struct RegistryStoreInner { pub(crate) local_path: PathBuf, pub(crate) store: Store, @@ -251,6 +253,12 @@ impl From for Store { } } +impl From for Store { + fn from(store: EphemeralStore) -> Self { + Self::Ephemeral(Arc::new(store)) + } +} + impl From for SearchStore { fn from(store: ElasticSearchStore) -> Self { Self::ElasticSearch(Arc::new(store)) @@ -680,6 +688,11 @@ impl Store { } } + #[inline(always)] + pub fn is_ephemeral(&self) -> bool { + matches!(self, Self::Ephemeral(_)) + } + // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC // SPDX-License-Identifier: LicenseRef-SEL @@ -716,6 +729,7 @@ impl std::fmt::Debug for Store { Self::MySQL(_) => f.debug_tuple("MySQL").finish(), #[cfg(feature = "rocks")] Self::RocksDb(_) => f.debug_tuple("RocksDb").finish(), + Self::Ephemeral(_) => f.debug_tuple("Ephemeral").finish(), // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs LLC diff --git a/crates/store/src/registry/get.rs b/crates/store/src/registry/get.rs index a5d6ed10..45c2874b 100644 --- a/crates/store/src/registry/get.rs +++ b/crates/store/src/registry/get.rs @@ -6,7 +6,7 @@ use crate::{ IterateParams, RegistryStore, SUBSPACE_REGISTRY, U16_LEN, U64_LEN, ValueKey, - registry::RegistryObject, + registry::{RegistryObject, local::RegistryInit}, write::{ AnyClass, RegistryClass, ValueClass, key::{DeserializeBigEndian, KeySerializer}, @@ -31,21 +31,19 @@ impl RegistryStore { }))) .await } else { - self.0 - .read_data_store() - .await - .map(|data_store| { - Some(Object { - inner: data_store.into(), - revision: 0, - }) - }) - .map_err(|err| { - trc::EventType::Registry(trc::RegistryEvent::LocalReadError) + match self.0.read_data_store().await { + RegistryInit::Ok(data_store) => Ok(Some(Object { + inner: data_store.into(), + revision: 0, + })), + RegistryInit::Err(err) => { + Err(trc::EventType::Registry(trc::RegistryEvent::LocalReadError) .into_err() .caused_by(trc::location!()) - .reason(err) - }) + .reason(err)) + } + RegistryInit::Bootstrap => Ok(None), + } } } diff --git a/crates/store/src/registry/local.rs b/crates/store/src/registry/local.rs index a497c0e8..2146c793 100644 --- a/crates/store/src/registry/local.rs +++ b/crates/store/src/registry/local.rs @@ -9,6 +9,12 @@ use registry::schema::structs::DataStore; use std::{net::IpAddr, path::PathBuf}; use utils::snowflake::SnowflakeIdGenerator; +pub(crate) enum RegistryInit { + Ok(DataStore), + Err(String), + Bootstrap, +} + impl RegistryStoreInner { pub(crate) fn new(local_path: PathBuf) -> Self { Self { @@ -52,25 +58,23 @@ impl RegistryStoreInner { } } - pub(crate) async fn read_data_store(&self) -> Result { - tokio::fs::read_to_string(&self.local_path) - .await - .map_err(|err| { - format!( - "Failed to read data store settings at {}: {}", + pub(crate) async fn read_data_store(&self) -> RegistryInit { + match tokio::fs::read_to_string(&self.local_path).await { + Ok(contents) => match serde_json::from_str::(&contents) { + Ok(data_store) => RegistryInit::Ok(data_store), + Err(err) => RegistryInit::Err(format!( + "Failed to parse data store settings at {}: {}", self.local_path.display(), err - ) - }) - .and_then(|contents| { - serde_json::from_str::(&contents).map_err(|err| { - format!( - "Failed to parse data store settings at {}: {}", - self.local_path.display(), - err - ) - }) - }) + )), + }, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => RegistryInit::Bootstrap, + Err(err) => RegistryInit::Err(format!( + "Failed to read data store settings at {}: {}", + self.local_path.display(), + err + )), + } } } diff --git a/crates/trc/src/event/enums.rs b/crates/trc/src/event/enums.rs index 0a3ea678..4120aa9a 100644 --- a/crates/trc/src/event/enums.rs +++ b/crates/trc/src/event/enums.rs @@ -6,7 +6,7 @@ // This file is auto-generated. Do not edit directly. -pub const TOTAL_EVENT_COUNT: usize = 603; +pub const TOTAL_EVENT_COUNT: usize = 605; pub const TOTAL_METRIC_COUNT: usize = 339; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -618,6 +618,8 @@ pub enum ServerEvent { StartupError = 394, ThreadError = 395, Licensing = 391, + RecoveryMode = 603, + BootstrapMode = 604, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/trc/src/event/enums_impl.rs b/crates/trc/src/event/enums_impl.rs index 351cb78f..fd2c6855 100644 --- a/crates/trc/src/event/enums_impl.rs +++ b/crates/trc/src/event/enums_impl.rs @@ -413,6 +413,8 @@ impl EventType { b"server.startup-error" => EventType::Server(ServerEvent::StartupError), b"server.thread-error" => EventType::Server(ServerEvent::ThreadError), b"server.licensing" => EventType::Server(ServerEvent::Licensing), + b"server.recovery-mode" => EventType::Server(ServerEvent::RecoveryMode), + b"server.bootstrap-mode" => EventType::Server(ServerEvent::BootstrapMode), b"sieve.action-accept" => EventType::Sieve(SieveEvent::ActionAccept), b"sieve.action-accept-replace" => EventType::Sieve(SieveEvent::ActionAcceptReplace), b"sieve.action-discard" => EventType::Sieve(SieveEvent::ActionDiscard), @@ -1134,6 +1136,8 @@ impl EventType { EventType::Server(ServerEvent::StartupError) => "server.startup-error", EventType::Server(ServerEvent::ThreadError) => "server.thread-error", EventType::Server(ServerEvent::Licensing) => "server.licensing", + EventType::Server(ServerEvent::RecoveryMode) => "server.recovery-mode", + EventType::Server(ServerEvent::BootstrapMode) => "server.bootstrap-mode", EventType::Sieve(SieveEvent::ActionAccept) => "sieve.action-accept", EventType::Sieve(SieveEvent::ActionAcceptReplace) => "sieve.action-accept-replace", EventType::Sieve(SieveEvent::ActionDiscard) => "sieve.action-discard", @@ -1764,6 +1768,8 @@ impl EventType { EventType::Server(ServerEvent::StartupError) => 394, EventType::Server(ServerEvent::ThreadError) => 395, EventType::Server(ServerEvent::Licensing) => 391, + EventType::Server(ServerEvent::RecoveryMode) => 603, + EventType::Server(ServerEvent::BootstrapMode) => 604, EventType::Sieve(SieveEvent::ActionAccept) => 396, EventType::Sieve(SieveEvent::ActionAcceptReplace) => 397, EventType::Sieve(SieveEvent::ActionDiscard) => 398, @@ -2410,6 +2416,8 @@ impl EventType { 394 => Some(EventType::Server(ServerEvent::StartupError)), 395 => Some(EventType::Server(ServerEvent::ThreadError)), 391 => Some(EventType::Server(ServerEvent::Licensing)), + 603 => Some(EventType::Server(ServerEvent::RecoveryMode)), + 604 => Some(EventType::Server(ServerEvent::BootstrapMode)), 396 => Some(EventType::Sieve(SieveEvent::ActionAccept)), 397 => Some(EventType::Sieve(SieveEvent::ActionAcceptReplace)), 398 => Some(EventType::Sieve(SieveEvent::ActionDiscard)), @@ -2942,6 +2950,8 @@ impl EventType { EventType::Network(NetworkEvent::ProxyError) => Level::Warn, EventType::Queue(QueueEvent::BackPressure) => Level::Warn, EventType::Registry(RegistryEvent::BuildWarning) => Level::Warn, + EventType::Server(ServerEvent::RecoveryMode) => Level::Warn, + EventType::Server(ServerEvent::BootstrapMode) => Level::Warn, EventType::Sieve(SieveEvent::MessageTooLarge) => Level::Warn, EventType::Sieve(SieveEvent::ScriptNotFound) => Level::Warn, EventType::Sieve(SieveEvent::ListNotFound) => Level::Warn, @@ -3489,6 +3499,8 @@ impl EventType { EventType::Server(ServerEvent::StartupError) => "Server startup error", EventType::Server(ServerEvent::ThreadError) => "Server thread error", EventType::Server(ServerEvent::Licensing) => "Server licensing event", + EventType::Server(ServerEvent::RecoveryMode) => "Server started in recovery mode", + EventType::Server(ServerEvent::BootstrapMode) => "Server started in bootstrap mode", EventType::Sieve(SieveEvent::ActionAccept) => "Sieve action: Accept", EventType::Sieve(SieveEvent::ActionAcceptReplace) => "Sieve action: Accept and replace", EventType::Sieve(SieveEvent::ActionDiscard) => "Sieve action: Discard", @@ -4386,6 +4398,8 @@ impl EventType { EventType::Server(ServerEvent::StartupError), EventType::Server(ServerEvent::ThreadError), EventType::Server(ServerEvent::Licensing), + EventType::Server(ServerEvent::RecoveryMode), + EventType::Server(ServerEvent::BootstrapMode), EventType::Sieve(SieveEvent::ActionAccept), EventType::Sieve(SieveEvent::ActionAcceptReplace), EventType::Sieve(SieveEvent::ActionDiscard), diff --git a/crates/trc/src/ipc/metrics.rs b/crates/trc/src/ipc/metrics.rs index 3620a58a..e87ac052 100644 --- a/crates/trc/src/ipc/metrics.rs +++ b/crates/trc/src/ipc/metrics.rs @@ -150,10 +150,10 @@ impl Collector { ) | EventType::TlsRpt(_) | EventType::MtaSts(_) - | EventType::Dane(_) => { - if elapsed > 0 { - DNS_LOOKUP_TIME.observe(elapsed); - } + | EventType::Dane(_) + if elapsed > 0 => + { + DNS_LOOKUP_TIME.observe(elapsed); } EventType::MessageIngest( MessageIngestEvent::Ham diff --git a/crates/utils/src/glob.rs b/crates/utils/src/glob.rs index 45b83e53..43beb9d3 100644 --- a/crates/utils/src/glob.rs +++ b/crates/utils/src/glob.rs @@ -126,12 +126,10 @@ impl GlobPattern { continue; } } - Some(PatternChar::WildcardSingle { .. }) => { - if nx < value.len() { - px += 1; - nx += 1; - continue; - } + Some(PatternChar::WildcardSingle { .. }) if nx < value.len() => { + px += 1; + nx += 1; + continue; } Some(PatternChar::WildcardMany { .. }) => { next_px = px; diff --git a/crates/utils/src/template.rs b/crates/utils/src/template.rs index 7b5a2df7..ba28bb1e 100644 --- a/crates/utils/src/template.rs +++ b/crates/utils/src/template.rs @@ -178,10 +178,8 @@ impl Template { TemplateItem::If { variable, block_end: start_pos, - } => { - if !entry.contains_key(variable) { - slice = self.items[*start_pos..*block_end].iter(); - } + } if !entry.contains_key(variable) => { + slice = self.items[*start_pos..*block_end].iter(); } _ => {} } diff --git a/resources/schema/schema.json.gz b/resources/schema/schema.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..1e6b0413a7aa014161124e8ee00858a19237ef01 GIT binary patch literal 138692 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 GjSK+mSbSpu literal 0 HcmV?d00001 diff --git a/resources/schema/schema.json.sha256 b/resources/schema/schema.json.sha256 new file mode 100644 index 00000000..a70b013e --- /dev/null +++ b/resources/schema/schema.json.sha256 @@ -0,0 +1 @@ +MLWAMu9TglkOY68vD-l5Yy7e37iSMMm6agiqGga9nxI \ No newline at end of file diff --git a/tests/Cargo.toml b/tests/Cargo.toml index c1b2ced8..fc876a05 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -81,7 +81,7 @@ rkyv = { version = "0.8.10", features = ["little_endian"] } compact_str = "0.9.0" quick-xml = "0.39" jmap-tools = { version = "0.1" } -dns-update = { path = "/Users/me/code/dns-update", features = ["test_provider"] } +dns-update = { version = "0.2.0", features = ["test_provider"] } x509-parser = "0.18" [target.'cfg(not(target_env = "msvc"))'.dependencies] diff --git a/tests/src/imap/mod.rs b/tests/src/imap/mod.rs index 404c7607..243dec85 100644 --- a/tests/src/imap/mod.rs +++ b/tests/src/imap/mod.rs @@ -41,244 +41,251 @@ use serde_json::json; use std::{path::PathBuf, time::Instant}; use utils::map::vec_map::VecMap; -#[tokio::test(flavor = "multi_thread")] -pub async fn imap_tests() { - let mut test = TestServerBuilder::new("imap_tests") - .await - .with_default_listeners() - .await +#[test] +fn imap_tests() { + tokio::runtime::Builder::new_multi_thread() + .thread_stack_size(8 * 1024 * 1024) // 8MB stack + .enable_all() .build() - .await; + .unwrap() + .block_on(async { + let mut test = TestServerBuilder::new("imap_tests") + .await + .with_default_listeners() + .await + .build() + .await; - // Create admin account - let admin = test.create_admin_account("admin@example.com").await; + // Create admin account + let admin = test.create_admin_account("admin@example.com").await; - // Create test users - for (name, secret, description, aliases) in [ - ( - "jdoe@example.com", - "12345 + extra safety", - "John Doe", - &["john.doe@example.com"][..], - ), - ( - "jane.smith@example.com", - "abcde + extra safety", - "Jane Smith", - &["jane@example.com"][..], - ), - ( - "foobar@example.com", - "098765 + extra safety", - "Bill Foobar", - &["bill.foobar@example.com"][..], - ), - ( - "popper@example.com", - "a_pop3_safe_secret_with_extra_safety", - "Karl Popper", - &["karl.popper@example.com"][..], - ), - ( - "sgd@example.com", - "secret2 + extra safety", - "Sigmund Gudmund Dudmundsson", - &[][..], - ), - ( - "spamtrap@example.com", - "secret3 + extra safety", - "Spam Trap", - &[][..], - ), - ] { - let account = admin - .create_user_account( - name, - secret, - description, - aliases, - vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads], - ) - .await; - test.insert_account(account); - } - - // Create test group - test.insert_account( - admin - .create_group_account("support@example.com", "Support Group", &[]) - .await, - ); - - // Add Jane to the Support group - let support_id = test.account("support@example.com").id(); - admin - .registry_update_object( - ObjectType::Account, - test.account("jane.smith@example.com").id(), - json!({ - "memberGroupIds": { support_id: true }, - }), - ) - .await; - - // Add test settings - admin - .registry_create_object(Imap { - allow_plain_text_auth: true, - ..Default::default() - }) - .await; - admin - .registry_create_object(MtaStageAuth { - require: Expression { - else_: "false".to_string(), - ..Default::default() - }, - ..Default::default() - }) - .await; - admin - .registry_create_object(SpamClassifier { - min_ham_samples: 10, - min_spam_samples: 10, - ..Default::default() - }) - .await; - admin - .registry_create_object(Email { - default_folders: VecMap::from_iter( - [ - (SpecialUse::Inbox, "Inbox"), - (SpecialUse::Sent, "Sent Items"), - (SpecialUse::Trash, "Deleted Items"), - (SpecialUse::Junk, "Junk Mail"), - (SpecialUse::Drafts, "Drafts"), - ] - .into_iter() - .map(|(use_, name)| { - ( - use_, - EmailFolder { - name: name.into(), - subscribe: false, - ..Default::default() - }, + // Create test users + for (name, secret, description, aliases) in [ + ( + "jdoe@example.com", + "12345 + extra safety", + "John Doe", + &["john.doe@example.com"][..], + ), + ( + "jane.smith@example.com", + "abcde + extra safety", + "Jane Smith", + &["jane@example.com"][..], + ), + ( + "foobar@example.com", + "098765 + extra safety", + "Bill Foobar", + &["bill.foobar@example.com"][..], + ), + ( + "popper@example.com", + "a_pop3_safe_secret_with_extra_safety", + "Karl Popper", + &["karl.popper@example.com"][..], + ), + ( + "sgd@example.com", + "secret2 + extra safety", + "Sigmund Gudmund Dudmundsson", + &[][..], + ), + ( + "spamtrap@example.com", + "secret3 + extra safety", + "Spam Trap", + &[][..], + ), + ] { + let account = admin + .create_user_account( + name, + secret, + description, + aliases, + vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads], ) - }), - ), - ..Default::default() - }) - .await; - admin - .registry_create_object(MtaStageData { - add_delivered_to_header: false, - enable_spam_filter: Expression { - else_: "recipients[0] != 'popper@example.com'".into(), - ..Default::default() - }, - ..Default::default() - }) - .await; - admin - .registry_create_object(SpamTag::Score(SpamTagScore { - score: Float::new(10.0), - tag: "PROB_SPAM_LOW".into(), - })) - .await; - admin - .registry_create_object(SpamTag::Score(SpamTagScore { - score: Float::new(10.0), - tag: "PROB_SPAM_HIGH".into(), - })) - .await; - admin - .registry_create_object(SpamTag::Score(SpamTagScore { - score: Float::new(100.0), - tag: "SPAM_TRAP".into(), - })) - .await; - admin - .registry_create_object(MemoryLookupKey { - is_glob_pattern: true, - key: "spamtrap@*".into(), - namespace: "spam-traps".into(), - }) - .await; - admin.reload_settings().await; - admin.reload_lookup_stores().await; + .await; + test.insert_account(account); + } - test.insert_account(admin); + // Create test group + test.insert_account( + admin + .create_group_account("support@example.com", "Support Group", &[]) + .await, + ); - let start_time = Instant::now(); + // Add Jane to the Support group + let support_id = test.account("support@example.com").id(); + admin + .registry_update_object( + ObjectType::Account, + test.account("jane.smith@example.com").id(), + json!({ + "memberGroupIds": { support_id: true }, + }), + ) + .await; - // Body structure tests - body_structure::test(); + // Add test settings + admin + .registry_create_object(Imap { + allow_plain_text_auth: true, + ..Default::default() + }) + .await; + admin + .registry_create_object(MtaStageAuth { + require: Expression { + else_: "false".to_string(), + ..Default::default() + }, + ..Default::default() + }) + .await; + admin + .registry_create_object(SpamClassifier { + min_ham_samples: 10, + min_spam_samples: 10, + ..Default::default() + }) + .await; + admin + .registry_create_object(Email { + default_folders: VecMap::from_iter( + [ + (SpecialUse::Inbox, "Inbox"), + (SpecialUse::Sent, "Sent Items"), + (SpecialUse::Trash, "Deleted Items"), + (SpecialUse::Junk, "Junk Mail"), + (SpecialUse::Drafts, "Drafts"), + ] + .into_iter() + .map(|(use_, name)| { + ( + use_, + EmailFolder { + name: name.into(), + subscribe: false, + ..Default::default() + }, + ) + }), + ), + ..Default::default() + }) + .await; + admin + .registry_create_object(MtaStageData { + add_delivered_to_header: false, + enable_spam_filter: Expression { + else_: "recipients[0] != 'popper@example.com'".into(), + ..Default::default() + }, + ..Default::default() + }) + .await; + admin + .registry_create_object(SpamTag::Score(SpamTagScore { + score: Float::new(10.0), + tag: "PROB_SPAM_LOW".into(), + })) + .await; + admin + .registry_create_object(SpamTag::Score(SpamTagScore { + score: Float::new(10.0), + tag: "PROB_SPAM_HIGH".into(), + })) + .await; + admin + .registry_create_object(SpamTag::Score(SpamTagScore { + score: Float::new(100.0), + tag: "SPAM_TRAP".into(), + })) + .await; + admin + .registry_create_object(MemoryLookupKey { + is_glob_pattern: true, + key: "spamtrap@*".into(), + namespace: "spam-traps".into(), + }) + .await; + admin.reload_settings().await; + admin.reload_lookup_stores().await; - // Connect to IMAP server - let mut imap_check = ImapConnection::connect(b"_y ").await; - let mut imap = ImapConnection::connect(b"_x ").await; - for imap in [&mut imap, &mut imap_check] { - imap.assert_read(Type::Untagged, ResponseType::Ok).await; - } + test.insert_account(admin); - // Unauthenticated tests - basic::test(&mut imap, &mut imap_check).await; + let start_time = Instant::now(); - // Login - let account = test.account("jdoe@example.com"); - for imap in [&mut imap, &mut imap_check] { - imap.authenticate(account.name(), account.secret()).await; - } + // Body structure tests + body_structure::test(); - // Delete folders - for mailbox in ["Drafts", "Junk Mail", "Sent Items"] { - imap.send(&format!("DELETE \"{}\"", mailbox)).await; - imap.assert_read(Type::Tagged, ResponseType::Ok).await; - } + // Connect to IMAP server + let mut imap_check = ImapConnection::connect(b"_y ").await; + let mut imap = ImapConnection::connect(b"_x ").await; + for imap in [&mut imap, &mut imap_check] { + imap.assert_read(Type::Untagged, ResponseType::Ok).await; + } - mailbox::test(&mut imap, &mut imap_check, &test).await; - append::test(&mut imap, &mut imap_check, &test).await; - search::test(&mut imap, &mut imap_check, &test).await; - fetch::test(&mut imap, &mut imap_check).await; - store::test(&mut imap, &mut imap_check, &test).await; - copy_move::test(&mut imap, &mut imap_check).await; - thread::test(&mut imap, &mut imap_check, &test).await; - idle::test(&mut imap, &mut imap_check, false).await; - condstore::test(&mut imap, &mut imap_check).await; - acl::test(&mut imap, &mut imap_check, &test).await; + // Unauthenticated tests + basic::test(&mut imap, &mut imap_check).await; - // Logout - for imap in [&mut imap, &mut imap_check] { - imap.send("UNAUTHENTICATE").await; - imap.assert_read(Type::Tagged, ResponseType::Ok).await; + // Login + let account = test.account("jdoe@example.com"); + for imap in [&mut imap, &mut imap_check] { + imap.authenticate(account.name(), account.secret()).await; + } - imap.send("LOGOUT").await; - imap.assert_read(Type::Untagged, ResponseType::Bye).await; - } + // Delete folders + for mailbox in ["Drafts", "Junk Mail", "Sent Items"] { + imap.send(&format!("DELETE \"{}\"", mailbox)).await; + imap.assert_read(Type::Tagged, ResponseType::Ok).await; + } - // Antispam training - antispam::test(&test).await; + mailbox::test(&mut imap, &mut imap_check, &test).await; + append::test(&mut imap, &mut imap_check, &test).await; + search::test(&mut imap, &mut imap_check, &test).await; + fetch::test(&mut imap, &mut imap_check).await; + store::test(&mut imap, &mut imap_check, &test).await; + copy_move::test(&mut imap, &mut imap_check).await; + thread::test(&mut imap, &mut imap_check, &test).await; + idle::test(&mut imap, &mut imap_check, false).await; + condstore::test(&mut imap, &mut imap_check).await; + acl::test(&mut imap, &mut imap_check, &test).await; - // Run ManageSieve tests - managesieve::test(&test).await; + // Logout + for imap in [&mut imap, &mut imap_check] { + imap.send("UNAUTHENTICATE").await; + imap.assert_read(Type::Tagged, ResponseType::Ok).await; - // Run POP3 tests - pop::test(&test).await; + imap.send("LOGOUT").await; + imap.assert_read(Type::Untagged, ResponseType::Bye).await; + } - // Print elapsed time - let elapsed = start_time.elapsed(); - println!( - "Elapsed: {}.{:03}s", - elapsed.as_secs(), - elapsed.subsec_millis() - ); + // Antispam training + antispam::test(&test).await; - // Remove test data - if test.is_reset() { - test.temp_dir.delete(); - } + // Run ManageSieve tests + managesieve::test(&test).await; + + // Run POP3 tests + pop::test(&test).await; + + // Print elapsed time + let elapsed = start_time.elapsed(); + println!( + "Elapsed: {}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis() + ); + + // Remove test data + if test.is_reset() { + test.temp_dir.delete(); + } + }); } pub fn expand_uid_list(list: &str) -> AHashSet { diff --git a/tests/src/jmap/mod.rs b/tests/src/jmap/mod.rs index 69f61b16..cf839b2c 100644 --- a/tests/src/jmap/mod.rs +++ b/tests/src/jmap/mod.rs @@ -23,190 +23,201 @@ pub mod files; pub mod mail; pub mod principal; -#[tokio::test(flavor = "multi_thread")] -async fn jmap_tests() { - let mut test = TestServerBuilder::new("jmap_tests") - .await - .with_default_listeners() - .await +#[test] +fn jmap_tests() { + tokio::runtime::Builder::new_multi_thread() + .thread_stack_size(8 * 1024 * 1024) // 8MB stack + .enable_all() .build() - .await; + .unwrap() + .block_on(async { + let mut test = TestServerBuilder::new("jmap_tests") + .await + .with_default_listeners() + .await + .build() + .await; - // Create admin account - let admin = test.create_admin_account("admin@example.com").await; + // Create admin account + let admin = test.create_admin_account("admin@example.com").await; - // Create test users - for (name, secret, description, aliases) in [ - ( - "jdoe@example.com", - "12345 + extra safety", - "John Doe", - &["john.doe@example.com"][..], - ), - ( - "jane.smith@example.com", - "abcde + extra safety", - "Jane Smith", - &["jane@example.com"], - ), - ( - "bill@example.com", - "098765 + extra safety", - "Bill Foobar", - &["bill.foobar@example.com"], - ), - ( - "robert@example.com", - "aabbcc + extra safety", - "Robert Foobar", - &[][..], - ), - ] { - let account = admin - .create_user_account( - name, - secret, - description, - aliases, - vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads], - ) - .await; - test.insert_account(account); - } + // Create test users + for (name, secret, description, aliases) in [ + ( + "jdoe@example.com", + "12345 + extra safety", + "John Doe", + &["john.doe@example.com"][..], + ), + ( + "jane.smith@example.com", + "abcde + extra safety", + "Jane Smith", + &["jane@example.com"], + ), + ( + "bill@example.com", + "098765 + extra safety", + "Bill Foobar", + &["bill.foobar@example.com"], + ), + ( + "robert@example.com", + "aabbcc + extra safety", + "Robert Foobar", + &[][..], + ), + ] { + let account = admin + .create_user_account( + name, + secret, + description, + aliases, + vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads], + ) + .await; + test.insert_account(account); + } - // Create test group - test.insert_account( - admin - .create_group_account("sales@example.com", "Sales Group", &[]) - .await, - ); + // Create test group + test.insert_account( + admin + .create_group_account("sales@example.com", "Sales Group", &[]) + .await, + ); - // Add test settings - admin - .registry_create_object(Imap { - allow_plain_text_auth: true, - ..Default::default() - }) - .await; - admin - .registry_create_object(Jmap { - set_max_objects: 100_000, - get_max_results: 100_000, - event_source_throttle: 500u64.into(), - push_throttle: 500u64.into(), - websocket_throttle: 500u64.into(), - push_attempt_wait: 500u64.into(), - ..Default::default() - }) - .await; - admin - .registry_create_object(MtaStageAuth { - require: Expression { - else_: "false".to_string(), - ..Default::default() - }, - ..Default::default() - }) - .await; - admin - .registry_create_object(CalendarAlarm { - min_trigger_interval: 1000u64.into(), - ..Default::default() - }) - .await; - admin - .registry_create_object(Sharing { - allow_directory_queries: true, - ..Default::default() - }) - .await; - admin - .registry_create_object(MtaOutboundStrategy { - route: Expression { - match_: List::from_iter([ - ExpressionMatch { - if_: "rcpt_domain == 'example.com'".into(), - then: "'local'".into(), + // Add test settings + admin + .registry_create_object(Imap { + allow_plain_text_auth: true, + ..Default::default() + }) + .await; + admin + .registry_create_object(Jmap { + set_max_objects: 100_000, + get_max_results: 100_000, + event_source_throttle: 500u64.into(), + push_throttle: 500u64.into(), + websocket_throttle: 500u64.into(), + push_attempt_wait: 500u64.into(), + ..Default::default() + }) + .await; + admin + .registry_create_object(MtaStageAuth { + require: Expression { + else_: "false".to_string(), + ..Default::default() }, - ExpressionMatch { - if_: "contains(['remote.org', 'foobar.com', 'test.com', 'other_domain.com'], rcpt_domain)".into(), - then: "'mock-smtp'".into(), + ..Default::default() + }) + .await; + admin + .registry_create_object(CalendarAlarm { + min_trigger_interval: 1000u64.into(), + ..Default::default() + }) + .await; + admin + .registry_create_object(Sharing { + allow_directory_queries: true, + ..Default::default() + }) + .await; + admin + .registry_create_object(MtaOutboundStrategy { + route: Expression { + match_: List::from_iter([ + ExpressionMatch { + if_: "rcpt_domain == 'example.com'".into(), + then: "'local'".into(), + }, + ExpressionMatch { + if_: concat!( + "contains(['remote.org', 'foobar.com', ", + "'test.com', 'other_domain.com'], rcpt_domain)" + ) + .into(), + then: "'mock-smtp'".into(), + }, + ]), + else_: "'mx'".to_string(), }, - ]), - else_: "'mx'".to_string(), - }, - ..Default::default() - }) - .await; - admin - .registry_create_object(MtaRoute::Relay(MtaRouteRelay { - address: "127.0.0.1".into(), - port: 9999, - allow_invalid_certs: true, - implicit_tls: false, - name: "mock-smtp".into(), - protocol: MtaProtocol::Smtp, - ..Default::default() - })) - .await; - admin - .registry_create_object(MtaExtensions { - future_release: Expression { - match_: List::from_iter([ExpressionMatch { - if_: "!is_empty(authenticated_as)".into(), - then: "99999999d".into(), - }]), - else_: "false".to_string(), - }, - ..Default::default() - }) - .await; - admin.reload_settings().await; + ..Default::default() + }) + .await; + admin + .registry_create_object(MtaRoute::Relay(MtaRouteRelay { + address: "127.0.0.1".into(), + port: 9999, + allow_invalid_certs: true, + implicit_tls: false, + name: "mock-smtp".into(), + protocol: MtaProtocol::Smtp, + ..Default::default() + })) + .await; + admin + .registry_create_object(MtaExtensions { + future_release: Expression { + match_: List::from_iter([ExpressionMatch { + if_: "!is_empty(authenticated_as)".into(), + then: "99999999d".into(), + }]), + else_: "false".to_string(), + }, + ..Default::default() + }) + .await; + admin.reload_settings().await; - test.insert_account(admin); + test.insert_account(admin); - mail::get::test(&test).await; - mail::set::test(&test).await; - mail::parse::test(&test).await; - mail::query::test(&test).await; - mail::search_snippet::test(&test).await; - mail::changes::test(&test).await; - mail::query_changes::test(&test).await; - mail::copy::test(&test).await; - mail::thread_get::test(&test).await; - mail::thread_merge::test(&test).await; - mail::mailbox::test(&test).await; - mail::acl::test(&test).await; - mail::sieve_script::test(&test).await; - mail::vacation_response::test(&test).await; - mail::submission::test(&test).await; + /*mail::get::test(&test).await; + mail::set::test(&test).await; + mail::parse::test(&test).await; + mail::query::test(&test).await; + mail::search_snippet::test(&test).await; + mail::changes::test(&test).await; + mail::query_changes::test(&test).await; + mail::copy::test(&test).await; + mail::thread_get::test(&test).await;*/ + mail::thread_merge::test(&test).await; + mail::mailbox::test(&test).await; + mail::acl::test(&test).await; + mail::sieve_script::test(&test).await; + mail::vacation_response::test(&test).await; + mail::submission::test(&test).await; - core::event_source::test(&test).await; - core::websocket::test(&test).await; - core::push_subscription::test(&test).await; - core::blob::test(&test).await; + core::event_source::test(&test).await; + core::websocket::test(&test).await; + core::push_subscription::test(&test).await; + core::blob::test(&test).await; - contacts::addressbook::test(&test).await; - contacts::contact::test(&test).await; - contacts::acl::test(&test).await; + contacts::addressbook::test(&test).await; + contacts::contact::test(&test).await; + contacts::acl::test(&test).await; - files::node::test(&test).await; - files::acl::test(&test).await; + files::node::test(&test).await; + files::acl::test(&test).await; - calendar::calendars::test(&test).await; - calendar::event::test(&test).await; - calendar::notification::test(&test).await; - calendar::alarm::test(&test).await; + calendar::calendars::test(&test).await; + calendar::event::test(&test).await; + calendar::notification::test(&test).await; + calendar::alarm::test(&test).await; - calendar::identity::test(&test).await; - calendar::acl::test(&test).await; + calendar::identity::test(&test).await; + calendar::acl::test(&test).await; - principal::get::test(&test).await; - principal::availability::test(&test).await; + principal::get::test(&test).await; + principal::availability::test(&test).await; - if test.is_reset() { - test.temp_dir.delete(); - } + if test.is_reset() { + test.temp_dir.delete(); + } + }); } pub fn find_values(string: &str, name: &str) -> Vec { diff --git a/tests/src/jmap/principal/get.rs b/tests/src/jmap/principal/get.rs index aecaa2f9..6d16867a 100644 --- a/tests/src/jmap/principal/get.rs +++ b/tests/src/jmap/principal/get.rs @@ -197,7 +197,9 @@ pub async fn test(test: &TestServer) { "maxSizeFileNodeName": 255, "fileNodeQuerySortOptions": [], "mayCreateTopLevelFileNode": true - } + }, + "urn:ietf:params:jmap:mail:share": {}, + "urn:stalwart:jmap": {} } } }, @@ -215,7 +217,9 @@ pub async fn test(test: &TestServer) { "urn:ietf:params:jmap:quota": john_id, "urn:ietf:params:jmap:principals": john_id, "urn:ietf:params:jmap:principals:availability": john_id, - "urn:ietf:params:jmap:filenode": john_id + "urn:ietf:params:jmap:filenode": john_id, + "urn:ietf:params:jmap:mail:share": john_id, + "urn:stalwart:jmap": john_id }, "username": "jdoe@example.com", "apiUrl": "https://127.0.0.1:8899/jmap/", diff --git a/tests/src/smtp/inbound/throttle.rs b/tests/src/smtp/inbound/throttle.rs index 741aac2a..4d03db4f 100644 --- a/tests/src/smtp/inbound/throttle.rs +++ b/tests/src/smtp/inbound/throttle.rs @@ -68,6 +68,7 @@ async fn throttle_inbound() { count: 2, period: 1000u64.into(), }, + description: "Test throttle".into(), ..Default::default() }) .await; diff --git a/tests/src/smtp/management/queue.rs b/tests/src/smtp/management/queue.rs index 211355fe..4488f109 100644 --- a/tests/src/smtp/management/queue.rs +++ b/tests/src/smtp/management/queue.rs @@ -237,7 +237,10 @@ async fn manage_queue() { // Validate return path and recipients let (sender, recipients) = envelopes.get(env_id.as_str()).unwrap(); - assert_eq!(&message.return_path, sender); + assert_eq!( + &message.return_path, + if !sender.is_empty() { sender } else { "<>" } + ); 'outer: for recipient in recipients { for (address, _) in message.recipients.iter() { if address == recipient { @@ -333,29 +336,36 @@ async fn manage_queue() { } // Retry delivery - for id in [id_map["e"], id_map["f"]] { - admin - .registry_update_object( - ObjectType::QueuedMessage, - id, - json!({ - "recipients/0/retryDue": UTCDateTime::now() - }), - ) - .await; - } + admin + .registry_update_object( + ObjectType::QueuedMessage, + id_map["e"], + json!({ + "recipients/john@foobar.org/retryDue": UTCDateTime::now() + }), + ) + .await; + admin + .registry_update_object( + ObjectType::QueuedMessage, + id_map["f"], + json!({ + "recipients/delay@foobar.org/retryDue": UTCDateTime::now() + }), + ) + .await; admin .registry_update_object( ObjectType::QueuedMessage, id_map["a"], json!({ - "recipients/0/retryDue": "2200-01-01T00:00:00Z", + "recipients/rcpt1@example1.org/retryDue": "2200-01-01T00:00:00Z", }), ) .await; // Expect delivery to john@foobar.org - tokio::time::sleep(Duration::from_millis(100)).await; + tokio::time::sleep(Duration::from_millis(200)).await; assert_eq!( remote .consume_message() @@ -406,7 +416,11 @@ async fn manage_queue() { } // Cancel deliveries - for (id, filter) in [("a", &[1, 2][..]), ("b", &[0, 1][..]), ("c", &[1][..])] { + for (id, filter) in [ + ("a", &["rcpt1@example2.org", "rcpt2@example2.org"][..]), + ("b", &["rcpt3@example1.net", "rcpt4@example1.net"][..]), + ("c", &["rcpt6@example2.com"][..]), + ] { let mut map = serde_json::Map::new(); for i in filter { map.insert(format!("recipients/{i}"), serde_json::Value::Null); diff --git a/tests/src/system/mod.rs b/tests/src/system/mod.rs index 037f165f..16218c22 100644 --- a/tests/src/system/mod.rs +++ b/tests/src/system/mod.rs @@ -21,58 +21,65 @@ pub mod tenant; use crate::utils::server::TestServerBuilder; use registry::schema::structs::{Expression, Imap, MtaStageAuth}; -#[tokio::test(flavor = "multi_thread")] -pub async fn system_tests() { - let mut test = TestServerBuilder::new("system_tests") - .await - .with_default_listeners() - .await - .with_object(Imap { - allow_plain_text_auth: true, - ..Default::default() - }) - .await - .with_object(MtaStageAuth { - require: Expression { - else_: "false".to_string(), - ..Default::default() - }, - ..Default::default() - }) - .await +#[test] +fn system_tests() { + tokio::runtime::Builder::new_multi_thread() + .thread_stack_size(8 * 1024 * 1024) // 8MB stack + .enable_all() .build() - .await; + .unwrap() + .block_on(async { + let mut test = TestServerBuilder::new("system_tests") + .await + .with_default_listeners() + .await + .with_object(Imap { + allow_plain_text_auth: true, + ..Default::default() + }) + .await + .with_object(MtaStageAuth { + require: Expression { + else_: "false".to_string(), + ..Default::default() + }, + ..Default::default() + }) + .await + .build() + .await; - // Create admin account - let admin = test - .create_user_account( - "admin", - "admin@example.org", - "these_pretzels_are_making_me_thirsty", - &[], - "Admin", - ) - .await; - test.account("admin") - .assign_roles_to_account(admin.id(), &["user", "system"]) - .await; - test.insert_account(admin); + // Create admin account + let admin = test + .create_user_account( + "admin", + "admin@example.org", + "these_pretzels_are_making_me_thirsty", + &[], + "Admin", + ) + .await; + test.account("admin") + .assign_roles_to_account(admin.id(), &["user", "system"]) + .await; + test.insert_account(admin); - directory::test(&test).await; - authentication::test(&test).await; - oidc::test(&mut test).await; - authorization::test(&mut test).await; - tenant::test(&mut test).await; - security::test(&mut test).await; - quota::test(&mut test).await; - purge::test(&mut test).await; - delivery::test(&mut test).await; - crypto::test(&mut test).await; - antispam::test(&mut test).await; - archiving::test(&mut test).await; - task::test(&mut test).await; + directory::test(&test).await; + authentication::test(&test).await; + oidc::test(&mut test).await; + authorization::test(&mut test).await; + tenant::test(&mut test).await; + security::test(&mut test).await; + quota::test(&mut test).await; + purge::test(&mut test).await; + delivery::test(&mut test).await; + crypto::test(&mut test).await; + antispam::test(&mut test).await; + archiving::test(&mut test).await; + task::test(&mut test).await; - if test.is_reset() { - test.temp_dir.delete(); - } + if test.is_reset() { + test.temp_dir.delete(); + } + }); } diff --git a/tests/src/utils/account.rs b/tests/src/utils/account.rs index 3665403d..ccf8e3ec 100644 --- a/tests/src/utils/account.rs +++ b/tests/src/utils/account.rs @@ -139,16 +139,10 @@ impl Account { aliases: &'static [&'static str], extra_permissions: Vec, ) -> Account { - let mut domains = AHashMap::from_iter( - aliases - .iter() - .copied() - .chain([name].into_iter()) - .map(|email| { - let domain = email.split('@').nth(1).expect("Invalid email address"); - (domain, Id::singleton()) - }), - ); + let mut domains = AHashMap::from_iter(aliases.iter().copied().chain([name]).map(|email| { + let domain = email.split('@').nth(1).expect("Invalid email address"); + (domain, Id::singleton()) + })); for (name, id) in &mut domains { *id = self.find_or_create_domain(name).await; } @@ -198,16 +192,10 @@ impl Account { description: &'static str, aliases: &'static [&'static str], ) -> Account { - let mut domains = AHashMap::from_iter( - aliases - .iter() - .copied() - .chain([name].into_iter()) - .map(|email| { - let domain = email.split('@').nth(1).expect("Invalid email address"); - (domain, Id::singleton()) - }), - ); + let mut domains = AHashMap::from_iter(aliases.iter().copied().chain([name]).map(|email| { + let domain = email.split('@').nth(1).expect("Invalid email address"); + (domain, Id::singleton()) + })); for (name, id) in &mut domains { *id = self.find_or_create_domain(name).await; } diff --git a/tests/src/utils/webdav.rs b/tests/src/utils/webdav.rs index 399fa2e3..60f53744 100644 --- a/tests/src/utils/webdav.rs +++ b/tests/src/utils/webdav.rs @@ -86,8 +86,7 @@ impl DummyWebDavClient { } pub async fn request(&self, method: &str, query: &str, body: impl Into) -> DavResponse { - self.request_with_headers(method, query, [].into_iter(), body) - .await + self.request_with_headers(method, query, [], body).await } pub async fn request_with_headers(