spiral-sdk 0.1.11

Rust SDK for Spiral resource and table APIs
Documentation
// Generated by tools/service-contracts/rust.py. Do not edit.
#![doc = "Generated transport-independent contract objects."]

use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};

use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use spiral_contract::error::{ErrorEnvelope, ServiceError};
use spiral_contract::strict::{DeserializeStrict, Strict};
use uuid::Uuid;

/// Create using the Organization storage default and optional Volume. A prefix has at most 25
/// lowercase ASCII letters, digits or hyphens.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateProjectRequest {
    /// Contract field description.
    #[serde(rename = "description")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// Contract field idPrefix.
    #[serde(rename = "idPrefix")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub id_prefix: Option<String>,
    /// Contract field volumeId.
    #[serde(rename = "volumeId")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub volume_id: Option<String>,
}
impl<'de> DeserializeStrict<'de> for CreateProjectRequest {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "description")]
            #[serde(default)]
            description: Strict<Option<String>>,
            #[serde(rename = "idPrefix")]
            #[serde(default)]
            id_prefix: Strict<Option<String>>,
            #[serde(rename = "volumeId")]
            #[serde(default)]
            volume_id: Strict<Option<String>>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            description: wire.description.0,
            id_prefix: wire.id_prefix.0,
            volume_id: wire.volume_id.0,
        })
    }
}

/// The created Project. Creation also provisions storage, grants and the Catalog.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateProjectResponse {
    /// Contract field project.
    #[serde(rename = "project")]
    pub project: Project,
}
impl<'de> DeserializeStrict<'de> for CreateProjectResponse {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "project")]
            project: Strict<Project>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            project: wire.project.0,
        })
    }
}

/// Live continuation request. Page size defaults to 100 and must be 1..=1000. Tokens expire after
/// one hour and are bound to the credential, operation, filters and page size.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ListProjectsRequest {
    /// Contract field pageSize.
    #[serde(rename = "pageSize")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub page_size: Option<u32>,
    /// Contract field pageToken.
    #[serde(rename = "pageToken")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub page_token: Option<String>,
}
impl<'de> DeserializeStrict<'de> for ListProjectsRequest {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "pageSize")]
            #[serde(default)]
            page_size: Strict<Option<u32>>,
            #[serde(rename = "pageToken")]
            #[serde(default)]
            page_token: Strict<Option<String>>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            page_size: wire.page_size.0,
            page_token: wire.page_token.0,
        })
    }
}

/// The saved revision and document, or revision zero and no document when absent.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Presentation {
    /// Contract field revision.
    #[serde(rename = "revision")]
    pub revision: i32,
    /// Contract field value.
    #[serde(rename = "value")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub value: Option<Value>,
}
impl<'de> DeserializeStrict<'de> for Presentation {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "revision")]
            revision: Strict<i32>,
            #[serde(rename = "value")]
            #[serde(default)]
            value: Strict<Option<Value>>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            revision: wire.revision.0,
            value: wire.value.0,
        })
    }
}

/// A 64-character hexadecimal key for shared presentation state.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PresentationKey {
    /// Contract field key.
    #[serde(rename = "key")]
    pub key: String,
}
impl<'de> DeserializeStrict<'de> for PresentationKey {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "key")]
            key: Strict<String>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self { key: wire.key.0 })
    }
}

/// Project identity, owning Organization and optional description.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Project {
    /// Contract field description.
    #[serde(rename = "description")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    /// Contract field id.
    #[serde(rename = "id")]
    pub id: String,
    /// Contract field organizationId.
    #[serde(rename = "organizationId")]
    pub organization_id: String,
}
impl<'de> DeserializeStrict<'de> for Project {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "description")]
            #[serde(default)]
            description: Strict<Option<String>>,
            #[serde(rename = "id")]
            id: Strict<String>,
            #[serde(rename = "organizationId")]
            organization_id: Strict<String>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            description: wire.description.0,
            id: wire.id.0,
            organization_id: wire.organization_id.0,
        })
    }
}

/// Accessible Projects in ascending ID order. This is a live listing: changes behind the cursor
/// require a new traversal.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProjectPage {
    /// Contract field items.
    #[serde(rename = "items")]
    pub items: Vec<Project>,
    /// Contract field nextPageToken.
    #[serde(rename = "nextPageToken")]
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub next_page_token: Option<String>,
}
impl<'de> DeserializeStrict<'de> for ProjectPage {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "items")]
            items: Strict<Vec<Project>>,
            #[serde(rename = "nextPageToken")]
            #[serde(default)]
            next_page_token: Strict<Option<String>>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            items: wire.items.0,
            next_page_token: wire.next_page_token.0,
        })
    }
}

