willow_data_model/relative_encodings/
range3d_range3d.rs

1use crate::{
2    grouping::{Range, Range3d, RangeEnd},
3    Path, SubspaceId,
4};
5
6use compact_u64::{CompactU64, Tag, TagWidth};
7use ufotofu::{BulkConsumer, BulkProducer};
8
9use ufotofu_codec::{
10    Blame, DecodableCanonic, DecodeError, Encodable, EncodableKnownSize, EncodableSync,
11    RelativeDecodable, RelativeDecodableCanonic, RelativeDecodableSync, RelativeEncodable,
12    RelativeEncodableKnownSize, RelativeEncodableSync,
13};
14use willow_encoding::is_bitflagged;
15
16impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
17    RelativeEncodable<Range3d<MCL, MCC, MPL, S>> for Range3d<MCL, MCC, MPL, S>
18where
19    S: SubspaceId + Encodable,
20{
21    /// Encodes this [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it.
22    ///
23    /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area).
24    async fn relative_encode<C>(
25        &self,
26        consumer: &mut C,
27        r: &Range3d<MCL, MCC, MPL, S>,
28    ) -> Result<(), C::Error>
29    where
30        C: BulkConsumer<Item = u8>,
31    {
32        let start_to_start = self.times().start.abs_diff(r.times().start);
33        let start_to_end = match r.times().end {
34            RangeEnd::Closed(end) => self.times().start.abs_diff(end),
35            RangeEnd::Open => u64::MAX,
36        };
37        let end_to_start = match self.times().end {
38            RangeEnd::Closed(end) => end.abs_diff(r.times().start),
39            RangeEnd::Open => u64::MAX,
40        };
41        let end_to_end = match (&self.times().end, &r.times().end) {
42            (RangeEnd::Closed(self_end), RangeEnd::Closed(ref_end)) => self_end.abs_diff(*ref_end),
43            (RangeEnd::Closed(_), RangeEnd::Open) => u64::MAX,
44            (RangeEnd::Open, RangeEnd::Closed(_)) => u64::MAX,
45            (RangeEnd::Open, RangeEnd::Open) => 0, // shouldn't matter right???
46        };
47
48        let start_time_diff = core::cmp::min(start_to_start, start_to_end);
49
50        let end_time_diff = core::cmp::min(end_to_start, end_to_end);
51
52        let mut header_1 = 0b0000_0000;
53
54        // Bits 0, 1 - Encode r.get_subspaces().start?
55        if self.subspaces().start == r.subspaces().start {
56            header_1 |= 0b0100_0000;
57        } else if r.subspaces().end == self.subspaces().start {
58            header_1 |= 0b1000_0000;
59        } else {
60            header_1 |= 0b1100_0000;
61        }
62
63        // Bits 2, 3 - Encode r.get_subspaces().end?
64        if self.subspaces().end == RangeEnd::Open {
65            // Do nothing
66        } else if self.subspaces().end == r.subspaces().start {
67            header_1 |= 0b0001_0000;
68        } else if self.subspaces().end == r.subspaces().end {
69            header_1 |= 0b0010_0000;
70        } else if self.subspaces().end != RangeEnd::Open {
71            header_1 |= 0b0011_0000;
72        }
73
74        // Bit 4 - Encode r.get_paths().start relative to ref.get_paths().start or to ref.get_paths().end?
75        if let RangeEnd::Closed(ref_path_end) = &r.paths().end {
76            let lcp_start_start = self.paths().start.longest_common_prefix(&r.paths().start);
77            let lcp_start_end = self.paths().start.longest_common_prefix(ref_path_end);
78
79            if lcp_start_start.component_count() >= lcp_start_end.component_count() {
80                header_1 |= 0b0000_1000;
81            }
82        } else {
83            header_1 |= 0b0000_1000;
84        }
85
86        // Bit 5 - Self path end open?
87        if self.paths().end == RangeEnd::Open {
88            header_1 |= 0b0000_0100;
89        }
90
91        // Bit 6 - Encode r.get_paths().end relative to ref.get_paths().start or to ref.get_paths().end (if at all)?
92        match (&self.paths().end, &r.paths().end) {
93            (RangeEnd::Closed(self_path_end), RangeEnd::Closed(ref_path_end)) => {
94                let lcp_end_start = self_path_end.longest_common_prefix(&r.paths().start);
95                let lcp_end_end = self_path_end.longest_common_prefix(ref_path_end);
96
97                if lcp_end_start.component_count() >= lcp_end_end.component_count() {
98                    header_1 |= 0b0000_0010;
99                }
100            }
101            (RangeEnd::Closed(_), RangeEnd::Open) => {
102                header_1 |= 0b0000_0010;
103            }
104            (RangeEnd::Open, RangeEnd::Closed(_)) => {}
105            (RangeEnd::Open, RangeEnd::Open) => {}
106        }
107
108        // Bit 7 - Self time end open?
109        if self.times().end == RangeEnd::Open {
110            header_1 |= 0b0000_0001;
111        }
112
113        consumer.consume(header_1).await?;
114
115        let mut header_2 = 0b0000_0000;
116
117        // Bit 8 - Encode r.get_times().start relative to ref.get_times().start or ref.get_times().end?
118        if start_to_start <= start_to_end {
119            header_2 |= 0b1000_0000;
120        }
121
122        // Bit 9 -Add or subtract start_time_diff?
123        if is_bitflagged(header_2, 0) && self.times().start >= r.times().start
124            || !is_bitflagged(header_2, 0) && self.times().start >= r.times().end
125        {
126            header_2 |= 0b0100_0000;
127        }
128
129        // Bit 10, 11 - 2-bit integer n such that 2^n gives compact_width(start_time_diff)
130        let start_diff_tag = Tag::min_tag(start_time_diff, TagWidth::two());
131        header_2 |= start_diff_tag.data_at_offset(2);
132
133        // Bit 12 - Encode r.get_times().end relative to ref.get_times().start or ref.get_times().end (if at all)?
134        if self.times().end != RangeEnd::Open && end_to_start <= end_to_end {
135            header_2 |= 0b0000_1000;
136        }
137
138        // Bit 13 - Add or subtract end_time_diff (if encoding it at all)?
139        if self.times().end == RangeEnd::Open {
140            // do nothing
141        } else if (is_bitflagged(header_2, 4) && self.times().end >= r.times().start)
142            || (!is_bitflagged(header_2, 4) && self.times().end >= r.times().end)
143        {
144            header_2 |= 0b0000_0100;
145        }
146
147        // Bits 14, 15 - ignored, or 2-bit integer n such that 2^n gives compact_width(end_time_diff)
148        if self.times().end == RangeEnd::Open {
149            // do nothing
150        } else {
151            let end_diff_tag = Tag::min_tag(end_time_diff, TagWidth::two());
152            header_2 |= end_diff_tag.data_at_offset(6);
153        }
154
155        consumer.consume(header_2).await?;
156
157        if (self.subspaces().start == r.subspaces().start)
158            || (r.subspaces().end == self.subspaces().start)
159        {
160            // Don't encode
161        } else {
162            self.subspaces().start.encode(consumer).await?;
163        }
164
165        if self.subspaces().end == RangeEnd::Open
166            || (self.subspaces().end == r.subspaces().start)
167            || (self.subspaces().end == r.subspaces().end)
168        {
169            // Don't encode end subspace
170        } else if let RangeEnd::Closed(end_subspace) = &self.subspaces().end {
171            end_subspace.encode(consumer).await?;
172        }
173
174        if is_bitflagged(header_1, 4) {
175            self.paths()
176                .start
177                .relative_encode(consumer, &r.paths().start)
178                .await?;
179        } else if let RangeEnd::Closed(end_path) = &r.paths().end {
180            self.paths()
181                .start
182                .relative_encode(consumer, end_path)
183                .await?;
184        }
185
186        if let RangeEnd::Closed(end_path) = &self.paths().end {
187            if is_bitflagged(header_1, 6) {
188                end_path.relative_encode(consumer, &r.paths().start).await?
189            } else if let RangeEnd::Closed(ref_end_path) = &r.paths().end {
190                end_path.relative_encode(consumer, ref_end_path).await?;
191            }
192        }
193
194        CompactU64(start_time_diff)
195            .relative_encode(consumer, &start_diff_tag.encoding_width())
196            .await?;
197
198        if self.times().end != RangeEnd::Open {
199            let end_diff_tag = Tag::min_tag(end_time_diff, TagWidth::two());
200
201            CompactU64(end_time_diff)
202                .relative_encode(consumer, &end_diff_tag.encoding_width())
203                .await?;
204        }
205
206        Ok(())
207    }
208}
209
210impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
211    RelativeDecodable<Range3d<MCL, MCC, MPL, S>, Blame> for Range3d<MCL, MCC, MPL, S>
212where
213    S: SubspaceId + DecodableCanonic,
214    Blame: From<S::ErrorReason> + From<S::ErrorCanonic>,
215{
216    /// Decodes a [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it.
217    ///
218    /// Will return an error if the encoding has not been produced by the corresponding encoding function.
219    ///
220    /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area).
221    async fn relative_decode<P>(
222        producer: &mut P,
223        r: &Range3d<MCL, MCC, MPL, S>,
224    ) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
225    where
226        P: BulkProducer<Item = u8>,
227        Self: Sized,
228    {
229        relative_decode_maybe_canonic::<false, MCL, MCC, MPL, S, P>(producer, r).await
230    }
231}
232
233impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
234    RelativeDecodableCanonic<Range3d<MCL, MCC, MPL, S>, Blame, Blame> for Range3d<MCL, MCC, MPL, S>
235where
236    S: SubspaceId + DecodableCanonic,
237    Blame: From<S::ErrorReason> + From<S::ErrorCanonic>,
238{
239    async fn relative_decode_canonic<P>(
240        producer: &mut P,
241        r: &Range3d<MCL, MCC, MPL, S>,
242    ) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
243    where
244        P: BulkProducer<Item = u8>,
245        Self: Sized,
246    {
247        relative_decode_maybe_canonic::<true, MCL, MCC, MPL, S, P>(producer, r).await
248    }
249}
250
251impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
252    RelativeEncodableKnownSize<Range3d<MCL, MCC, MPL, S>> for Range3d<MCL, MCC, MPL, S>
253where
254    S: SubspaceId + EncodableKnownSize,
255{
256    fn relative_len_of_encoding(&self, r: &Range3d<MCL, MCC, MPL, S>) -> usize {
257        let start_to_start = self.times().start.abs_diff(r.times().start);
258        let start_to_end = match r.times().end {
259            RangeEnd::Closed(end) => self.times().start.abs_diff(end),
260            RangeEnd::Open => u64::MAX,
261        };
262        let end_to_start = match self.times().end {
263            RangeEnd::Closed(end) => end.abs_diff(r.times().start),
264            RangeEnd::Open => u64::MAX,
265        };
266        let end_to_end = match (&self.times().end, &r.times().end) {
267            (RangeEnd::Closed(self_end), RangeEnd::Closed(ref_end)) => self_end.abs_diff(*ref_end),
268            (RangeEnd::Closed(_), RangeEnd::Open) => u64::MAX,
269            (RangeEnd::Open, RangeEnd::Closed(_)) => u64::MAX,
270            (RangeEnd::Open, RangeEnd::Open) => 0, // shouldn't matter right???
271        };
272
273        let start_time_diff = core::cmp::min(start_to_start, start_to_end);
274
275        let end_time_diff = core::cmp::min(end_to_start, end_to_end);
276
277        let subspace_start_len = if (self.subspaces().start == r.subspaces().start)
278            || (r.subspaces().end == self.subspaces().start)
279        {
280            0
281        } else {
282            self.subspaces().start.len_of_encoding()
283        };
284
285        let subspace_end_len = if self.subspaces().end == RangeEnd::Open
286            || (self.subspaces().end == r.subspaces().start)
287            || (self.subspaces().end == r.subspaces().end)
288        {
289            // Don't encode end subspace
290            0
291        } else if let RangeEnd::Closed(end_subspace) = &self.subspaces().end {
292            end_subspace.len_of_encoding()
293        } else {
294            0
295        };
296
297        let path_start_rel_to_start = if let RangeEnd::Closed(ref_path_end) = &r.paths().end {
298            let lcp_start_start = self.paths().start.longest_common_prefix(&r.paths().start);
299            let lcp_start_end = self.paths().start.longest_common_prefix(ref_path_end);
300
301            lcp_start_start.component_count() >= lcp_start_end.component_count()
302        } else {
303            true
304        };
305
306        let path_start_len = if path_start_rel_to_start {
307            self.paths()
308                .start
309                .relative_len_of_encoding(&r.paths().start)
310        } else if let RangeEnd::Closed(end_path) = &r.paths().end {
311            self.paths().start.relative_len_of_encoding(end_path)
312        } else {
313            panic!("Tried to encode a path range start relative to an open end")
314        };
315
316        let path_end_rel_to_start = match (&self.paths().end, &r.paths().end) {
317            (RangeEnd::Closed(self_path_end), RangeEnd::Closed(ref_path_end)) => {
318                let lcp_end_start = self_path_end.longest_common_prefix(&r.paths().start);
319                let lcp_end_end = self_path_end.longest_common_prefix(ref_path_end);
320
321                lcp_end_start.component_count() >= lcp_end_end.component_count()
322            }
323            (RangeEnd::Closed(_), RangeEnd::Open) => true,
324            (RangeEnd::Open, RangeEnd::Closed(_)) => false,
325            (RangeEnd::Open, RangeEnd::Open) => false,
326        };
327
328        let path_end_len = if let RangeEnd::Closed(end_path) = &self.paths().end {
329            if path_end_rel_to_start {
330                end_path.relative_len_of_encoding(&r.paths().start)
331            } else if let RangeEnd::Closed(ref_end_path) = &r.paths().end {
332                end_path.relative_len_of_encoding(ref_end_path)
333            } else {
334                0
335            }
336        } else {
337            0
338        };
339
340        let start_diff_tag = Tag::min_tag(start_time_diff, TagWidth::two());
341
342        let start_diff_len =
343            CompactU64(start_time_diff).relative_len_of_encoding(&start_diff_tag.encoding_width());
344
345        let end_diff_len = if self.times().end != RangeEnd::Open {
346            let end_diff_tag = Tag::min_tag(end_time_diff, TagWidth::two());
347
348            CompactU64(end_time_diff).relative_len_of_encoding(&end_diff_tag.encoding_width())
349        } else {
350            0
351        };
352
353        2 + subspace_start_len
354            + subspace_end_len
355            + path_start_len
356            + path_end_len
357            + start_diff_len
358            + end_diff_len
359    }
360}
361
362impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
363    RelativeEncodableSync<Range3d<MCL, MCC, MPL, S>> for Range3d<MCL, MCC, MPL, S>
364where
365    S: SubspaceId + EncodableSync,
366{
367}
368
369impl<const MCL: usize, const MCC: usize, const MPL: usize, S>
370    RelativeDecodableSync<Range3d<MCL, MCC, MPL, S>, Blame> for Range3d<MCL, MCC, MPL, S>
371where
372    S: SubspaceId + DecodableCanonic,
373    Blame: From<S::ErrorReason> + From<S::ErrorCanonic>,
374{
375}
376
377async fn relative_decode_maybe_canonic<
378    const CANONIC: bool,
379    const MCL: usize,
380    const MCC: usize,
381    const MPL: usize,
382    S,
383    P,
384>(
385    producer: &mut P,
386    r: &Range3d<MCL, MCC, MPL, S>,
387) -> Result<Range3d<MCL, MCC, MPL, S>, DecodeError<P::Final, P::Error, Blame>>
388where
389    P: BulkProducer<Item = u8>,
390    S: SubspaceId + DecodableCanonic,
391    Blame: From<S::ErrorReason> + From<S::ErrorCanonic>,
392{
393    let header_1 = producer.produce_item().await?;
394
395    let subspace_start_flags = header_1 & 0b1100_0000;
396    let subspace_end_flags = header_1 & 0b0011_0000;
397    let is_path_start_rel_to_start = is_bitflagged(header_1, 4);
398    let is_path_end_open = is_bitflagged(header_1, 5);
399    let is_path_end_rel_to_start = is_bitflagged(header_1, 6);
400    let is_times_end_open = is_bitflagged(header_1, 7);
401
402    let header_2 = producer.produce_item().await?;
403
404    let is_time_start_rel_to_start = is_bitflagged(header_2, 0);
405    let add_or_subtract_start_time_diff = is_bitflagged(header_2, 1);
406
407    let start_time_diff_tag = Tag::from_raw(header_2, TagWidth::two(), 2);
408    let is_time_end_rel_to_start = is_bitflagged(header_2, 4);
409    let add_or_subtract_end_time_diff = is_bitflagged(header_2, 5);
410    let end_time_diff_tag = Tag::from_raw(header_2, TagWidth::two(), 6);
411
412    // Decode subspace start
413    let subspace_start = match subspace_start_flags {
414        0b0100_0000 => r.subspaces().start.clone(),
415        0b1000_0000 => match &r.subspaces().end {
416            RangeEnd::Closed(end) => end.clone(),
417            RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
418        },
419        0b1100_0000 => {
420            let decoded_subspace = if CANONIC {
421                S::decode_canonic(producer)
422                    .await
423                    .map_err(DecodeError::map_other_from)?
424            } else {
425                S::decode(producer)
426                    .await
427                    .map_err(DecodeError::map_other_from)?
428            };
429
430            if decoded_subspace == r.subspaces().start || r.subspaces().end == decoded_subspace {
431                return Err(DecodeError::Other(Blame::TheirFault));
432            }
433
434            decoded_subspace
435        }
436        // This can only be b0000_0000 (which is not valid!)
437        _ => Err(DecodeError::Other(Blame::TheirFault))?,
438    };
439
440    let subspace_end = match subspace_end_flags {
441        0b0000_0000 => RangeEnd::Open,
442        0b0001_0000 => RangeEnd::Closed(r.subspaces().start.clone()),
443        0b0010_0000 => match &r.subspaces().end {
444            RangeEnd::Closed(end) => RangeEnd::Closed(end.clone()),
445            RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
446        },
447        // This can only be 0b0011_0000
448        _ => {
449            let decoded_subspace = if CANONIC {
450                RangeEnd::Closed(
451                    S::decode_canonic(producer)
452                        .await
453                        .map_err(DecodeError::map_other_from)?,
454                )
455            } else {
456                RangeEnd::Closed(
457                    S::decode(producer)
458                        .await
459                        .map_err(DecodeError::map_other_from)?,
460                )
461            };
462
463            if decoded_subspace == r.subspaces().start || r.subspaces().end == decoded_subspace {
464                return Err(DecodeError::Other(Blame::TheirFault));
465            }
466
467            decoded_subspace
468        }
469    };
470
471    // Check subspace end...
472
473    let path_start = match (is_path_start_rel_to_start, &r.paths().end) {
474        (true, RangeEnd::Closed(_)) => {
475            if CANONIC {
476                Path::relative_decode_canonic(producer, &r.paths().start).await?
477            } else {
478                Path::relative_decode(producer, &r.paths().start).await?
479            }
480        }
481        (true, RangeEnd::Open) => {
482            if CANONIC {
483                Path::relative_decode_canonic(producer, &r.paths().start).await?
484            } else {
485                Path::relative_decode(producer, &r.paths().start).await?
486            }
487        }
488        (false, RangeEnd::Closed(path_end)) => {
489            if CANONIC {
490                Path::relative_decode_canonic(producer, path_end).await?
491            } else {
492                Path::relative_decode(producer, path_end).await?
493            }
494        }
495        (false, RangeEnd::Open) => Err(DecodeError::Other(Blame::TheirFault))?,
496    };
497
498    // Canonicity check for path start
499    if CANONIC {
500        match &r.paths().end {
501            RangeEnd::Closed(ref_path_end) => {
502                let lcp_start_start = path_start.longest_common_prefix(&r.paths().start);
503                let lcp_start_end = path_start.longest_common_prefix(ref_path_end);
504
505                let expected_is_start_rel_to_start =
506                    lcp_start_start.component_count() >= lcp_start_end.component_count();
507
508                if expected_is_start_rel_to_start != is_path_start_rel_to_start {
509                    return Err(DecodeError::Other(Blame::TheirFault));
510                }
511            }
512            RangeEnd::Open => {
513                if !is_path_start_rel_to_start {
514                    return Err(DecodeError::Other(Blame::TheirFault));
515                }
516            }
517        }
518    }
519    // Canonicity check for path start over
520
521    let path_end = if is_path_end_open {
522        RangeEnd::Open
523    } else if is_path_end_rel_to_start {
524        if CANONIC {
525            RangeEnd::Closed(Path::relative_decode_canonic(producer, &r.paths().start).await?)
526        } else {
527            RangeEnd::Closed(Path::relative_decode(producer, &r.paths().start).await?)
528        }
529    } else {
530        match &r.paths().end {
531            RangeEnd::Closed(end) => {
532                if CANONIC {
533                    RangeEnd::Closed(Path::relative_decode_canonic(producer, end).await?)
534                } else {
535                    RangeEnd::Closed(Path::relative_decode(producer, end).await?)
536                }
537            }
538            RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
539        }
540    };
541
542    // Canonicity check for path end
543    if CANONIC {
544        match &path_end {
545            RangeEnd::Closed(p_end) => match &r.paths().end {
546                RangeEnd::Closed(ref_end) => {
547                    let lcp_end_start = p_end.longest_common_prefix(&r.paths().start);
548                    let lcp_end_end = p_end.longest_common_prefix(ref_end);
549
550                    let expected_is_path_end_rel_to_start =
551                        lcp_end_start.component_count() >= lcp_end_end.component_count();
552
553                    if expected_is_path_end_rel_to_start != is_path_end_rel_to_start {
554                        return Err(DecodeError::Other(Blame::TheirFault));
555                    }
556                }
557                RangeEnd::Open => {}
558            },
559            RangeEnd::Open => {
560                if is_path_end_rel_to_start {
561                    return Err(DecodeError::Other(Blame::TheirFault));
562                }
563            }
564        }
565    }
566    // End canonicity check
567
568    let start_time_diff = if CANONIC {
569        CompactU64::relative_decode_canonic(producer, &start_time_diff_tag)
570            .await
571            .map_err(DecodeError::map_other_from)?
572            .0
573    } else {
574        CompactU64::relative_decode(producer, &start_time_diff_tag)
575            .await
576            .map_err(DecodeError::map_other_from)?
577            .0
578    };
579
580    let time_start = match (is_time_start_rel_to_start, add_or_subtract_start_time_diff) {
581        (true, true) => r.times().start.checked_add(start_time_diff),
582        (true, false) => r.times().start.checked_sub(start_time_diff),
583        (false, true) => match r.times().end {
584            RangeEnd::Closed(ref_end) => ref_end.checked_add(start_time_diff),
585            RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
586        },
587        (false, false) => match r.times().end {
588            RangeEnd::Closed(ref_end) => ref_end.checked_sub(start_time_diff),
589            RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
590        },
591    }
592    .ok_or(DecodeError::Other(Blame::TheirFault))?;
593
594    // Canonicity check for start time
595    if CANONIC {
596        match r.times().end {
597            RangeEnd::Closed(ref_time_end) => {
598                let start_to_start = time_start.abs_diff(r.times().start);
599                let start_to_end = time_start.abs_diff(ref_time_end);
600
601                let expected_is_start_rel_to_start = start_to_start <= start_to_end;
602
603                if expected_is_start_rel_to_start != is_time_start_rel_to_start {
604                    return Err(DecodeError::Other(Blame::TheirFault));
605                }
606
607                let expected_add_or_subtract_start_time_diff = is_time_start_rel_to_start
608                    && time_start >= r.times().start
609                    || !expected_is_start_rel_to_start && time_start >= ref_time_end;
610
611                if expected_add_or_subtract_start_time_diff != add_or_subtract_start_time_diff {
612                    return Err(DecodeError::Other(Blame::TheirFault));
613                }
614            }
615            RangeEnd::Open => {
616                if !is_time_start_rel_to_start {
617                    return Err(DecodeError::Other(Blame::TheirFault));
618                }
619
620                // I need to very add or subtract time diff here.
621                let expected_add_or_subtract_time_diff = time_start >= r.times().start;
622
623                if expected_add_or_subtract_time_diff != add_or_subtract_start_time_diff {
624                    return Err(DecodeError::Other(Blame::TheirFault));
625                }
626            }
627        }
628    }
629    // End of canonicity check for start time
630
631    let time_end = if is_times_end_open {
632        if CANONIC {
633            if add_or_subtract_end_time_diff {
634                return Err(DecodeError::Other(Blame::TheirFault));
635            }
636
637            if is_time_end_rel_to_start {
638                return Err(DecodeError::Other(Blame::TheirFault));
639            }
640
641            let end_time_diff_compact_width_flags = 0b0000_0011;
642            if header_2 & end_time_diff_compact_width_flags != 0b0000_0000 {
643                return Err(DecodeError::Other(Blame::TheirFault));
644            }
645        }
646
647        RangeEnd::Open
648    } else {
649        let end_time_diff = if CANONIC {
650            CompactU64::relative_decode_canonic(producer, &end_time_diff_tag)
651                .await
652                .map_err(DecodeError::map_other_from)?
653                .0
654        } else {
655            CompactU64::relative_decode(producer, &end_time_diff_tag)
656                .await
657                .map_err(DecodeError::map_other_from)?
658                .0
659        };
660
661        let time_end = match (is_time_end_rel_to_start, add_or_subtract_end_time_diff) {
662            (true, true) => r
663                .times()
664                .start
665                .checked_add(end_time_diff)
666                .ok_or(DecodeError::Other(Blame::TheirFault))?,
667
668            (true, false) => r
669                .times()
670                .start
671                .checked_sub(end_time_diff)
672                .ok_or(DecodeError::Other(Blame::TheirFault))?,
673
674            (false, true) => match r.times().end {
675                RangeEnd::Closed(ref_end) => ref_end
676                    .checked_add(end_time_diff)
677                    .ok_or(DecodeError::Other(Blame::TheirFault))?,
678
679                RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
680            },
681            (false, false) => match r.times().end {
682                RangeEnd::Closed(ref_end) => ref_end
683                    .checked_sub(end_time_diff)
684                    .ok_or(DecodeError::Other(Blame::TheirFault))?,
685
686                RangeEnd::Open => Err(DecodeError::Other(Blame::TheirFault))?,
687            },
688        };
689
690        let end_to_start = time_end.abs_diff(r.times().start);
691        let end_to_end = match &r.times().end {
692            RangeEnd::Closed(ref_end) => time_end.abs_diff(*ref_end),
693            RangeEnd::Open => u64::MAX,
694        };
695
696        if CANONIC {
697            let expected_is_time_end_rel_to_start = end_to_start <= end_to_end;
698            if expected_is_time_end_rel_to_start != is_time_end_rel_to_start {
699                return Err(DecodeError::Other(Blame::TheirFault));
700            }
701
702            let expected_end_time_diff = core::cmp::min(end_to_start, end_to_end);
703
704            if expected_end_time_diff != end_time_diff {
705                return Err(DecodeError::Other(Blame::TheirFault));
706            }
707
708            let expected_add_or_subtract_end_time_diff = (is_time_end_rel_to_start
709                && time_end >= r.times().start)
710                || (!is_time_end_rel_to_start && time_end >= r.times().end);
711
712            if expected_add_or_subtract_end_time_diff != add_or_subtract_end_time_diff {
713                return Err(DecodeError::Other(Blame::TheirFault));
714            }
715        }
716
717        RangeEnd::Closed(time_end)
718    };
719
720    Ok(Range3d::new(
721        Range {
722            start: subspace_start,
723            end: subspace_end,
724        },
725        Range {
726            start: path_start,
727            end: path_end,
728        },
729        Range {
730            start: time_start,
731            end: time_end,
732        },
733    ))
734}