live_data/descriptor.rs
1//! Per-feed descriptor and capability advertisement.
2
3use serde::{Deserialize, Serialize};
4
5use crate::schema::WireSchema;
6use crate::transport::{FormatPreference, TransportTag};
7
8/// Single named live feed, as advertised by a publisher.
9///
10/// A descriptor is information-only: it describes what the feed is and how it
11/// can be consumed. The matching producer-side handle
12/// lives in `live-stream`.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct FeedDescriptor {
15 /// Stable identifier for the feed, unique within a single publisher.
16 pub name: String,
17 /// Schema every emitted batch on the feed conforms to.
18 pub schema: WireSchema,
19 /// Transports the publisher is currently accepting subscriptions over.
20 pub transports: Vec<TransportTag>,
21 /// Formats the publisher can serialise batches into.
22 pub formats: Vec<FormatPreference>,
23 /// What the publisher is willing to do server-side at subscribe time.
24 pub capabilities: Capabilities,
25 /// Name of the column carrying the canonical event timestamp on
26 /// this feed. Optional in the manifest grammar so future
27 /// non-temporal feeds remain expressible, always populated for
28 /// streaming market data feeds.
29 #[serde(default)]
30 pub event_time_key: Option<String>,
31 /// Free-form classification tags, e.g. `["finance", "ticks"]`.
32 #[serde(default)]
33 pub tags: Vec<String>,
34 /// Optional human-readable description.
35 #[serde(default)]
36 pub description: Option<String>,
37}
38
39impl FeedDescriptor {
40 pub fn new(name: impl Into<String>, schema: WireSchema) -> Self {
41 Self {
42 name: name.into(),
43 schema,
44 transports: Vec::new(),
45 formats: Vec::new(),
46 capabilities: Capabilities::minimal(),
47 event_time_key: None,
48 tags: Vec::new(),
49 description: None,
50 }
51 }
52}
53
54/// What the publisher is willing to do server-side when accepting a subscription.
55///
56/// Only `can_project` defaults to true. The other two fields exist so
57/// the wire format is stable when filter and sampling support land, and so
58/// consumers can already gate features on what the server advertises.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
60pub struct Capabilities {
61 /// Server honours [`SubscriptionDescriptor::columns`] for projection.
62 pub can_project: bool,
63 /// Server honours [`SubscriptionDescriptor::filter`] for row-level filtering.
64 pub can_filter: bool,
65 /// Server honours [`SubscriptionDescriptor::sampling`].
66 pub can_sample: bool,
67}
68
69impl Capabilities {
70 /// Minimum guaranteed capability set
71 pub const fn minimal() -> Self {
72 Self { can_project: true, can_filter: false, can_sample: false }
73 }
74
75 /// All capabilities enabled.
76 pub const fn all() -> Self {
77 Self { can_project: true, can_filter: true, can_sample: true }
78 }
79}
80
81impl Default for Capabilities {
82 fn default() -> Self {
83 Self::minimal()
84 }
85}