/// Compare-and-swap one presentation. Revision zero creates it; value must be a JSON object of at
/// most one MiB.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct SavePresentation {
    /// Contract field key.
    #[serde(rename = "key")]
    pub key: String,
    /// Contract field revision.
    #[serde(rename = "revision")]
    pub revision: i32,
    /// Contract field value.
    #[serde(rename = "value")]
    pub value: Value,
}
impl<'de> DeserializeStrict<'de> for SavePresentation {
    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct __Wire {
            #[serde(rename = "key")]
            key: Strict<String>,
            #[serde(rename = "revision")]
            revision: Strict<i32>,
            #[serde(rename = "value")]
            value: Strict<Value>,
        }
        let wire = __Wire::deserialize(deserializer)?;
        Ok(Self {
            key: wire.key.0,
            revision: wire.revision.0,
            value: wire.value.0,
        })
    }
}

/// Typed errors declared by this service contract.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ProjectError {
    /// Project:Conflict.
    Conflict { reason: String },
    /// Project:InvalidArgument.
    InvalidArgument { reason: String },
    /// Project:LimitReached.
    LimitReached { reason: String },
    /// Project:NotFound.
    NotFound { resource: String },
}
impl ProjectError {
    /// HTTP status for this declared error.
    pub fn status(&self) -> u16 {
        match self {
            Self::Conflict { .. } => 409,
            Self::InvalidArgument { .. } => 400,
            Self::LimitReached { .. } => 412,
            Self::NotFound { .. } => 404,
        }
    }
    /// Serialize only contract-declared error parameters.
    pub fn envelope(&self, instance: String) -> ErrorEnvelope {
        match self {
            Self::Conflict { reason } => {
                let mut envelope = ErrorEnvelope::new("CONFLICT", "Project:Conflict", instance);
                envelope
                    .parameters
                    .insert("reason".into(), reason.to_string());
                envelope
            }
            Self::InvalidArgument { reason } => {
                let mut envelope =
                    ErrorEnvelope::new("INVALID_ARGUMENT", "Project:InvalidArgument", instance);
                envelope
                    .parameters
                    .insert("reason".into(), reason.to_string());
                envelope
            }
            Self::LimitReached { reason } => {
                let mut envelope =
                    ErrorEnvelope::new("FAILED_PRECONDITION", "Project:LimitReached", instance);
                envelope
                    .parameters
                    .insert("reason".into(), reason.to_string());
                envelope
            }
            Self::NotFound { resource } => {
                let mut envelope = ErrorEnvelope::new("NOT_FOUND", "Project:NotFound", instance);
                envelope
                    .parameters
                    .insert("resource".into(), resource.to_string());
                envelope
            }
        }
    }
    /// Decode a declared error and its typed error parameters.
    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() {
            "Project:Conflict" => {
                if envelope.error_code != "CONFLICT" {
                    return None;
                }
                let reason = envelope.parameters.get("reason")?.clone();
                Some(Self::Conflict { reason })
            }
            "Project:InvalidArgument" => {
                if envelope.error_code != "INVALID_ARGUMENT" {
                    return None;
                }
                let reason = envelope.parameters.get("reason")?.clone();
                Some(Self::InvalidArgument { reason })
            }
            "Project:LimitReached" => {
                if envelope.error_code != "FAILED_PRECONDITION" {
                    return None;
                }
                let reason = envelope.parameters.get("reason")?.clone();
                Some(Self::LimitReached { reason })
            }
            "Project:NotFound" => {
                if envelope.error_code != "NOT_FOUND" {
                    return None;
                }
                let resource = envelope.parameters.get("resource")?.clone();
                Some(Self::NotFound { resource })
            }
            _ => None,
        }
    }
}
impl Display for ProjectError {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Conflict { reason } => write!(formatter, "Project:Conflict (reason: {})", reason),
            Self::InvalidArgument { reason } => {
                write!(formatter, "Project:InvalidArgument (reason: {})", reason)
            }
            Self::LimitReached { reason } => {
                write!(formatter, "Project:LimitReached (reason: {})", reason)
            }
            Self::NotFound { resource } => {
                write!(formatter, "Project:NotFound (resource: {})", resource)
            }
        }
    }
}
impl StdError for ProjectError {}
impl ServiceError for ProjectError {
    fn to_envelope(&self, instance: String) -> ErrorEnvelope {
        Self::envelope(self, instance)
    }
    fn from_envelope(envelope: &ErrorEnvelope) -> Option<Self> {
        Self::decode_envelope(envelope)
    }
}
#[automatically_derived]
impl Default for CreateProjectRequest {
    fn default() -> Self {
        Self {
            description: None,
            id_prefix: None,
            volume_id: None,
        }
    }
}
#[automatically_derived]
impl Default for ListProjectsRequest {
    fn default() -> Self {
        Self {
            page_size: None,
            page_token: None,
        }
    }
}