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 #[cfg_attr(feature = "utoipa", param(value_type = String, default = "", required = false))]
18 pub prefix: Option<BasinNamePrefix>,
19 #[cfg_attr(feature = "utoipa", param(value_type = String, default = "", required = false))]
22 pub start_after: Option<BasinNameStartAfter>,
23 #[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 #[cfg_attr(feature = "utoipa", schema(max_items = 1000))]
40 pub basins: Vec<BasinInfo>,
41 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 pub name: BasinName,
51 pub location: Option<LocationName>,
53 #[serde(with = "time::serde::rfc3339")]
55 pub created_at: OffsetDateTime,
56 #[serde(default, with = "time::serde::rfc3339::option")]
58 pub deleted_at: Option<OffsetDateTime>,
59 #[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 Active,
131 Deleting,
133}
134
135#[rustfmt::skip]
136#[derive(Debug, Clone, Serialize, Deserialize)]
137#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
138pub struct EnsureBasinRequest {
139 pub config: Option<BasinConfig>,
141 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 pub basin: BasinName,
155 pub config: Option<BasinConfig>,
157 pub location: Option<LocationName>,
160}