Skip to main content

dash_runtime/client/
action.rs

1//! What the caller must fetch ([`Action`]) and how it names a fetch
2//! ([`ResourceId`]).
3
4use broadcast_common::impl_spec_display;
5
6use crate::timing::utc_timing::UtcScheme;
7
8/// Client-assigned identity of one Representation in one Period. Stable for
9/// the life of the client.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct RepId(pub(crate) u32);
12
13impl RepId {
14    /// The numeric value.
15    #[must_use]
16    pub fn get(self) -> u32 {
17        self.0
18    }
19}
20
21/// One fetchable resource; correlates an [`Action`] with the `on_*` call that
22/// delivers it.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[non_exhaustive]
25pub enum ResourceId {
26    /// The Initialization Segment of a Representation. Representations whose
27    /// resolved init URL and range are identical share one fetch, named by
28    /// the first of them.
29    Init {
30        /// The Representation that asked first.
31        rep: RepId,
32    },
33    /// The `sidx` of a `SegmentBase` Representation.
34    Index {
35        /// The Representation.
36        rep: RepId,
37    },
38    /// One Media Segment.
39    Segment {
40        /// The Representation.
41        rep: RepId,
42        /// Its `$Number$` (the 1-based position for a `sidx`).
43        number: u64,
44    },
45}
46
47impl ResourceId {
48    /// The Representation the resource belongs to.
49    #[must_use]
50    pub fn rep(&self) -> RepId {
51        match self {
52            Self::Init { rep } | Self::Index { rep } | Self::Segment { rep, .. } => *rep,
53        }
54    }
55}
56
57/// Identity of one `UTCTiming` request; correlates an
58/// [`Action::FetchUtcTiming`] with the `on_utc_*` call that answers it.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
60pub struct UtcId(pub(crate) u32);
61
62impl UtcId {
63    /// The numeric value.
64    #[must_use]
65    pub fn get(self) -> u32 {
66        self.0
67    }
68}
69
70/// The HTTP method of a `UTCTiming` request.
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72#[non_exhaustive]
73pub enum UtcMethod {
74    /// `GET`; the body (or, for `http-head` re-issued after a refused `HEAD`,
75    /// only the `Date` header) is the time.
76    Get,
77    /// `HEAD`; the `Date` header is the time.
78    Head,
79}
80
81impl UtcMethod {
82    /// The method token.
83    #[must_use]
84    pub fn name(&self) -> &'static str {
85        match self {
86            Self::Get => "GET",
87            Self::Head => "HEAD",
88        }
89    }
90}
91impl_spec_display!(UtcMethod);
92
93/// The validators of the MPD the client holds; send them as `If-None-Match`
94/// and `If-Modified-Since` so an unchanged MPD answers `304` (IOP 4.4.4).
95#[derive(Debug, Clone, PartialEq, Eq, Default)]
96#[non_exhaustive]
97pub struct MpdValidators {
98    /// The last `ETag`.
99    pub etag: Option<String>,
100    /// The last `Last-Modified`.
101    pub last_modified: Option<String>,
102}
103
104/// One unit of I/O the caller performs.
105#[derive(Debug, Clone, PartialEq, Eq)]
106#[non_exhaustive]
107pub enum Action {
108    /// GET the MPD (conditional when `validators` are set). A `304` is
109    /// reported with [`super::DashClient::on_mpd_unchanged`].
110    FetchMpd {
111        /// The MPD URL: the first `Location`, else the redirect target, else
112        /// the original (23009-1 A.11).
113        url: String,
114        /// Validators of the MPD held now.
115        validators: MpdValidators,
116    },
117    /// Fetch the time from a `UTCTiming` server (23009-1 5.8.5.7). Report with
118    /// [`super::DashClient::on_utc_response`] or
119    /// [`super::DashClient::on_utc_failure`]. Carry no credentials: the server
120    /// is chosen by the MPD.
121    FetchUtcTiming {
122        /// Correlates the answer.
123        id: UtcId,
124        /// The scheme the MPD announced.
125        scheme: UtcScheme,
126        /// Absolute URL.
127        url: String,
128        /// `GET` or `HEAD`.
129        method: UtcMethod,
130    },
131    /// GET an Initialization Segment.
132    FetchInit {
133        /// Correlates [`super::DashClient::on_init`].
134        id: ResourceId,
135        /// Absolute URL.
136        url: String,
137        /// `(offset, length)` of a byte-range request.
138        byte_range: Option<(u64, u64)>,
139    },
140    /// GET a `sidx` (SegmentBase index).
141    FetchIndex {
142        /// Correlates [`super::DashClient::on_index`].
143        id: ResourceId,
144        /// Absolute URL.
145        url: String,
146        /// `(offset, length)` of a byte-range request.
147        byte_range: Option<(u64, u64)>,
148    },
149    /// GET a Media Segment.
150    FetchSegment {
151        /// Correlates [`super::DashClient::on_segment`].
152        id: ResourceId,
153        /// Absolute URL.
154        url: String,
155        /// `(offset, length)` of a byte-range request.
156        byte_range: Option<(u64, u64)>,
157    },
158}
159
160impl Action {
161    /// The resource a fetch action names; `None` for [`Action::FetchMpd`].
162    #[must_use]
163    pub fn id(&self) -> Option<ResourceId> {
164        match self {
165            Self::FetchMpd { .. } | Self::FetchUtcTiming { .. } => None,
166            Self::FetchInit { id, .. }
167            | Self::FetchIndex { id, .. }
168            | Self::FetchSegment { id, .. } => Some(*id),
169        }
170    }
171
172    /// The URL to fetch.
173    #[must_use]
174    pub fn url(&self) -> &str {
175        match self {
176            Self::FetchMpd { url, .. }
177            | Self::FetchUtcTiming { url, .. }
178            | Self::FetchInit { url, .. }
179            | Self::FetchIndex { url, .. }
180            | Self::FetchSegment { url, .. } => url,
181        }
182    }
183
184    /// The byte range, if the request is ranged.
185    #[must_use]
186    pub fn byte_range(&self) -> Option<(u64, u64)> {
187        match self {
188            Self::FetchMpd { .. } | Self::FetchUtcTiming { .. } => None,
189            Self::FetchInit { byte_range, .. }
190            | Self::FetchIndex { byte_range, .. }
191            | Self::FetchSegment { byte_range, .. } => *byte_range,
192        }
193    }
194}