isobmff/boxes/
sample_group.rs

1use std::io;
2
3use scuffle_bytes_util::BitWriter;
4use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be, ZeroCopyReader};
5
6use super::SampleGroupDescriptionEntry;
7use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
8
9/// Sample to group box
10///
11/// ISO/IEC 14496-12 - 8.9.2
12#[derive(IsoBox, Debug, PartialEq, Eq)]
13#[iso_box(box_type = b"sbgp", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
14pub struct SampleToGroupBox {
15    /// The full box header.
16    pub full_header: FullBoxHeader,
17    /// An integer that identifies the type (i.e. criterion used to form the sample groups)
18    /// of the sample grouping and links it to its sample group description table with the same value for
19    /// `grouping_type`. At most one occurrence of this box with the same value for `grouping_type` (and,
20    /// if used, `grouping_type_parameter`) shall exist for a track.
21    pub grouping_type: [u8; 4],
22    /// An indication of the sub-type of the grouping.
23    pub grouping_type_parameter: Option<u32>,
24    /// An integer that gives the number of entries in the following table.
25    pub entry_count: u32,
26    /// `sample_count` and `group_description_index`
27    pub entries: Vec<SampleToGroupBoxEntry>,
28}
29
30impl<'a> DeserializeSeed<'a, BoxHeader> for SampleToGroupBox {
31    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
32    where
33        R: ZeroCopyReader<'a>,
34    {
35        let full_header = FullBoxHeader::deserialize(&mut reader)?;
36
37        let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
38        let grouping_type_parameter = if full_header.version == 1 {
39            Some(u32::deserialize(&mut reader)?)
40        } else {
41            None
42        };
43
44        let entry_count = u32::deserialize(&mut reader)?;
45        let mut entries = Vec::with_capacity(entry_count as usize);
46        for _ in 0..entry_count {
47            entries.push(SampleToGroupBoxEntry::deserialize(&mut reader)?);
48        }
49
50        Ok(Self {
51            full_header,
52            grouping_type,
53            grouping_type_parameter,
54            entry_count,
55            entries,
56        })
57    }
58}
59
60impl Serialize for SampleToGroupBox {
61    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
62    where
63        W: std::io::Write,
64    {
65        self.serialize_box_header(&mut writer)?;
66        self.full_header.serialize(&mut writer)?;
67
68        self.grouping_type.serialize(&mut writer)?;
69        if self.full_header.version == 1 {
70            self.grouping_type_parameter
71                .ok_or(io::Error::new(
72                    io::ErrorKind::InvalidData,
73                    "grouping_type_parameter is required",
74                ))?
75                .serialize(&mut writer)?;
76        }
77
78        self.entry_count.serialize(&mut writer)?;
79        for entry in &self.entries {
80            entry.serialize(&mut writer)?;
81        }
82
83        Ok(())
84    }
85}
86
87impl IsoSized for SampleToGroupBox {
88    fn size(&self) -> usize {
89        let mut size = self.full_header.size();
90        size += 4; // grouping_type
91        if self.full_header.version == 1 {
92            size += 4; // grouping_type_parameter
93        }
94        size += 4; // entry_count
95        size += self.entries.size();
96
97        Self::add_header_size(size)
98    }
99}
100
101/// Entry in [`SampleToGroupBox`].
102#[derive(Debug, PartialEq, Eq)]
103pub struct SampleToGroupBoxEntry {
104    /// An integer that gives the number of consecutive samples with the same sample group
105    /// descriptor. It is an error for the total in this box to be greater than the `sample_count` documented
106    /// elsewhere, and the reader behaviour would then be undefined. If the sum of the sample count in
107    /// this box is less than the total sample count, or there is no [`SampleToGroupBox`] that applies to some
108    /// samples (e.g. it is absent from a track fragment), then those samples are associated with the group
109    /// identified by the `default_group_description_index` in the [`SampleGroupDescriptionBox`], if any, or
110    /// else with no group.
111    pub sample_count: u32,
112    /// An integer that gives the index of the sample group entry which describes
113    /// the samples in this group. The index ranges from 1 to the number of sample group entries in the
114    /// [`SampleGroupDescriptionBox`], or takes the value 0 to indicate that this sample is a member of no
115    /// group of this type.
116    pub group_description_index: u32,
117}
118
119impl<'a> Deserialize<'a> for SampleToGroupBoxEntry {
120    fn deserialize<R>(mut reader: R) -> io::Result<Self>
121    where
122        R: ZeroCopyReader<'a>,
123    {
124        Ok(Self {
125            sample_count: u32::deserialize(&mut reader)?,
126            group_description_index: u32::deserialize(&mut reader)?,
127        })
128    }
129}
130
131impl Serialize for SampleToGroupBoxEntry {
132    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
133    where
134        W: std::io::Write,
135    {
136        self.sample_count.serialize(&mut writer)?;
137        self.group_description_index.serialize(&mut writer)?;
138        Ok(())
139    }
140}
141
142impl IsoSized for SampleToGroupBoxEntry {
143    fn size(&self) -> usize {
144        4 + 4 // sample_count + group_description_index
145    }
146}
147
148/// Sample group description box
149///
150/// ISO/IEC 14496-12 - 8.9.3
151#[derive(IsoBox, Debug, PartialEq, Eq)]
152#[iso_box(box_type = b"sgpd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
153pub struct SampleGroupDescriptionBox<'a> {
154    /// The full box header.
155    pub full_header: FullBoxHeader,
156    /// An integer that identifies the [`SampleToGroupBox`] that is associated with this sample group description.
157    pub grouping_type: [u8; 4],
158    /// Indicates the length of every group entry (if the length is constant), or zero (0) if it is variable.
159    pub default_length: Option<u32>,
160    /// Specifies the index of the sample group description entry which
161    /// applies to all samples in the track for which no sample to group mapping is provided through a
162    /// [`SampleToGroupBox`]. The default value of this field is zero (indicating that the samples are mapped to
163    /// no group description of this type).
164    pub default_group_description_index: Option<u32>,
165    /// An integer that gives the number of entries in the following table.
166    pub entry_count: u32,
167    /// The contained sample group description entries.
168    pub entries: Vec<SampleGroupDescriptionEntry<'a>>,
169}
170
171impl<'a> DeserializeSeed<'a, BoxHeader> for SampleGroupDescriptionBox<'a> {
172    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
173    where
174        R: ZeroCopyReader<'a>,
175    {
176        let full_header = FullBoxHeader::deserialize(&mut reader)?;
177
178        let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
179        let default_length = if full_header.version >= 1 {
180            Some(u32::deserialize(&mut reader)?)
181        } else {
182            None
183        };
184        let default_group_description_index = if full_header.version >= 2 {
185            Some(u32::deserialize(&mut reader)?)
186        } else {
187            None
188        };
189
190        let entry_count = u32::deserialize(&mut reader)?;
191        let mut entries = Vec::with_capacity(entry_count as usize);
192        for _ in 0..entry_count {
193            let description_length = if default_length.is_some_and(|l| l == 0) {
194                Some(u32::deserialize(&mut reader)?)
195            } else {
196                None
197            };
198
199            let length = description_length.or(default_length);
200
201            let sample_group_description_entry =
202                SampleGroupDescriptionEntry::deserialize_seed(&mut reader, (grouping_type, length))?;
203
204            entries.push(sample_group_description_entry);
205        }
206
207        Ok(Self {
208            full_header,
209            grouping_type,
210            default_length,
211            default_group_description_index,
212            entry_count,
213            entries,
214        })
215    }
216}
217
218impl Serialize for SampleGroupDescriptionBox<'_> {
219    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
220    where
221        W: std::io::Write,
222    {
223        self.serialize_box_header(&mut writer)?;
224        self.full_header.serialize(&mut writer)?;
225
226        self.grouping_type.serialize(&mut writer)?;
227        if self.full_header.version >= 1 {
228            self.default_length
229                .ok_or(io::Error::new(io::ErrorKind::InvalidData, "default_length is required"))?
230                .serialize(&mut writer)?;
231        }
232        if self.full_header.version >= 2 {
233            self.default_group_description_index
234                .ok_or(io::Error::new(
235                    io::ErrorKind::InvalidData,
236                    "default_group_description_index is required",
237                ))?
238                .serialize(&mut writer)?;
239        }
240
241        self.entry_count.serialize(&mut writer)?;
242        for entry in &self.entries {
243            if self.full_header.version >= 1 && self.default_length.is_some_and(|l| l == 0) {
244                (entry.size() as u32).serialize(&mut writer)?;
245            }
246            entry.serialize(&mut writer)?;
247        }
248
249        Ok(())
250    }
251}
252
253impl IsoSized for SampleGroupDescriptionBox<'_> {
254    fn size(&self) -> usize {
255        let mut size = self.full_header.size();
256        size += 4; // grouping_type
257        if self.full_header.version >= 1 {
258            size += 4; // default_length
259        }
260        if self.full_header.version >= 2 {
261            size += 4; // default_group_description_index
262        }
263        size += 4; // entry_count
264        size += self
265            .entries
266            .iter()
267            .map(|entry| {
268                let mut size = 0;
269                if self.full_header.version >= 1 && self.default_length.is_some_and(|l| l == 0) {
270                    size += 4; // description_length
271                }
272                size += entry.size();
273                size
274            })
275            .sum::<usize>();
276
277        Self::add_header_size(size)
278    }
279}
280
281/// Compact sample to group box
282///
283/// ISO/IEC 14496-12 - 8.9.5
284#[derive(IsoBox, Debug, PartialEq, Eq)]
285#[iso_box(box_type = b"csgp", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
286pub struct CompactSampleToGroupBox {
287    // full header:
288    /// The version of the box.
289    pub version: u8,
290    /// The flags of the box.
291    pub flags: CompactSampleToGroupBoxFlags,
292    // body:
293    /// An integer that identifies the type (i.e. criterion used to form the sample groups) of the
294    /// sample grouping and links it to its sample group description table with the same value for grouping
295    /// type. At most one occurrence of either the ['csgp'](CompactSampleToGroupBox) or ['sbgp'](SampleToGroupBox) with
296    /// the same value for `grouping_type` (and, if used, `grouping_type_parameter`) shall exist for a track.
297    pub grouping_type: [u8; 4],
298    /// An indication of the sub-type of the grouping.
299    pub grouping_type_parameter: Option<u32>,
300    /// Indicates the length of the associated pattern in the pattern array that follows it. The
301    /// sum of the included sample_count values indicates the number of mapped samples.
302    pub pattern_count: u32,
303    /// `pattern_length` and `sample_count`
304    pub patterns: Vec<CompactSampleToGroupBoxPattern>,
305    /// `sample_group_description_index[j][k]`
306    ///
307    /// See [`CompactSampleToGroupBoxSampleGroupDescriptionIndex::value`] for details.
308    pub sample_group_description_index: Vec<Vec<CompactSampleToGroupBoxSampleGroupDescriptionIndex>>,
309}
310
311/// Flags for [`CompactSampleToGroupBox`].
312#[derive(Debug, PartialEq, Eq, Clone, Copy)]
313pub struct CompactSampleToGroupBoxFlags {
314    /// A flag that shall be zero when this box appears inside a [`TrackBox`](super::TrackBox)
315    /// but may be 0 or 1 when this box appears inside a [`TrackFragmentBox`](super::TrackFragmentBox).
316    /// When it is 1, it indicates that the most significant bit (MSB) of every `sample_group_description_index`
317    /// does not form part of the index number but instead indicates which [`SampleGroupDescriptionBox`] the
318    /// group description is to be found in: if the MSB is 0, the index identifies a group description from
319    /// the [`TrackBox`](super::TrackBox)'s [`SampleGroupDescriptionBox`];
320    /// if the MSB is 1, the index identifies a group description from the [`TrackFragmentBox`](super::TrackFragmentBox)'s
321    /// [`SampleGroupDescriptionBox`].
322    pub index_msb_indicates_fragment_local_description: bool,
323    /// If set, [`CompactSampleToGroupBox::grouping_type_parameter`] is present.
324    pub grouping_type_parameter_present: bool,
325    /// Inidicates the size of [`CompactSampleToGroupBoxPattern::pattern_length`].
326    ///
327    /// - `0`: 4 bits
328    /// - `1`: 8 bits
329    /// - `2`: 16 bits
330    /// - `3`: 32 bits
331    pub pattern_size_code: u8,
332    /// Inidicates the size of [`CompactSampleToGroupBoxPattern::sample_count`].
333    ///
334    /// - `0`: 4 bits
335    /// - `1`: 8 bits
336    /// - `2`: 16 bits
337    /// - `3`: 32 bits
338    pub count_size_code: u8,
339    /// The size of [`CompactSampleToGroupBoxSampleGroupDescriptionIndex::value`].
340    ///
341    /// - `0`: 4 bits
342    /// - `1`: 8 bits
343    /// - `2`: 16 bits
344    /// - `3`: 32 bits
345    pub index_size_code: u8,
346}
347
348impl<'a> Deserialize<'a> for CompactSampleToGroupBoxFlags {
349    fn deserialize<R>(reader: R) -> io::Result<Self>
350    where
351        R: ZeroCopyReader<'a>,
352    {
353        let value = U24Be::deserialize(reader)?.0;
354
355        Ok(Self {
356            index_msb_indicates_fragment_local_description: (value >> 7) & 0b1 != 0,
357            grouping_type_parameter_present: (value >> 6) & 0b1 != 0,
358            pattern_size_code: ((value >> 4) & 0b11) as u8,
359            count_size_code: ((value >> 2) & 0b11) as u8,
360            index_size_code: (value & 0b11) as u8,
361        })
362    }
363}
364
365impl Serialize for CompactSampleToGroupBoxFlags {
366    fn serialize<W>(&self, writer: W) -> io::Result<()>
367    where
368        W: std::io::Write,
369    {
370        let mut bit_writer = BitWriter::new(writer);
371        bit_writer.write_bit(self.index_msb_indicates_fragment_local_description)?;
372        bit_writer.write_bit(self.grouping_type_parameter_present)?;
373        bit_writer.write_bits(self.pattern_size_code as u64, 2)?;
374        bit_writer.write_bits(self.count_size_code as u64, 2)?;
375        bit_writer.write_bits(self.index_size_code as u64, 2)?;
376        Ok(())
377    }
378}
379
380impl IsoSized for CompactSampleToGroupBoxFlags {
381    fn size(&self) -> usize {
382        3
383    }
384}
385
386impl<'a> DeserializeSeed<'a, BoxHeader> for CompactSampleToGroupBox {
387    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
388    where
389        R: ZeroCopyReader<'a>,
390    {
391        let version = u8::deserialize(&mut reader)?;
392        let flags = CompactSampleToGroupBoxFlags::deserialize(&mut reader)?;
393
394        let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
395        let grouping_type_parameter = if flags.grouping_type_parameter_present {
396            Some(u32::deserialize(&mut reader)?)
397        } else {
398            None
399        };
400
401        let pattern_count = u32::deserialize(&mut reader)?;
402
403        let mut patterns = Vec::with_capacity(pattern_count as usize);
404        for _ in 0..pattern_count {
405            patterns.push(CompactSampleToGroupBoxPattern::deserialize_seed(&mut reader, flags)?);
406        }
407
408        let mut sample_group_description_index = Vec::with_capacity(pattern_count as usize);
409
410        let mut next_value = None; // used as a buffer for 4 bit values
411        for pattern in patterns.iter_mut() {
412            let mut current = Vec::with_capacity(pattern.pattern_length as usize);
413
414            for _ in 0..pattern.pattern_length {
415                match flags.index_size_code {
416                    0 => match next_value {
417                        None => {
418                            let byte = u8::deserialize(&mut reader)?;
419
420                            let mut value = byte >> 4;
421                            let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
422                                // Most significant bit indicates the fragment local flag
423                                let msb = (value >> 3) & 0b1 != 0;
424                                value &= 0b0111;
425                                msb
426                            });
427
428                            current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
429                                value: value as u32,
430                                fragment_local,
431                            });
432                            next_value = Some(byte & 0b0000_1111);
433                        }
434                        Some(mut value) => {
435                            let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
436                                // Most significant bit indicates the fragment local flag
437                                let msb = (value >> 3) & 0b1 != 0;
438                                value &= 0b0111;
439                                msb
440                            });
441
442                            current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
443                                value: value as u32,
444                                fragment_local,
445                            });
446                            next_value = None;
447                        }
448                    },
449                    1 => {
450                        let mut value = u8::deserialize(&mut reader)?;
451                        let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
452                            // Most significant bit indicates the fragment local flag
453                            let msb = (value >> 7) & 0b1 != 0;
454                            value &= 0b0111_1111;
455                            msb
456                        });
457                        current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
458                            value: value as u32,
459                            fragment_local,
460                        });
461                    }
462                    2 => {
463                        let mut value = u16::deserialize(&mut reader)?;
464                        let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
465                            // Most significant bit indicates the fragment local flag
466                            let msb = (value >> 15) & 0b1 != 0;
467                            value &= 0b0111_1111_1111_1111;
468                            msb
469                        });
470
471                        current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
472                            value: value as u32,
473                            fragment_local,
474                        });
475                    }
476                    3 => {
477                        let mut value = u32::deserialize(&mut reader)?;
478                        let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
479                            // Most significant bit indicates the fragment local flag
480                            let msb = (value >> 31) & 0b1 != 0;
481                            value &= 0b0111_1111_1111_1111_1111_1111_1111_1111;
482                            msb
483                        });
484
485                        current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex { value, fragment_local });
486                    }
487                    _ => unreachable!(),
488                }
489            }
490
491            sample_group_description_index.push(current);
492        }
493
494        Ok(Self {
495            version,
496            flags,
497            grouping_type,
498            grouping_type_parameter,
499            pattern_count,
500            patterns,
501            sample_group_description_index,
502        })
503    }
504}
505
506fn f(index: u8) -> u8 {
507    match index {
508        0 => 4,
509        1 => 8,
510        2 => 16,
511        3 => 32,
512        _ => unreachable!(),
513    }
514}
515
516impl Serialize for CompactSampleToGroupBox {
517    fn serialize<W>(&self, writer: W) -> io::Result<()>
518    where
519        W: std::io::Write,
520    {
521        let mut bit_writer = BitWriter::new(writer);
522
523        self.serialize_box_header(&mut bit_writer)?;
524        self.version.serialize(&mut bit_writer)?;
525        self.flags.serialize(&mut bit_writer)?;
526
527        self.grouping_type.serialize(&mut bit_writer)?;
528
529        if let Some(grouping_type_parameter) = self.grouping_type_parameter {
530            grouping_type_parameter.serialize(&mut bit_writer)?;
531        }
532
533        self.pattern_count.serialize(&mut bit_writer)?;
534        for pattern in &self.patterns {
535            bit_writer.write_bits(pattern.pattern_length as u64, f(self.flags.pattern_size_code))?;
536            bit_writer.write_bits(pattern.sample_count as u64, f(self.flags.count_size_code))?;
537        }
538
539        for j in &self.sample_group_description_index {
540            for k in j {
541                let bit_count = f(self.flags.index_size_code);
542                bit_writer.write_bits(k.to_value(bit_count) as u64, bit_count)?;
543            }
544        }
545
546        bit_writer.align()?;
547
548        Ok(())
549    }
550}
551
552impl IsoSized for CompactSampleToGroupBox {
553    fn size(&self) -> usize {
554        let mut size = 0;
555        size += self.version.size();
556        size += self.flags.size();
557        size += 4; // grouping_type
558        if self.grouping_type_parameter.is_some() {
559            size += 4; // grouping_type_parameter
560        }
561        size += 4; // pattern_count
562
563        let mut bits = 0;
564        bits += (f(self.flags.pattern_size_code) + f(self.flags.count_size_code)) * self.patterns.len() as u8;
565        for j in &self.sample_group_description_index {
566            bits += f(self.flags.index_size_code) * j.len() as u8;
567        }
568        size += (bits as usize).div_ceil(8);
569
570        Self::add_header_size(size)
571    }
572}
573
574/// A pattern in [`CompactSampleToGroupBox`].
575#[derive(Debug, PartialEq, Eq)]
576pub struct CompactSampleToGroupBoxPattern {
577    /// Corresponds to a pattern within the second array of `sample_group_description_index[j]` values.
578    /// Each instance of `pattern_length[i]` shall be greater than 0.
579    pub pattern_length: u32,
580    /// Specifies the number of samples that use the `i`-th pattern.
581    /// `sample_count[i]` shall be greater than zero, and `sample_count[i]` shall be
582    /// greater than or equal to [`pattern_length[i]`](Self::pattern_length).
583    pub sample_count: u32,
584}
585
586impl<'a> DeserializeSeed<'a, CompactSampleToGroupBoxFlags> for CompactSampleToGroupBoxPattern {
587    fn deserialize_seed<R>(mut reader: R, seed: CompactSampleToGroupBoxFlags) -> io::Result<Self>
588    where
589        R: ZeroCopyReader<'a>,
590    {
591        if (seed.pattern_size_code == 0) != (seed.count_size_code == 0) {
592            return Err(io::Error::new(
593                io::ErrorKind::InvalidData,
594                "If one of pattern size code and count size is 0, the other must be 0 too".to_string(),
595            ));
596        }
597
598        let mut pattern_length = match seed.pattern_size_code {
599            1 => u8::deserialize(&mut reader)? as u32,  // 8 bits
600            2 => u16::deserialize(&mut reader)? as u32, // 16 bits
601            3 => u32::deserialize(&mut reader)?,        // 32 bits
602            _ => 0,                                     // skip
603        };
604
605        let sample_count = match seed.count_size_code {
606            0 => {
607                // 4 bits
608                let byte = u8::deserialize(&mut reader)?;
609                pattern_length = (byte >> 4) as u32;
610                (byte & 0b0000_1111) as u32
611            }
612            1 => u8::deserialize(&mut reader)? as u32,  // 8 bits
613            2 => u16::deserialize(&mut reader)? as u32, // 16 bits
614            3 => u32::deserialize(&mut reader)?,        // 32 bits
615            _ => unreachable!(),
616        };
617
618        Ok(Self {
619            pattern_length,
620            sample_count,
621        })
622    }
623}
624
625/// The `sample_group_description_index[j][k]` in [`CompactSampleToGroupBox`].
626#[derive(Debug, PartialEq, Eq)]
627pub struct CompactSampleToGroupBoxSampleGroupDescriptionIndex {
628    /// An integer that gives the index of the sample group entry
629    /// which describes the samples in this group. The index ranges from 1 to the number of sample group
630    /// entries in the SampleGroupDescriptionBox, inclusive, or takes the value 0 to indicate that this
631    /// sample is a member of no group of this type.
632    pub value: u32,
633    /// If present, indicates fragment_local or global.
634    pub fragment_local: Option<bool>,
635}
636
637impl CompactSampleToGroupBoxSampleGroupDescriptionIndex {
638    /// Converts this value to a number with given size in bits.
639    pub fn to_value(&self, size: u8) -> u32 {
640        if let Some(fl) = self.fragment_local {
641            let mut value = (fl as u32) << (size - 1);
642            value |= self.value & ((1 << (size - 1)) - 1);
643            value
644        } else {
645            self.value & ((1 << size) - 1)
646        }
647    }
648}