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 00000000..1e6b0413 Binary files /dev/null and b/resources/schema/schema.json.gz differ 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(