Skip to main content

s2_api/v1/
basin.rs

1use s2_common::types::{
2    self,
3    basin::{BasinName, BasinNamePrefix, BasinNameStartAfter},
4    location::LocationName,
5};
6use serde::{Deserialize, Serialize};
7use time::OffsetDateTime;
8
9use super::config::BasinConfig;
10
11#[rustfmt::skip]
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[cfg_attr(feature = "utoipa", derive(utoipa::IntoParams))]
14#[cfg_attr(feature = "utoipa", into_params(parameter_in = Query))]
15pub struct ListBasinsRequest {
16    /// Filter to basins whose names begin with this prefix.
17    #[cfg_attr(feature = "utoipa", param(value_type = String, default = "", required = false))]
18    pub prefix: Option<BasinNamePrefix>,
19    /// Filter to basins whose names lexicographically start after this string.
20    /// It must be greater than or equal to the `prefix` if specified.
21    #[cfg_attr(feature = "utoipa", param(value_type = String, default = "", required = false))]
22    pub start_after: Option<BasinNameStartAfter>,
23    /// Number of results, up to a maximum of 1000.
24    #[cfg_attr(feature = "utoipa", param(value_type = usize, maximum = 1000, default = 1000, required = false))]
25    pub limit: Option<usize>,
26}
27
28super::impl_list_request_conversions!(
29    ListBasinsRequest,
30    types::basin::BasinNamePrefix,
31    types::basin::BasinNameStartAfter
32);
33
34#[rustfmt::skip]
35#[derive(Debug, Clone, Serialize, Deserialize)]
36#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
37pub struct ListBasinsResponse {
38    /// Matching basins.
39    #[cfg_attr(feature = "utoipa", schema(max_items = 1000))]
40    pub basins: Vec<BasinInfo>,
41    /// Indicates that there are more basins that match the criteria.
42    pub has_more: bool,
43}
44
45#[rustfmt::skip]
46#[derive(Debug, Clone, Serialize)]
47#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
48pub struct BasinInfo {
49    /// Basin name.
50    pub name: BasinName,
51    /// Basin location.
52    pub location: Option<LocationName>,
53    /// Creation time in RFC 3339 format.
54    #[serde(with = "time::serde::rfc3339")]
55    pub created_at: OffsetDateTime,
56    /// Deletion time in RFC 3339 format, if the basin is being deleted.
57    #[serde(default, with = "time::serde::rfc3339::option")]
58    pub deleted_at: Option<OffsetDateTime>,
59    /// Deprecated basin state inferred from `deleted_at`.
60    #[cfg_attr(feature = "utoipa", schema(ignore))]
61    pub state: BasinState,
62}
63
64impl From<types::basin::BasinInfo> for BasinInfo {
65    fn from(value: types::basin::BasinInfo) -> Self {
66        let types::basin::BasinInfo {
67            name,
68            location,
69            created_at,
70            deleted_at,
71        } = value;
72
73        Self {
74            name,
75            location,
76            created_at,
77            deleted_at,
78            state: basin_state_for_deleted_at(deleted_at.as_ref()),
79        }
80    }
81}
82
83fn basin_state_for_deleted_at(deleted_at: Option<&OffsetDateTime>) -> BasinState {
84    if deleted_at.is_some() {
85        BasinState::Deleting
86    } else {
87        BasinState::Active
88    }
89}
90
91#[derive(Deserialize)]
92struct BasinInfoSerde {
93    name: BasinName,
94    location: Option<LocationName>,
95    #[serde(with = "time::serde::rfc3339")]
96    created_at: OffsetDateTime,
97    #[serde(default, with = "time::serde::rfc3339::option")]
98    deleted_at: Option<OffsetDateTime>,
99}
100
101impl<'de> Deserialize<'de> for BasinInfo {
102    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103    where
104        D: serde::Deserializer<'de>,
105    {
106        let BasinInfoSerde {
107            name,
108            location,
109            created_at,
110            deleted_at,
111        } = BasinInfoSerde::deserialize(deserializer)?;
112        let state = basin_state_for_deleted_at(deleted_at.as_ref());
113
114        Ok(Self {
115            name,
116            location,
117            created_at,
118            deleted_at,
119            state,
120        })
121    }
122}
123
124#[rustfmt::skip]
125#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
126#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
127#[serde(rename_all = "kebab-case")]
128pub enum BasinState {
129    /// Basin is active.
130    Active,
131    /// Basin is being deleted.
132    Deleting,
133}
134
135#[rustfmt::skip]
136#[derive(Debug, Clone, Serialize, Deserialize)]
137#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
138pub struct EnsureBasinRequest {
139    /// Basin configuration.
140    pub config: Option<BasinConfig>,
141    /// Basin location.
142    /// If omitted when creating, uses the default location for the account.
143    /// This cannot be changed.
144    pub location: Option<LocationName>,
145}
146
147#[rustfmt::skip]
148#[derive(Debug, Clone, Serialize, Deserialize)]
149#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
150pub struct CreateBasinRequest {
151    /// Basin name which must be globally unique.
152    /// It can be between 8 and 48 bytes in length, and comprise lowercase letters, numbers and hyphens.
153    /// It cannot begin or end with a hyphen.
154    pub basin: BasinName,
155    /// Basin configuration.
156    pub config: Option<BasinConfig>,
157    /// Basin location.
158    /// If omitted when creating, uses the default location for the account.
159    pub location: Option<LocationName>,
160}