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