use serde::de::value::{MapDeserializer, SeqDeserializer};
use serde::de::{DeserializeOwned, Error as _, IntoDeserializer, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use crate::proto::pethost::panel::v1 as wire;
use crate::{convert, timestamp, types};
macro_rules! json {
($public:ty, $wire:ty, $to:path, $from:path) => {
impl Serialize for $public {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
$to(Clone::clone(self)).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for $public {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
read::<$wire, D>(deserializer).map($from)
}
}
};
}
json!(
crate::Timestamp,
buffa_types::google::protobuf::Timestamp,
timestamp::to_wire,
timestamp::from_wire
);
json!(
types::AlertChannelKind,
buffa::EnumValue<wire::AlertChannelKind>,
convert::alert_channel_kind_to_wire,
convert::alert_channel_kind_from_wire
);
json!(
types::MachineSessionKind,
buffa::EnumValue<wire::MachineSessionKind>,
convert::machine_session_kind_to_wire,
convert::machine_session_kind_from_wire
);
json!(
types::ProjectProblemKind,
buffa::EnumValue<wire::ProjectProblemKind>,
convert::project_problem_kind_to_wire,
convert::project_problem_kind_from_wire
);
json!(
types::ServicesActionKind,
buffa::EnumValue<wire::ServicesActionKind>,
convert::services_action_kind_to_wire,
convert::services_action_kind_from_wire
);
json!(
types::ServiceState,
buffa::EnumValue<wire::ServiceState>,
convert::service_state_to_wire,
convert::service_state_from_wire
);
json!(
types::RestartPolicy,
buffa::EnumValue<wire::RestartPolicy>,
convert::restart_policy_to_wire,
convert::restart_policy_from_wire
);
json!(
types::HealthStatus,
buffa::EnumValue<wire::HealthStatus>,
convert::health_status_to_wire,
convert::health_status_from_wire
);
json!(
types::CertificateSource,
buffa::EnumValue<wire::CertificateSource>,
convert::certificate_source_to_wire,
convert::certificate_source_from_wire
);
json!(
types::OperationKind,
buffa::EnumValue<wire::OperationKind>,
convert::operation_kind_to_wire,
convert::operation_kind_from_wire
);
json!(
types::OperationStatus,
buffa::EnumValue<wire::OperationStatus>,
convert::operation_status_to_wire,
convert::operation_status_from_wire
);
json!(
types::DeployFailureReason,
buffa::EnumValue<wire::DeployFailureReason>,
convert::deploy_failure_reason_to_wire,
convert::deploy_failure_reason_from_wire
);
json!(
types::TrafficMetric,
buffa::EnumValue<wire::TrafficMetric>,
convert::traffic_metric_to_wire,
convert::traffic_metric_from_wire
);
json!(
types::AlertStatus,
buffa::EnumValue<wire::AlertStatus>,
convert::alert_status_to_wire,
convert::alert_status_from_wire
);
json!(
types::IncidentQuietReason,
buffa::EnumValue<wire::IncidentQuietReason>,
convert::incident_quiet_reason_to_wire,
convert::incident_quiet_reason_from_wire
);
json!(
types::OutputStream,
buffa::EnumValue<wire::OutputStream>,
convert::output_stream_to_wire,
convert::output_stream_from_wire
);
json!(
types::FileType,
buffa::EnumValue<wire::FileType>,
convert::file_type_to_wire,
convert::file_type_from_wire
);
json!(
types::FileLocation,
buffa::EnumValue<wire::FileLocation>,
convert::file_location_to_wire,
convert::file_location_from_wire
);
json!(
types::NoMachineReason,
buffa::EnumValue<wire::NoMachineReason>,
convert::no_machine_reason_to_wire,
convert::no_machine_reason_from_wire
);
json!(
types::GetMachineRequest,
wire::GetMachineRequest,
wire::GetMachineRequest::from,
types::GetMachineRequest::from
);
json!(
types::GetMachineResponse,
wire::GetMachineResponse,
wire::GetMachineResponse::from,
types::GetMachineResponse::from
);
json!(types::Machine, wire::Machine, wire::Machine::from, types::Machine::from);
json!(
types::AlertDestination,
wire::AlertDestination,
wire::AlertDestination::from,
types::AlertDestination::from
);
json!(
types::MachineSession,
wire::MachineSession,
wire::MachineSession::from,
types::MachineSession::from
);
json!(
types::DiskUsage,
wire::DiskUsage,
wire::DiskUsage::from,
types::DiskUsage::from
);
json!(types::SshKey, wire::SshKey, wire::SshKey::from, types::SshKey::from);
json!(
types::GithubConnection,
wire::GithubConnection,
wire::GithubConnection::from,
types::GithubConnection::from
);
json!(
types::GithubRepository,
wire::GithubRepository,
wire::GithubRepository::from,
types::GithubRepository::from
);
json!(
types::DeletedProject,
wire::DeletedProject,
wire::DeletedProject::from,
types::DeletedProject::from
);
json!(
types::RunMachineActionRequest,
wire::RunMachineActionRequest,
wire::RunMachineActionRequest::from,
types::RunMachineActionRequest::from
);
json!(
types::RestartMachineAction,
wire::RestartMachineAction,
wire::RestartMachineAction::from,
types::RestartMachineAction::from
);
json!(
types::RunMachineActionResponse,
wire::RunMachineActionResponse,
wire::RunMachineActionResponse::from,
types::RunMachineActionResponse::from
);
json!(
types::ProjectMetadata,
wire::ProjectMetadata,
wire::ProjectMetadata::from,
types::ProjectMetadata::from
);
json!(
types::ProjectSummary,
wire::ProjectSummary,
wire::ProjectSummary::from,
types::ProjectSummary::from
);
json!(
types::ServiceSummary,
wire::ServiceSummary,
wire::ServiceSummary::from,
types::ServiceSummary::from
);
json!(
types::ProjectProblem,
wire::ProjectProblem,
wire::ProjectProblem::from,
types::ProjectProblem::from
);
json!(
types::GetProjectRequest,
wire::GetProjectRequest,
wire::GetProjectRequest::from,
types::GetProjectRequest::from
);
json!(
types::GetProjectResponse,
wire::GetProjectResponse,
wire::GetProjectResponse::from,
types::GetProjectResponse::from
);
json!(types::Project, wire::Project, wire::Project::from, types::Project::from);
json!(
types::RunningServicesAction,
wire::RunningServicesAction,
wire::RunningServicesAction::from,
types::RunningServicesAction::from
);
json!(
types::ProjectSource,
wire::ProjectSource,
wire::ProjectSource::from,
types::ProjectSource::from
);
json!(
types::GithubSource,
wire::GithubSource,
wire::GithubSource::from,
types::GithubSource::from
);
json!(
types::GithubCommit,
wire::GithubCommit,
wire::GithubCommit::from,
types::GithubCommit::from
);
json!(types::Service, wire::Service, wire::Service::from, types::Service::from);
json!(
types::PublishedPort,
wire::PublishedPort,
wire::PublishedPort::from,
types::PublishedPort::from
);
json!(
types::VolumeMount,
wire::VolumeMount,
wire::VolumeMount::from,
types::VolumeMount::from
);
json!(
types::HealthCheck,
wire::HealthCheck,
wire::HealthCheck::from,
types::HealthCheck::from
);
json!(
types::EnvironmentVariable,
wire::EnvironmentVariable,
wire::EnvironmentVariable::from,
types::EnvironmentVariable::from
);
json!(types::Volume, wire::Volume, wire::Volume::from, types::Volume::from);
json!(
types::VolumeMountedBy,
wire::VolumeMountedBy,
wire::VolumeMountedBy::from,
types::VolumeMountedBy::from
);
json!(types::Host, wire::Host, wire::Host::from, types::Host::from);
json!(types::Route, wire::Route, wire::Route::from, types::Route::from);
json!(
types::Operation,
wire::Operation,
wire::Operation::from,
types::Operation::from
);
json!(
types::Snapshot,
wire::Snapshot,
wire::Snapshot::from,
types::Snapshot::from
);
json!(
types::HttpTrafficSummary,
wire::HttpTrafficSummary,
wire::HttpTrafficSummary::from,
types::HttpTrafficSummary::from
);
json!(
types::CreateProjectRequest,
wire::CreateProjectRequest,
wire::CreateProjectRequest::from,
types::CreateProjectRequest::from
);
json!(
types::CreateProjectResponse,
wire::CreateProjectResponse,
wire::CreateProjectResponse::from,
types::CreateProjectResponse::from
);
json!(
types::DeployProjectRequest,
wire::DeployProjectRequest,
wire::DeployProjectRequest::from,
types::DeployProjectRequest::from
);
json!(
types::MountVolume,
wire::MountVolume,
wire::MountVolume::from,
types::MountVolume::from
);
json!(
types::ProjectExtension,
wire::ProjectExtension,
wire::ProjectExtension::from,
types::ProjectExtension::from
);
json!(
types::FileChange,
wire::FileChange,
wire::FileChange::from,
types::FileChange::from
);
json!(
types::DeployProjectResponse,
wire::DeployProjectResponse,
wire::DeployProjectResponse::from,
types::DeployProjectResponse::from
);
json!(
types::SpecViolation,
wire::SpecViolation,
wire::SpecViolation::from,
types::SpecViolation::from
);
json!(
types::ListCommitsRequest,
wire::ListCommitsRequest,
wire::ListCommitsRequest::from,
types::ListCommitsRequest::from
);
json!(
types::ListCommitsResponse,
wire::ListCommitsResponse,
wire::ListCommitsResponse::from,
types::ListCommitsResponse::from
);
json!(
types::BranchCommit,
wire::BranchCommit,
wire::BranchCommit::from,
types::BranchCommit::from
);
json!(
types::RunProjectActionRequest,
wire::RunProjectActionRequest,
wire::RunProjectActionRequest::from,
types::RunProjectActionRequest::from
);
json!(
types::ServicesAction,
wire::ServicesAction,
wire::ServicesAction::from,
types::ServicesAction::from
);
json!(
types::RecreateServiceAction,
wire::RecreateServiceAction,
wire::RecreateServiceAction::from,
types::RecreateServiceAction::from
);
json!(
types::BackUpAction,
wire::BackUpAction,
wire::BackUpAction::from,
types::BackUpAction::from
);
json!(
types::RestoreSnapshotAction,
wire::RestoreSnapshotAction,
wire::RestoreSnapshotAction::from,
types::RestoreSnapshotAction::from
);
json!(
types::CancelOperationAction,
wire::CancelOperationAction,
wire::CancelOperationAction::from,
types::CancelOperationAction::from
);
json!(
types::DeleteProjectAction,
wire::DeleteProjectAction,
wire::DeleteProjectAction::from,
types::DeleteProjectAction::from
);
json!(
types::RunProjectActionResponse,
wire::RunProjectActionResponse,
wire::RunProjectActionResponse::from,
types::RunProjectActionResponse::from
);
json!(
types::SetProjectAlertsRequest,
wire::SetProjectAlertsRequest,
wire::SetProjectAlertsRequest::from,
types::SetProjectAlertsRequest::from
);
json!(
types::SetProjectAlertsResponse,
wire::SetProjectAlertsResponse,
wire::SetProjectAlertsResponse::from,
types::SetProjectAlertsResponse::from
);
json!(
types::SiteCheck,
wire::SiteCheck,
wire::SiteCheck::from,
types::SiteCheck::from
);
json!(
types::TrafficRule,
wire::TrafficRule,
wire::TrafficRule::from,
types::TrafficRule::from
);
json!(
types::ProjectAlerts,
wire::ProjectAlerts,
wire::ProjectAlerts::from,
types::ProjectAlerts::from
);
json!(
types::SiteCheckState,
wire::SiteCheckState,
wire::SiteCheckState::from,
types::SiteCheckState::from
);
json!(
types::SiteCheckResult,
wire::SiteCheckResult,
wire::SiteCheckResult::from,
types::SiteCheckResult::from
);
json!(
types::TrafficRuleState,
wire::TrafficRuleState,
wire::TrafficRuleState::from,
types::TrafficRuleState::from
);
json!(
types::Incident,
wire::Incident,
wire::Incident::from,
types::Incident::from
);
json!(
types::IncidentEvidence,
wire::IncidentEvidence,
wire::IncidentEvidence::from,
types::IncidentEvidence::from
);
json!(
types::UptimeDay,
wire::UptimeDay,
wire::UptimeDay::from,
types::UptimeDay::from
);
json!(
types::GetOperationRequest,
wire::GetOperationRequest,
wire::GetOperationRequest::from,
types::GetOperationRequest::from
);
json!(
types::GetOperationResponse,
wire::GetOperationResponse,
wire::GetOperationResponse::from,
types::GetOperationResponse::from
);
json!(
types::OperationLogLine,
wire::OperationLogLine,
wire::OperationLogLine::from,
types::OperationLogLine::from
);
json!(
types::HttpTrafficFilter,
wire::HttpTrafficFilter,
wire::HttpTrafficFilter::from,
types::HttpTrafficFilter::from
);
json!(
types::QueryHttpTrafficRequest,
wire::QueryHttpTrafficRequest,
wire::QueryHttpTrafficRequest::from,
types::QueryHttpTrafficRequest::from
);
json!(
types::QueryHttpTrafficResponse,
wire::QueryHttpTrafficResponse,
wire::QueryHttpTrafficResponse::from,
types::QueryHttpTrafficResponse::from
);
json!(
types::HttpTrafficBucket,
wire::HttpTrafficBucket,
wire::HttpTrafficBucket::from,
types::HttpTrafficBucket::from
);
json!(
types::HttpPathTraffic,
wire::HttpPathTraffic,
wire::HttpPathTraffic::from,
types::HttpPathTraffic::from
);
json!(
types::HttpRequest,
wire::HttpRequest,
wire::HttpRequest::from,
types::HttpRequest::from
);
json!(
types::ContainerLogFilter,
wire::ContainerLogFilter,
wire::ContainerLogFilter::from,
types::ContainerLogFilter::from
);
json!(
types::QueryContainerLogsRequest,
wire::QueryContainerLogsRequest,
wire::QueryContainerLogsRequest::from,
types::QueryContainerLogsRequest::from
);
json!(
types::QueryContainerLogsResponse,
wire::QueryContainerLogsResponse,
wire::QueryContainerLogsResponse::from,
types::QueryContainerLogsResponse::from
);
json!(types::LogLine, wire::LogLine, wire::LogLine::from, types::LogLine::from);
json!(
types::RunServiceCommandRequest,
wire::RunServiceCommandRequest,
wire::RunServiceCommandRequest::from,
types::RunServiceCommandRequest::from
);
json!(
types::RunServiceCommandResponse,
wire::RunServiceCommandResponse,
wire::RunServiceCommandResponse::from,
types::RunServiceCommandResponse::from
);
json!(
types::FileEntry,
wire::FileEntry,
wire::FileEntry::from,
types::FileEntry::from
);
json!(
types::ReadPathRequest,
wire::ReadPathRequest,
wire::ReadPathRequest::from,
types::ReadPathRequest::from
);
json!(
types::ReadPathResponse,
wire::ReadPathResponse,
wire::ReadPathResponse::from,
types::ReadPathResponse::from
);
json!(
types::CreateTransferRequest,
wire::CreateTransferRequest,
wire::CreateTransferRequest::from,
types::CreateTransferRequest::from
);
json!(
types::ArchiveUpload,
wire::ArchiveUpload,
wire::ArchiveUpload::from,
types::ArchiveUpload::from
);
json!(
types::FileUpload,
wire::FileUpload,
wire::FileUpload::from,
types::FileUpload::from
);
json!(
types::PathDownload,
wire::PathDownload,
wire::PathDownload::from,
types::PathDownload::from
);
json!(
types::CreateTransferResponse,
wire::CreateTransferResponse,
wire::CreateTransferResponse::from,
types::CreateTransferResponse::from
);
json!(
types::ProjectBusy,
wire::ProjectBusy,
wire::ProjectBusy::from,
types::ProjectBusy::from
);
json!(
types::ProjectChanged,
wire::ProjectChanged,
wire::ProjectChanged::from,
types::ProjectChanged::from
);
json!(
types::MachineUnreachable,
wire::MachineUnreachable,
wire::MachineUnreachable::from,
types::MachineUnreachable::from
);
json!(
types::MachineUpdatePending,
wire::MachineUpdatePending,
wire::MachineUpdatePending::from,
types::MachineUpdatePending::from
);
json!(
types::NoMachine,
wire::NoMachine,
wire::NoMachine::from,
types::NoMachine::from
);
json!(
types::WatchOperationRequest,
wire::WatchOperationRequest,
wire::WatchOperationRequest::from,
types::WatchOperationRequest::from
);
json!(
types::WatchOperationResponse,
wire::WatchOperationResponse,
wire::WatchOperationResponse::from,
types::WatchOperationResponse::from
);
json!(
types::TailContainerLogsRequest,
wire::TailContainerLogsRequest,
wire::TailContainerLogsRequest::from,
types::TailContainerLogsRequest::from
);
json!(
types::TailContainerLogsResponse,
wire::TailContainerLogsResponse,
wire::TailContainerLogsResponse::from,
types::TailContainerLogsResponse::from
);
json!(
types::TailHttpTrafficRequest,
wire::TailHttpTrafficRequest,
wire::TailHttpTrafficRequest::from,
types::TailHttpTrafficRequest::from
);
json!(
types::TailHttpTrafficResponse,
wire::TailHttpTrafficResponse,
wire::TailHttpTrafficResponse::from,
types::TailHttpTrafficResponse::from
);
fn read<'de, Wire: DeserializeOwned, D: Deserializer<'de>>(deserializer: D) -> Result<Wire, D::Error> {
let value = Value::deserialize(deserializer)?;
Wire::deserialize(Strict { value, field: None }).map_err(D::Error::custom)
}
struct Strict {
value: Value,
field: Option<String>,
}
impl Strict {
fn item(value: Value) -> Self {
Self { value, field: None }
}
fn of_field((field, value): (String, Value)) -> (String, Self) {
let named = Self {
value,
field: Some(field.clone()),
};
(field, named)
}
}
impl<'de> IntoDeserializer<'de, serde_json::Error> for Strict {
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de> Deserializer<'de> for Strict {
type Error = serde_json::Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
match self.value {
Value::Array(items) => {
let mut items = SeqDeserializer::<_, Self::Error>::new(items.into_iter().map(Self::item));
let read = visitor.visit_seq(&mut items)?;
items.end()?;
Ok(read)
}
Value::Object(fields) => {
let mut fields = MapDeserializer::<_, Self::Error>::new(fields.into_iter().map(Self::of_field));
let read = visitor.visit_map(&mut fields)?;
fields.end()?;
Ok(read)
}
scalar => scalar.deserialize_any(visitor),
}
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
match self.value {
Value::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_newtype_struct<V: Visitor<'de>>(self, _: &'static str, visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_newtype_struct(self)
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_: &'static str,
_: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error> {
match self.value {
Value::Array(_) => Err(Self::Error::invalid_type(Unexpected::Seq, &visitor)),
_ => self.deserialize_any(visitor),
}
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, _: V) -> Result<V::Value, Self::Error> {
let field = self.field.unwrap_or_default();
Err(Self::Error::custom(format_args!("unknown field `{field}`")))
}
serde::forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf unit
unit_struct seq tuple tuple_struct map enum identifier
}
}