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))]
21 pub start_after: Option<BasinNameStartAfter>,
22 #[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 #[cfg_attr(feature = "utoipa", schema(max_items = 1000))]
39 pub basins: Vec<BasinInfo>,
40 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 pub name: BasinName,
50 pub location: Option<LocationName>,
52 #[serde(with = "time::serde::rfc3339")]
54 pub created_at: OffsetDateTime,
55 #[serde(default, with = "time::serde::rfc3339::option")]
57 pub deleted_at: Option<OffsetDateTime>,
58 #[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 Active,
130 Deleting,
132}
133
134#[rustfmt::skip]
135#[derive(Debug, Clone, Serialize, Deserialize)]
136#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
137pub struct EnsureBasinRequest {
138 pub config: Option<BasinConfig>,
140 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 pub basin: BasinName,
154 pub config: Option<BasinConfig>,
156 pub location: Option<LocationName>,
159}