diff --git a/api/src/v1/access.rs b/api/src/v1/access.rs index 7b5ca189..2269eb43 100644 --- a/api/src/v1/access.rs +++ b/api/src/v1/access.rs @@ -163,8 +163,9 @@ pub struct AccessTokenInfo { pub expires_at: Option, /// Namespace streams based on the configured stream-level scope, which must be a prefix. /// Stream name arguments will be automatically prefixed, and the prefix will be stripped when listing streams. - #[cfg_attr(feature = "utoipa", schema(value_type = bool, default = false, required = false))] - pub auto_prefix_streams: Option, + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] + pub auto_prefix_streams: bool, /// Access token scope. pub scope: AccessTokenScope, } @@ -176,7 +177,7 @@ impl TryFrom for types::access::IssueAccessTokenRequest { Ok(Self { id: value.id, expires_at: value.expires_at, - auto_prefix_streams: value.auto_prefix_streams.unwrap_or_default(), + auto_prefix_streams: value.auto_prefix_streams, scope: value.scope.try_into()?, }) } @@ -187,7 +188,7 @@ impl From for AccessTokenInfo { Self { id: value.id, expires_at: Some(value.expires_at), - auto_prefix_streams: Some(value.auto_prefix_streams), + auto_prefix_streams: value.auto_prefix_streams, scope: value.scope.into(), } } @@ -198,7 +199,7 @@ impl From for AccessTokenInfo { Self { id: value.id, expires_at: value.expires_at, - auto_prefix_streams: Some(value.auto_prefix_streams), + auto_prefix_streams: value.auto_prefix_streams, scope: value.scope.into(), } } @@ -352,21 +353,20 @@ impl From for PermittedOperationGroups #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct ReadWritePermissions { /// Read permission. - #[cfg_attr(feature = "utoipa", schema(value_type = bool, default = false, required = false))] - pub read: Option, + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] + pub read: bool, /// Write permission. - #[cfg_attr(feature = "utoipa", schema(value_type = bool, default = false, required = false))] - pub write: Option, + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] + pub write: bool, } impl From for types::access::ReadWritePermissions { fn from(value: ReadWritePermissions) -> Self { let ReadWritePermissions { read, write } = value; - Self { - read: read.unwrap_or_default(), - write: write.unwrap_or_default(), - } + Self { read, write } } } @@ -374,10 +374,7 @@ impl From for ReadWritePermissions { fn from(value: types::access::ReadWritePermissions) -> Self { let types::access::ReadWritePermissions { read, write } = value; - Self { - read: Some(read), - write: Some(write), - } + Self { read, write } } } diff --git a/api/src/v1/config.rs b/api/src/v1/config.rs index 3eeeadf6..004e9211 100644 --- a/api/src/v1/config.rs +++ b/api/src/v1/config.rs @@ -113,15 +113,17 @@ pub struct TimestampingConfig { /// Timestamping mode for appends that influences how timestamps are handled. pub mode: Option, /// Allow client-specified timestamps to exceed the arrival time. - /// If this is `false` or not set, client timestamps will be capped at the arrival time. - pub uncapped: Option, + /// If this is `false`, client timestamps will be capped at the arrival time. + #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] + pub uncapped: bool, } impl TimestampingConfig { pub fn to_opt(config: types::config::OptionalTimestampingConfig) -> Option { let config = TimestampingConfig { mode: config.mode.map(Into::into), - uncapped: config.uncapped, + uncapped: config.uncapped.unwrap_or_default(), }; if config == Self::default() { None @@ -135,7 +137,7 @@ impl From for TimestampingConfig { fn from(value: types::config::TimestampingConfig) -> Self { Self { mode: Some(value.mode.into()), - uncapped: Some(value.uncapped), + uncapped: value.uncapped, } } } @@ -144,7 +146,7 @@ impl From for types::config::OptionalTimestampingConfig { fn from(value: TimestampingConfig) -> Self { Self { mode: value.mode.map(Into::into), - uncapped: value.uncapped, + uncapped: Some(value.uncapped), } } } @@ -160,14 +162,14 @@ pub struct TimestampingReconfiguration { /// Allow client-specified timestamps to exceed the arrival time. #[serde(default, skip_serializing_if = "Maybe::is_unspecified")] #[cfg_attr(feature = "utoipa", schema(value_type = Option))] - pub uncapped: Maybe>, + pub uncapped: Maybe, } impl From for types::config::TimestampingReconfiguration { fn from(value: TimestampingReconfiguration) -> Self { Self { mode: value.mode.map_opt(Into::into), - uncapped: value.uncapped, + uncapped: value.uncapped.map(Some), } } } @@ -176,7 +178,7 @@ impl From for TimestampingReconfigur fn from(value: types::config::TimestampingReconfiguration) -> Self { Self { mode: value.mode.map_opt(Into::into), - uncapped: value.uncapped, + uncapped: value.uncapped.map(|v| v.unwrap_or_default()), } } } @@ -406,9 +408,11 @@ pub struct BasinConfig { pub default_stream_config: Option, /// Create stream on append if it doesn't exist, using the default stream configuration. #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] pub create_stream_on_append: bool, /// Create stream on read if it doesn't exist, using the default stream configuration. #[serde(default)] + #[cfg_attr(feature = "utoipa", schema(default = false))] pub create_stream_on_read: bool, } @@ -527,10 +531,7 @@ mod tests { } fn gen_timestamping_config() -> impl Strategy { - ( - proptest::option::of(gen_timestamping_mode()), - proptest::option::of(any::()), - ) + (proptest::option::of(gen_timestamping_mode()), any::()) .prop_map(|(mode, uncapped)| TimestampingConfig { mode, uncapped }) } @@ -602,7 +603,13 @@ mod tests { } fn gen_timestamping_reconfiguration() -> impl Strategy { - (gen_maybe(gen_timestamping_mode()), gen_maybe(any::())) + ( + gen_maybe(gen_timestamping_mode()), + prop_oneof![ + Just(Maybe::Unspecified), + any::().prop_map(Maybe::Specified), + ], + ) .prop_map(|(mode, uncapped)| TimestampingReconfiguration { mode, uncapped }) } diff --git a/sdk/src/types.rs b/sdk/src/types.rs index aaa41a36..d5e38001 100644 --- a/sdk/src/types.rs +++ b/sdk/src/types.rs @@ -632,7 +632,7 @@ impl From for TimestampingConfig { fn from(value: api::config::TimestampingConfig) -> Self { Self { mode: value.mode.map(Into::into), - uncapped: value.uncapped.unwrap_or_default(), + uncapped: value.uncapped, } } } @@ -641,7 +641,7 @@ impl From for api::config::TimestampingConfig { fn from(value: TimestampingConfig) -> Self { Self { mode: value.mode.map(Into::into), - uncapped: Some(value.uncapped), + uncapped: value.uncapped, } } } @@ -1105,7 +1105,7 @@ pub struct TimestampingReconfiguration { /// Override for the existing [`mode`](TimestampingConfig::mode). pub mode: Maybe>, /// Override for the existing [`uncapped`](TimestampingConfig::uncapped) setting. - pub uncapped: Maybe>, + pub uncapped: Maybe, } impl TimestampingReconfiguration { @@ -1125,7 +1125,7 @@ impl TimestampingReconfiguration { /// Set the override for the existing [`uncapped`](TimestampingConfig::uncapped). pub fn with_uncapped(self, uncapped: bool) -> Self { Self { - uncapped: Maybe::Specified(Some(uncapped)), + uncapped: Maybe::Specified(uncapped), ..self } } @@ -1430,7 +1430,7 @@ impl TryFrom for AccessTokenInfo { Ok(Self { id: value.id, expires_at, - auto_prefix_streams: value.auto_prefix_streams.unwrap_or(false), + auto_prefix_streams: value.auto_prefix_streams, scope: value.scope.into(), }) } @@ -1523,8 +1523,8 @@ impl ReadWritePermissions { impl From for api::access::ReadWritePermissions { fn from(value: ReadWritePermissions) -> Self { Self { - read: Some(value.read), - write: Some(value.write), + read: value.read, + write: value.write, } } } @@ -1532,8 +1532,8 @@ impl From for api::access::ReadWritePermissions { impl From for ReadWritePermissions { fn from(value: api::access::ReadWritePermissions) -> Self { Self { - read: value.read.unwrap_or_default(), - write: value.write.unwrap_or_default(), + read: value.read, + write: value.write, } } } @@ -1980,7 +1980,7 @@ impl From for api::access::AccessTokenInfo { Self { id: value.id, expires_at: value.expires_at.map(Into::into), - auto_prefix_streams: value.auto_prefix_streams.then_some(true), + auto_prefix_streams: value.auto_prefix_streams, scope: value.scope.into(), } }