#![doc = "Generated transport-independent contract objects."]
use std::collections::BTreeMap;
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use spiral_contract::error::{ErrorEnvelope, ServiceError};
use spiral_contract::safelong::{SafeLong, SafeUnsignedLong};
use spiral_contract::strict::{DeserializeStrict, Strict};
use uuid::Uuid;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArborScanUsage {
#[serde(rename = "filesConsidered")]
pub files_considered: SafeUnsignedLong,
#[serde(rename = "filesPruned")]
pub files_pruned: SafeUnsignedLong,
#[serde(rename = "finished")]
pub finished: bool,
#[serde(rename = "fragmentsConsidered")]
pub fragments_considered: SafeUnsignedLong,
#[serde(rename = "fragmentsPruned")]
pub fragments_pruned: SafeUnsignedLong,
#[serde(rename = "outputRows")]
pub output_rows: SafeUnsignedLong,
#[serde(rename = "storage")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub storage: Option<StorageReads>,
}
impl<'de> DeserializeStrict<'de> for ArborScanUsage {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "filesConsidered")]
files_considered: Strict<SafeUnsignedLong>,
#[serde(rename = "filesPruned")]
files_pruned: Strict<SafeUnsignedLong>,
#[serde(rename = "finished")]
finished: Strict<bool>,
#[serde(rename = "fragmentsConsidered")]
fragments_considered: Strict<SafeUnsignedLong>,
#[serde(rename = "fragmentsPruned")]
fragments_pruned: Strict<SafeUnsignedLong>,
#[serde(rename = "outputRows")]
output_rows: Strict<SafeUnsignedLong>,
#[serde(rename = "storage")]
#[serde(default)]
storage: Strict<Option<StorageReads>>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
files_considered: wire.files_considered.0,
files_pruned: wire.files_pruned.0,
finished: wire.finished.0,
fragments_considered: wire.fragments_considered.0,
fragments_pruned: wire.fragments_pruned.0,
output_rows: wire.output_rows.0,
storage: wire.storage.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ProjectId(pub String);
impl std::fmt::Display for ProjectId {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(formatter)
}
}
impl<'de> DeserializeStrict<'de> for ProjectId {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(Self(Strict::<String>::deserialize(deserializer)?.0))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReportUsageRecordsRequest {
#[serde(rename = "records")]
pub records: Vec<UsageRecord>,
}
impl<'de> DeserializeStrict<'de> for ReportUsageRecordsRequest {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "records")]
records: Strict<Vec<UsageRecord>>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
records: wire.records.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReportUsageRequest {
#[serde(rename = "events")]
pub events: Vec<UsageEvent>,
#[serde(rename = "projectId")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub project_id: Option<String>,
#[serde(rename = "tableId")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub table_id: Option<String>,
}
impl<'de> DeserializeStrict<'de> for ReportUsageRequest {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "events")]
events: Strict<Vec<UsageEvent>>,
#[serde(rename = "projectId")]
#[serde(default)]
project_id: Strict<Option<String>>,
#[serde(rename = "tableId")]
#[serde(default)]
table_id: Strict<Option<String>>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
events: wire.events.0,
project_id: wire.project_id.0,
table_id: wire.table_id.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StorageReadScope {
Complete,
Direct,
Unknown(String),
}
impl Serialize for StorageReadScope {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(match self {
Self::Complete => "complete",
Self::Direct => "direct",
Self::Unknown(value) => value,
})
}
}
impl<'de> Deserialize<'de> for StorageReadScope {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(match String::deserialize(deserializer)?.as_str() {
"complete" => Self::Complete,
"direct" => Self::Direct,
value => Self::Unknown(value.to_owned()),
})
}
}
impl<'de> DeserializeStrict<'de> for StorageReadScope {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
enum __Known {
#[serde(rename = "complete")]
Complete,
#[serde(rename = "direct")]
Direct,
}
Ok(match __Known::deserialize(deserializer)? {
__Known::Complete => Self::Complete,
__Known::Direct => Self::Direct,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct StorageReads {
#[serde(rename = "bytes")]
pub bytes: SafeUnsignedLong,
#[serde(rename = "readTimeNs")]
pub read_time_ns: SafeUnsignedLong,
#[serde(rename = "requests")]
pub requests: SafeUnsignedLong,
#[serde(rename = "scope")]
pub scope: StorageReadScope,
}
impl<'de> DeserializeStrict<'de> for StorageReads {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "bytes")]
bytes: Strict<SafeUnsignedLong>,
#[serde(rename = "readTimeNs")]
read_time_ns: Strict<SafeUnsignedLong>,
#[serde(rename = "requests")]
requests: Strict<SafeUnsignedLong>,
#[serde(rename = "scope")]
scope: Strict<StorageReadScope>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
bytes: wire.bytes.0,
read_time_ns: wire.read_time_ns.0,
requests: wire.requests.0,
scope: wire.scope.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct UsageEvent {
#[serde(rename = "eventType")]
pub event_type: String,
#[serde(rename = "properties")]
pub properties: BTreeMap<String, Value>,
}
impl<'de> DeserializeStrict<'de> for UsageEvent {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "eventType")]
event_type: Strict<String>,
#[serde(rename = "properties")]
properties: Strict<BTreeMap<String, Value>>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
event_type: wire.event_type.0,
properties: wire.properties.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UsageMeasurement {
ArborScanV1(ArborScanUsage),
Unknown { tag: String, value: Value },
}
impl Serialize for UsageMeasurement {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::ArborScanV1(value) => {
let mut object = serde_json::Map::new();
object.insert("type".into(), Value::String("arborScanV1".into()));
object.insert(
"arborScanV1".into(),
serde_json::to_value(value).map_err(serde::ser::Error::custom)?,
);
Value::Object(object).serialize(serializer)
}
Self::Unknown { tag, value } => {
if value.get("type").and_then(Value::as_str) != Some(tag.as_str()) {
return Err(serde::ser::Error::custom(
"unknown union discriminator mismatch",
));
}
value.serialize(serializer)
}
}
}
}
impl<'de> Deserialize<'de> for UsageMeasurement {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = Value::deserialize(deserializer)?;
let tag = value
.get("type")
.and_then(Value::as_str)
.ok_or_else(|| serde::de::Error::custom("union requires type"))?;
match tag {
"arborScanV1" => Ok(Self::ArborScanV1(
serde_json::from_value(
value
.get("arborScanV1")
.cloned()
.ok_or_else(|| serde::de::Error::custom("union requires matching arm"))?,
)
.map_err(serde::de::Error::custom)?,
)),
tag => Ok(Self::Unknown {
tag: tag.to_owned(),
value,
}),
}
}
}
impl<'de> DeserializeStrict<'de> for UsageMeasurement {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
enum __Tag0 {
#[serde(rename = "arborScanV1")]
Value,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Arm0 {
#[serde(rename = "type")]
_tag: __Tag0,
#[serde(rename = "arborScanV1")]
value: Strict<ArborScanUsage>,
}
#[derive(Deserialize)]
#[serde(untagged)]
enum __Known {
ArborScanV1(Box<__Arm0>),
}
Ok(match __Known::deserialize(deserializer)? {
__Known::ArborScanV1(arm) => Self::ArborScanV1(arm.value.0),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct UsageRecord {
#[serde(rename = "emitterVersion")]
pub emitter_version: String,
#[serde(rename = "id")]
pub id: Uuid,
#[serde(rename = "measurement")]
pub measurement: UsageMeasurement,
#[serde(rename = "occurredAtMicros")]
pub occurred_at_micros: SafeLong,
#[serde(rename = "resourceId")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resource_id: Option<Uuid>,
#[serde(rename = "source")]
pub source: String,
#[serde(rename = "versionId")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version_id: Option<Uuid>,
}
impl<'de> DeserializeStrict<'de> for UsageRecord {
fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct __Wire {
#[serde(rename = "emitterVersion")]
emitter_version: Strict<String>,
#[serde(rename = "id")]
id: Strict<Uuid>,
#[serde(rename = "measurement")]
measurement: Strict<UsageMeasurement>,
#[serde(rename = "occurredAtMicros")]
occurred_at_micros: Strict<SafeLong>,
#[serde(rename = "resourceId")]
#[serde(default)]
resource_id: Strict<Option<Uuid>>,
#[serde(rename = "source")]
source: Strict<String>,
#[serde(rename = "versionId")]
#[serde(default)]
version_id: Strict<Option<Uuid>>,
}
let wire = __Wire::deserialize(deserializer)?;
Ok(Self {
emitter_version: wire.emitter_version.0,
id: wire.id.0,
measurement: wire.measurement.0,
occurred_at_micros: wire.occurred_at_micros.0,
resource_id: wire.resource_id.0,
source: wire.source.0,
version_id: wire.version_id.0,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UsageError {
Conflict { reason: String },
InvalidArgument { reason: String },
NotFound { resource: String },
}
impl UsageError {
pub fn status(&self) -> u16 {
match self {
Self::Conflict { .. } => 409,
Self::InvalidArgument { .. } => 400,
Self::NotFound { .. } => 404,
}
}
pub fn envelope(&self, instance: String) -> ErrorEnvelope {
match self {
Self::Conflict { reason } => {
let mut envelope = ErrorEnvelope::new("CONFLICT", "Usage:Conflict", instance);
envelope
.parameters
.insert("reason".into(), reason.to_string());
envelope
}
Self::InvalidArgument { reason } => {
let mut envelope =
ErrorEnvelope::new("INVALID_ARGUMENT", "Usage:InvalidArgument", instance);
envelope
.parameters
.insert("reason".into(), reason.to_string());
envelope
}
Self::NotFound { resource } => {
let mut envelope = ErrorEnvelope::new("NOT_FOUND", "Usage:NotFound", instance);
envelope
.parameters
.insert("resource".into(), resource.to_string());
envelope
}
}
}
pub fn decode_envelope(envelope: &ErrorEnvelope) -> Option<Self> {
if envelope.error_instance_id.len() != 36
|| Uuid::parse_str(&envelope.error_instance_id).is_err()
{
return None;
}
match envelope.error_name.as_str() {
"Usage:Conflict" => {
if envelope.error_code != "CONFLICT" {
return None;
}
let reason = envelope.parameters.get("reason")?.clone();
Some(Self::Conflict { reason })
}
"Usage:InvalidArgument" => {
if envelope.error_code != "INVALID_ARGUMENT" {
return None;
}
let reason = envelope.parameters.get("reason")?.clone();
Some(Self::InvalidArgument { reason })
}
"Usage:NotFound" => {
if envelope.error_code != "NOT_FOUND" {
return None;
}
let resource = envelope.parameters.get("resource")?.clone();
Some(Self::NotFound { resource })
}
_ => None,
}
}
}
impl Display for UsageError {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Conflict { reason } => write!(formatter, "Usage:Conflict (reason: {})", reason),
Self::InvalidArgument { reason } => {
write!(formatter, "Usage:InvalidArgument (reason: {})", reason)
}
Self::NotFound { resource } => {
write!(formatter, "Usage:NotFound (resource: {})", resource)
}
}
}
}
impl StdError for UsageError {}
impl ServiceError for UsageError {
fn to_envelope(&self, instance: String) -> ErrorEnvelope {
Self::envelope(self, instance)
}
fn from_envelope(envelope: &ErrorEnvelope) -> Option<Self> {
Self::decode_envelope(envelope)
}
}