1use cyfs_base::*;
2
3use serde::{Deserialize, Serialize};
4use std::ops::{Deref, DerefMut, Range};
5
6#[derive(Clone, Debug)]
14pub struct NDNDataRange {
15 pub start: Option<u64>,
16 pub length: Option<u64>,
17}
18
19impl NDNDataRange {
20 pub fn to_string(&self) -> String {
22 let start = self.start.unwrap_or(0);
23 match self.length {
24 Some(len) => {
25 format!("{}-{}", start, start + len - 1)
26 }
27 None => {
28 format!("{}-", start)
29 }
30 }
31 }
32}
33
34impl From<Range<u64>> for NDNDataRange {
35 fn from(v: Range<u64>) -> Self {
36 let length = if v.end >= v.start {
37 v.end - v.start
38 } else {
39 0
40 };
41
42 Self {
43 start: Some(v.start),
44 length: Some(length),
45 }
46 }
47}
48
49#[derive(Clone, Debug)]
50pub struct NDNDataRanges(Vec<NDNDataRange>);
51
52impl Deref for NDNDataRanges {
53 type Target = Vec<NDNDataRange>;
54
55 fn deref(&self) -> &Self::Target {
56 &self.0
57 }
58}
59
60impl DerefMut for NDNDataRanges {
61 fn deref_mut(&mut self) -> &mut Self::Target {
62 &mut self.0
63 }
64}
65
66
67impl NDNDataRanges {
68 pub fn ranges(&self) -> &Vec<NDNDataRange> {
69 &self.0
70 }
71
72 pub fn to_string(&self) -> String {
74 if self.0.len() == 0 {
75 "bytes=0-".to_owned()
76 } else {
77 let ranges: Vec<String> = self.0.iter().map(|range| range.to_string()).collect();
78
79 format!("bytes={}", ranges.join(", "))
80 }
81 }
82}
83
84#[derive(Clone, Debug)]
85pub enum NDNDataRequestRange {
86 Unparsed(String),
87 Range(NDNDataRanges),
88}
89
90impl std::fmt::Display for NDNDataRequestRange {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 write!(f, "{}", self.to_display_string())
93 }
94}
95
96#[derive(Clone, Debug, Serialize, Deserialize)]
97pub enum NDNDataResponseRange {
98 NoOverlap(u64),
99 InvalidRange,
100 Range((Vec<Range<u64>>, u64)),
101}
102
103impl ObjectFormatAutoWithSerde for NDNDataResponseRange {}
104impl JsonCodecAutoWithSerde for NDNDataResponseRange {}
105
106impl NDNDataRequestRange {
107 pub fn new_data_range(ranges: Vec<NDNDataRange>) -> Self {
108 Self::Range(NDNDataRanges(ranges))
109 }
110
111 pub fn new_range(ranges: Vec<Range<u64>>) -> Self {
112 let ranges = ranges.into_iter().map(|v| {
113 v.into()
114 }).collect();
115
116 Self::new_data_range(ranges)
117 }
118
119 pub fn new_unparsed(s: impl ToString) -> Self {
120 Self::Unparsed(s.to_string())
121 }
122
123 pub fn encode_string(&self) -> String {
124 match self {
125 Self::Unparsed(s) => s.clone(),
126 Self::Range(range) => range.to_string(),
127 }
128 }
129
130 pub fn to_display_string(&self) -> String {
131 match self {
132 Self::Unparsed(s) => {
133 format!("unparsed: {}", s)
134 }
135 Self::Range(range) => range.to_string(),
136 }
137 }
138
139 pub fn convert_to_response(&self, size: u64) -> Option<NDNDataResponseRange> {
140 let ret = match self {
141 Self::Unparsed(s) => Self::parse_str(s.as_str(), size),
142 Self::Range(list) => Self::parse_ranges(list, size),
143 };
144
145 info!("data range convert: {} -> {:?}", self, ret);
146
147 ret
148 }
149
150 fn parse_ranges(list: &NDNDataRanges, size: u64) -> Option<NDNDataResponseRange> {
151 let mut no_overlap = false;
152 let mut ranges = vec![];
153 for range in list.ranges() {
154 match Self::parse_range(range, size) {
155 Some(v) => match v {
156 NDNDataResponseRange::Range((range, _)) => {
157 assert!(range.len() > 0);
158 ranges.extend_from_slice(&range);
159 }
160 NDNDataResponseRange::InvalidRange => {
161 return Some(NDNDataResponseRange::InvalidRange);
162 }
163 NDNDataResponseRange::NoOverlap(_) => {
164 unreachable!();
165 }
166 },
167 None => {
168 no_overlap = true;
169 continue;
170 }
171 }
172 }
173
174 if ranges.is_empty() {
175 if no_overlap {
176 return Some(NDNDataResponseRange::NoOverlap(size));
177 } else {
178 return None;
179 }
180 }
181
182 Some(NDNDataResponseRange::Range((ranges, size)))
183 }
184
185 fn parse_range(range: &NDNDataRange, size: u64) -> Option<NDNDataResponseRange> {
186 match range.start {
187 Some(start) => {
188 if start >= size {
189 return None;
190 }
191
192 match range.length {
193 Some(mut len) => {
194 if len == 0 {
195 None
196 } else {
197 if start + len > size {
198 len = size - start;
199 }
200 let range = Range {
201 start,
202 end: start + len,
203 };
204 Some(NDNDataResponseRange::Range((vec![range], size)))
205 }
206 }
207 None => {
208 let len = size - start;
209 let range = Range {
210 start,
211 end: start + len,
212 };
213 Some(NDNDataResponseRange::Range((vec![range], size)))
214 }
215 }
216 }
217 None => match range.length {
219 Some(mut len) => {
220 if len > size {
221 len = size;
222 }
223
224 let range = Range { start: 0, end: len };
225 Some(NDNDataResponseRange::Range((vec![range], size)))
226 }
227 None => Some(NDNDataResponseRange::InvalidRange),
228 },
229 }
230 }
231
232 fn parse_str(range_str: &str, size: u64) -> Option<NDNDataResponseRange> {
233 let ranges = match http_range::HttpRange::parse(range_str, size) {
234 Ok(r) => r,
235 Err(err) => {
236 let res = match err {
237 http_range::HttpRangeParseError::NoOverlap => {
238 NDNDataResponseRange::NoOverlap(size)
239 }
240 http_range::HttpRangeParseError::InvalidRange => {
241 warn!("invalid range: {}, size={}", range_str, size);
242 NDNDataResponseRange::InvalidRange
243 }
244 };
245
246 return Some(res);
247 }
248 };
249
250 if ranges.is_empty() {
251 return None;
252 }
253
254 let ranges: Vec<Range<u64>> = ranges
255 .into_iter()
256 .map(|item| Range {
257 start: item.start,
258 end: item.start + item.length,
259 })
260 .collect();
261
262 Some(NDNDataResponseRange::Range((ranges, size)))
263 }
264}
265
266pub struct RangeHelper<Idx> {
267 _marker: std::marker::PhantomData<Idx>,
268}
269
270impl<Idx> RangeHelper<Idx> {
271 pub fn intersect(left: &Range<Idx>, right: &Range<Idx>) -> Option<Range<Idx>>
272 where
273 Idx: PartialOrd<Idx> + Ord + Copy,
274 {
275 if left.end <= right.start {
276 None
277 } else if left.start >= right.end {
278 None
279 } else {
280 let start = std::cmp::max(left.start, right.start);
281 let end = std::cmp::min(left.end, right.end);
282
283 let r = Range { start, end };
284 if r.is_empty() {
285 None
286 } else {
287 Some(r)
288 }
289 }
290 }
291
292 pub fn intersect_list(target: &Range<Idx>, ranges: &Vec<Range<Idx>>) -> Vec<Range<Idx>>
293 where
294 Idx: PartialOrd<Idx> + Ord + Copy,
295 {
296 ranges
297 .iter()
298 .filter_map(|range| Self::intersect(target, range))
299 .collect()
300 }
301
302 pub fn sum(ranges: &Vec<Range<Idx>>) -> Idx
303 where
304 Idx: std::ops::Add<Output = Idx> + std::ops::Sub<Output = Idx> + Default + Copy,
305 {
306 ranges
307 .iter()
308 .fold(Idx::default(), |acc, v| acc + (v.end - v.start))
309 }
310}
311
312use super::requestor_helper::RequestorHelper;
313
314pub struct RequestorRangeHelper {}
315
316impl RequestorRangeHelper {
317 fn encode_content_range(range: &Vec<Range<u64>>, size: u64) -> String {
319 assert!(range.len() > 0);
320 if range.len() > 1 {
321 warn!(
322 "only single range support for http range protocol! ranges={:?}, size={}",
323 range, size
324 );
325 }
326
327 let range = &range[0];
328
329 if size > 0 {
330 format!("bytes {}-{}/{}", range.start, range.end - 1, size)
331 } else {
332 format!("bytes {}-{}/*", range.start, range.end - 1)
333 }
334 }
335
336 fn encode_empty_range(size: u64) -> String {
337 format!("bytes */{}", size)
338 }
339
340 pub fn new_range_response(range_resp: &NDNDataResponseRange) -> http_types::Response {
341 let mut resp = match range_resp {
342 NDNDataResponseRange::Range((ranges, len)) => {
343 let mut resp =
344 RequestorHelper::new_response(http_types::StatusCode::PartialContent);
345
346 let value = Self::encode_content_range(ranges, *len);
347 resp.insert_header(http_types::headers::CONTENT_RANGE, value);
348
349 resp
350 }
351 NDNDataResponseRange::NoOverlap(len) => {
352 let msg = format!("Invalid range, no overlap! size={}", len);
353 let e = BuckyError::new(BuckyErrorCode::RangeNotSatisfiable, msg);
354
355 let mut resp: http_types::Response = RequestorHelper::trans_error(e);
356
357 let value = Self::encode_empty_range(*len);
358 resp.insert_header(http_types::headers::CONTENT_RANGE, value);
359
360 resp
361 }
362 NDNDataResponseRange::InvalidRange => {
363 let e = BuckyError::new(BuckyErrorCode::RangeNotSatisfiable, "Invalid range");
364
365 RequestorHelper::trans_error(e)
366 }
367 };
368
369 resp.insert_header(http_types::headers::ACCEPT_RANGES, "bytes");
370
371 resp
372 }
373}