mlt_core/frames/v01/id/
encode.rs1use crate::MltResult;
2use crate::codecs::bytes::encode_bools_to_bytes;
3use crate::codecs::rle::encode_byte_rle;
4use crate::v01::{
5 EncodedId, EncodedIdValue, EncodedStream, EncodedStreamData, IdValues, IdWidth, IntEncoder,
6 IntEncoding, LogicalEncoder, LogicalEncoding, PhysicalEncoder, PhysicalEncoding, RleMeta,
7 StreamMeta, StreamType,
8};
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12#[cfg_attr(all(not(test), feature = "arbitrary"), derive(arbitrary::Arbitrary))]
13pub struct IdEncoder {
14 pub logical: LogicalEncoder,
15 pub id_width: IdWidth,
16}
17
18impl IdEncoder {
19 #[must_use]
20 pub fn new(logical: LogicalEncoder, id_width: IdWidth) -> Self {
21 Self { logical, id_width }
22 }
23}
24
25impl EncodedId {
26 pub(crate) fn encode(value: &IdValues, encoder: IdEncoder) -> MltResult<Self> {
27 use IdWidth as CFG;
28
29 let presence = if matches!(encoder.id_width, CFG::OptId32 | CFG::OptId64) {
30 let present: Vec<bool> = value.0.iter().map(Option::is_some).collect();
31 let num_values = u32::try_from(present.len())?;
32 let data = encode_byte_rle(&encode_bools_to_bytes(&present));
33
34 let runs = num_values.div_ceil(8);
38 let num_rle_values = u32::try_from(data.len())?;
39 let meta = StreamMeta::new(
40 StreamType::Present,
41 IntEncoding::new(
42 LogicalEncoding::Rle(RleMeta {
43 runs,
44 num_rle_values,
45 }),
46 PhysicalEncoding::None,
47 ),
48 num_values,
49 );
50
51 Some(EncodedStream {
52 meta,
53 data: EncodedStreamData::Encoded(data),
54 })
55 } else {
56 None
57 };
58
59 let value_stream = if matches!(encoder.id_width, CFG::Id32 | CFG::OptId32) {
60 #[expect(clippy::cast_possible_truncation, reason = "truncation was requested")]
61 let vals: Vec<u32> = value
62 .0
63 .iter()
64 .filter_map(|&id| id)
65 .map(|v| v as u32)
66 .collect();
67 EncodedIdValue::Id32(EncodedStream::encode_u32s(
68 &vals,
69 IntEncoder::new(encoder.logical, PhysicalEncoder::VarInt),
70 )?)
71 } else {
72 let vals: Vec<u64> = value.0.iter().filter_map(|&id| id).collect();
73 EncodedIdValue::Id64(EncodedStream::encode_u64s(
74 &vals,
75 IntEncoder::new(encoder.logical, PhysicalEncoder::VarInt),
76 )?)
77 };
78
79 Ok(Self {
80 presence,
81 value: value_stream,
82 })
83 }
84}