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}