Преглед на файлове

feat(lazer-protocol): add utoipa schema to api types (#3168)

* chore: add utoipa::ToSchema trait to request & response types for use in openapi spec

* bump patch ver

* chore: bump protocol dependents

* unify utoipa version, add more ToSchema traits

* fix: treat Channel as a str in schema

* fix examples

* examples

* fmt

* remove unnecessary import
Tejas Badadare преди 2 седмици
родител
ревизия
c0fc931111

+ 45 - 21
Cargo.lock

@@ -3132,7 +3132,7 @@ dependencies = [
  "tracing",
  "tracing-subscriber",
  "url",
- "utoipa",
+ "utoipa 3.5.0",
  "utoipa-swagger-ui",
 ]
 
@@ -5674,8 +5674,8 @@ dependencies = [
  "hyper 1.6.0",
  "hyper-util",
  "protobuf",
- "pyth-lazer-protocol 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "pyth-lazer-publisher-sdk 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pyth-lazer-protocol 0.20.0",
+ "pyth-lazer-publisher-sdk 0.20.0",
  "reqwest 0.12.23",
  "serde",
  "serde_json",
@@ -5694,7 +5694,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-client"
-version = "8.6.0"
+version = "8.6.1"
 dependencies = [
  "alloy-primitives 0.8.25",
  "anyhow",
@@ -5712,7 +5712,7 @@ dependencies = [
  "hex",
  "humantime-serde",
  "libsecp256k1 0.7.2",
- "pyth-lazer-protocol 0.20.0",
+ "pyth-lazer-protocol 0.20.1",
  "reqwest 0.12.23",
  "serde",
  "serde_json",
@@ -5727,22 +5727,17 @@ dependencies = [
 [[package]]
 name = "pyth-lazer-protocol"
 version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2efd998c309b88c9f9790addb962cb20cb2528f3c1fe305160f998403306ba7d"
 dependencies = [
- "alloy-primitives 0.8.25",
  "anyhow",
- "assert_float_eq",
- "bincode 1.3.3",
- "bs58",
  "byteorder",
  "chrono",
  "derive_more 1.0.0",
- "ed25519-dalek 2.1.1",
  "hex",
  "humantime",
  "humantime-serde",
  "itertools 0.13.0",
- "libsecp256k1 0.7.2",
- "mry",
  "protobuf",
  "rust_decimal",
  "serde",
@@ -5752,28 +5747,36 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-protocol"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2efd998c309b88c9f9790addb962cb20cb2528f3c1fe305160f998403306ba7d"
+version = "0.20.1"
 dependencies = [
+ "alloy-primitives 0.8.25",
  "anyhow",
+ "assert_float_eq",
+ "bincode 1.3.3",
+ "bs58",
  "byteorder",
  "chrono",
  "derive_more 1.0.0",
+ "ed25519-dalek 2.1.1",
  "hex",
  "humantime",
  "humantime-serde",
  "itertools 0.13.0",
+ "libsecp256k1 0.7.2",
+ "mry",
  "protobuf",
  "rust_decimal",
  "serde",
  "serde_json",
  "thiserror 2.0.12",
+ "utoipa 5.4.0",
 ]
 
 [[package]]
 name = "pyth-lazer-publisher-sdk"
 version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "988c6a2d6bc8d065a492d49915e803912b263e57ad5e300dc45c5a5471d609c8"
 dependencies = [
  "anyhow",
  "fs-err",
@@ -5785,15 +5788,13 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-publisher-sdk"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "988c6a2d6bc8d065a492d49915e803912b263e57ad5e300dc45c5a5471d609c8"
+version = "0.20.1"
 dependencies = [
  "anyhow",
  "fs-err",
  "protobuf",
  "protobuf-codegen",
- "pyth-lazer-protocol 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pyth-lazer-protocol 0.20.1",
  "serde_json",
 ]
 
@@ -10554,7 +10555,19 @@ dependencies = [
  "indexmap 2.10.0",
  "serde",
  "serde_json",
- "utoipa-gen",
+ "utoipa-gen 3.5.0",
+]
+
+[[package]]
+name = "utoipa"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993"
+dependencies = [
+ "indexmap 2.10.0",
+ "serde",
+ "serde_json",
+ "utoipa-gen 5.4.0",
 ]
 
 [[package]]
@@ -10570,6 +10583,17 @@ dependencies = [
  "syn 2.0.104",
 ]
 
+[[package]]
+name = "utoipa-gen"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
 [[package]]
 name = "utoipa-swagger-ui"
 version = "3.1.5"
@@ -10582,7 +10606,7 @@ dependencies = [
  "rust-embed",
  "serde",
  "serde_json",
- "utoipa",
+ "utoipa 3.5.0",
  "zip",
 ]
 

+ 2 - 2
lazer/publisher_sdk/rust/Cargo.toml

@@ -1,13 +1,13 @@
 [package]
 name = "pyth-lazer-publisher-sdk"
-version = "0.20.0"
+version = "0.20.1"
 edition = "2021"
 description = "Pyth Lazer Publisher SDK types."
 license = "Apache-2.0"
 repository = "https://github.com/pyth-network/pyth-crosschain"
 
 [dependencies]
-pyth-lazer-protocol = { version = "0.20.0", path = "../../sdk/rust/protocol" }
+pyth-lazer-protocol = { version = "0.20.1", path = "../../sdk/rust/protocol" }
 anyhow = "1.0.98"
 protobuf = "3.7.2"
 serde_json = "1.0.140"

+ 2 - 2
lazer/sdk/rust/client/Cargo.toml

@@ -1,12 +1,12 @@
 [package]
 name = "pyth-lazer-client"
-version = "8.6.0"
+version = "8.6.1"
 edition = "2021"
 description = "A Rust client for Pyth Lazer"
 license = "Apache-2.0"
 
 [dependencies]
-pyth-lazer-protocol = { path = "../protocol", version = "0.20.0" }
+pyth-lazer-protocol = { path = "../protocol", version = "0.20.1" }
 tokio = { version = "1", features = ["full"] }
 tokio-tungstenite = { version = "0.20", features = ["native-tls"] }
 futures-util = "0.3"

+ 2 - 1
lazer/sdk/rust/protocol/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "pyth-lazer-protocol"
-version = "0.20.0"
+version = "0.20.1"
 edition = "2021"
 description = "Pyth Lazer SDK - protocol types."
 license = "Apache-2.0"
@@ -21,6 +21,7 @@ chrono = "0.4.41"
 humantime = "2.2.0"
 hex = "0.4.3"
 thiserror = "2.0.12"
+utoipa = "5.3.1"
 
 [dev-dependencies]
 bincode = "1.3.3"

+ 43 - 27
lazer/sdk/rust/protocol/src/api.rs

@@ -7,6 +7,7 @@ use std::{
 use derive_more::derive::From;
 use itertools::Itertools as _;
 use serde::{de::Error, Deserialize, Serialize};
+use utoipa::ToSchema;
 
 use crate::{
     payload::AggregatedPriceFeedData,
@@ -14,11 +15,13 @@ use crate::{
     ChannelId, Price, PriceFeedId, PriceFeedProperty, Rate,
 };
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct LatestPriceRequestRepr {
     // Either price feed ids or symbols must be specified.
+    #[schema(example = json!([1]))]
     pub price_feed_ids: Option<Vec<PriceFeedId>>,
+    #[schema(example = schema_default_symbols)]
     pub symbols: Option<Vec<String>>,
     pub properties: Vec<PriceFeedProperty>,
     // "chains" was renamed to "formats". "chains" is still supported for compatibility.
@@ -33,7 +36,7 @@ pub struct LatestPriceRequestRepr {
     pub channel: Channel,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct LatestPriceRequest(LatestPriceRequestRepr);
 
@@ -79,12 +82,13 @@ impl DerefMut for LatestPriceRequest {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct PriceRequestRepr {
     pub timestamp: TimestampUs,
     // Either price feed ids or symbols must be specified.
     pub price_feed_ids: Option<Vec<PriceFeedId>>,
+    #[schema(default)]
     pub symbols: Option<Vec<String>>,
     pub properties: Vec<PriceFeedProperty>,
     pub formats: Vec<Format>,
@@ -97,7 +101,7 @@ pub struct PriceRequestRepr {
     pub channel: Channel,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct PriceRequest(PriceRequestRepr);
 
@@ -143,7 +147,7 @@ impl DerefMut for PriceRequest {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct ReducePriceRequest {
     pub payload: JsonUpdate,
@@ -158,7 +162,14 @@ pub fn default_parsed() -> bool {
     true
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
+pub fn schema_default_symbols() -> Option<Vec<String>> {
+    None
+}
+pub fn schema_default_price_feed_ids() -> Option<Vec<PriceFeedId>> {
+    Some(vec![PriceFeedId(1)])
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub enum DeliveryFormat {
     /// Deliver stream updates as JSON text messages.
@@ -168,7 +179,7 @@ pub enum DeliveryFormat {
     Binary,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub enum Format {
     Evm,
@@ -177,7 +188,7 @@ pub enum Format {
     LeUnsigned,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub enum JsonBinaryEncoding {
     #[default]
@@ -185,9 +196,11 @@ pub enum JsonBinaryEncoding {
     Hex,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, From)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, From, ToSchema)]
+#[schema(example = "fixed_rate@200ms")]
 pub enum Channel {
     FixedRate(FixedRate),
+    #[schema(rename = "real_time")]
     RealTime,
 }
 
@@ -275,11 +288,12 @@ impl<'de> Deserialize<'de> for Channel {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscriptionParamsRepr {
     // Either price feed ids or symbols must be specified.
     pub price_feed_ids: Option<Vec<PriceFeedId>>,
+    #[schema(default)]
     pub symbols: Option<Vec<String>>,
     pub properties: Vec<PriceFeedProperty>,
     // "chains" was renamed to "formats". "chains" is still supported for compatibility.
@@ -299,7 +313,7 @@ pub struct SubscriptionParamsRepr {
     pub ignore_invalid_feeds: bool,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscriptionParams(SubscriptionParamsRepr);
 
@@ -345,14 +359,14 @@ impl DerefMut for SubscriptionParams {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct JsonBinaryData {
     pub encoding: JsonBinaryEncoding,
     pub data: String,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct JsonUpdate {
     /// Present unless `parsed = false` is specified in subscription params.
@@ -372,7 +386,7 @@ pub struct JsonUpdate {
     pub le_unsigned: Option<JsonBinaryData>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct ParsedPayload {
     #[serde(with = "crate::serde_str::timestamp")]
@@ -380,7 +394,7 @@ pub struct ParsedPayload {
     pub price_feeds: Vec<ParsedFeedPayload>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct ParsedFeedPayload {
     pub price_feed_id: PriceFeedId,
@@ -491,7 +505,7 @@ impl ParsedFeedPayload {
 }
 
 /// A request sent from the client to the server.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(tag = "type")]
 #[serde(rename_all = "camelCase")]
 pub enum WsRequest {
@@ -499,10 +513,12 @@ pub enum WsRequest {
     Unsubscribe(UnsubscribeRequest),
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[derive(
+    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, ToSchema,
+)]
 pub struct SubscriptionId(pub u64);
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscribeRequest {
     pub subscription_id: SubscriptionId,
@@ -510,14 +526,14 @@ pub struct SubscribeRequest {
     pub params: SubscriptionParams,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct UnsubscribeRequest {
     pub subscription_id: SubscriptionId,
 }
 
 /// A JSON response sent from the server to the client.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, From)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, From, ToSchema)]
 #[serde(tag = "type")]
 #[serde(rename_all = "camelCase")]
 pub enum WsResponse {
@@ -530,13 +546,13 @@ pub enum WsResponse {
 }
 
 /// Sent from the server after a successul subscription.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscribedResponse {
     pub subscription_id: SubscriptionId,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct InvalidFeedSubscriptionDetails {
     pub unknown_ids: Vec<PriceFeedId>,
@@ -545,7 +561,7 @@ pub struct InvalidFeedSubscriptionDetails {
     pub unstable: Vec<PriceFeedId>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscribedWithInvalidFeedIdsIgnoredResponse {
     pub subscription_id: SubscriptionId,
@@ -553,7 +569,7 @@ pub struct SubscribedWithInvalidFeedIdsIgnoredResponse {
     pub ignored_invalid_feed_ids: InvalidFeedSubscriptionDetails,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct UnsubscribedResponse {
     pub subscription_id: SubscriptionId,
@@ -561,7 +577,7 @@ pub struct UnsubscribedResponse {
 
 /// Sent from the server if the requested subscription or unsubscription request
 /// could not be fulfilled.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct SubscriptionErrorResponse {
     pub subscription_id: SubscriptionId,
@@ -570,7 +586,7 @@ pub struct SubscriptionErrorResponse {
 
 /// Sent from the server if an internal error occured while serving data for an existing subscription,
 /// or a client request sent a bad request.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct ErrorResponse {
     pub error: String,
@@ -578,7 +594,7 @@ pub struct ErrorResponse {
 
 /// Sent from the server when new data is available for an existing subscription
 /// (only if `delivery_format == Json`).
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct StreamUpdatedResponse {
     pub subscription_id: SubscriptionId,

+ 16 - 2
lazer/sdk/rust/protocol/src/lib.rs

@@ -24,6 +24,7 @@ pub mod time;
 
 use derive_more::derive::{From, Into};
 use serde::{Deserialize, Serialize};
+use utoipa::ToSchema;
 
 pub use crate::{
     dynamic_value::DynamicValue,
@@ -39,8 +40,21 @@ pub use crate::{
 pub struct PublisherId(pub u16);
 
 #[derive(
-    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
+    Debug,
+    Clone,
+    Copy,
+    PartialEq,
+    Eq,
+    Hash,
+    PartialOrd,
+    Ord,
+    Serialize,
+    Deserialize,
+    From,
+    Into,
+    ToSchema,
 )]
+#[schema(value_type = u32)]
 pub struct PriceFeedId(pub u32);
 
 #[derive(
@@ -55,7 +69,7 @@ impl ChannelId {
     pub const FIXED_RATE_1000: ChannelId = ChannelId(4);
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
 #[serde(rename_all = "camelCase")]
 pub enum PriceFeedProperty {
     Price,

+ 5 - 1
lazer/sdk/rust/protocol/src/price.rs

@@ -7,6 +7,7 @@ use {
     serde::{Deserialize, Serialize},
     std::num::NonZeroI64,
     thiserror::Error,
+    utoipa::ToSchema,
 };
 
 #[derive(Debug, Error)]
@@ -21,8 +22,11 @@ pub enum PriceError {
     Overflow,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[derive(
+    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, ToSchema,
+)]
 #[repr(transparent)]
+#[schema(value_type = i64)]
 pub struct Price(NonZeroI64);
 
 impl Price {

+ 5 - 1
lazer/sdk/rust/protocol/src/rate.rs

@@ -6,6 +6,7 @@ use {
     rust_decimal::{prelude::FromPrimitive, Decimal},
     serde::{Deserialize, Serialize},
     thiserror::Error,
+    utoipa::ToSchema,
 };
 
 #[derive(Debug, Error)]
@@ -18,8 +19,11 @@ pub enum RateError {
     Overflow,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[derive(
+    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, ToSchema,
+)]
 #[repr(transparent)]
+#[schema(value_type = i64)]
 pub struct Rate(i64);
 
 impl Rate {

+ 11 - 3
lazer/sdk/rust/protocol/src/time.rs

@@ -11,11 +11,15 @@ use {
     },
     serde::{Deserialize, Serialize},
     std::time::{Duration, SystemTime},
+    utoipa::ToSchema,
 };
 
 /// Unix timestamp with microsecond resolution.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[derive(
+    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, ToSchema,
+)]
 #[repr(transparent)]
+#[schema(value_type = u64)]
 pub struct TimestampUs(u64);
 
 #[cfg_attr(feature = "mry", mry::mry)]
@@ -279,7 +283,10 @@ impl TryFrom<TimestampUs> for chrono::DateTime<chrono::Utc> {
 }
 
 /// Non-negative duration with microsecond resolution.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[derive(
+    Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, ToSchema,
+)]
+#[schema(value_type = u64)]
 pub struct DurationUs(u64);
 
 impl DurationUs {
@@ -487,7 +494,8 @@ pub mod duration_us_serde_humantime {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, ToSchema)]
+#[schema(as = String, example = "fixed_rate@200ms")]
 pub struct FixedRate {
     rate: DurationUs,
 }