vortex_ipc/messages/
encoder.rs1use bytes::Bytes;
5use bytes::BytesMut;
6use flatbuffers::FlatBufferBuilder;
7use vortex_array::ArrayContext;
8use vortex_array::ArrayRef;
9use vortex_array::dtype::DType;
10use vortex_array::serde::SerializeOptions;
11use vortex_buffer::ByteBuffer;
12use vortex_error::VortexResult;
13use vortex_error::vortex_err;
14use vortex_flatbuffers::FlatBuffer;
15use vortex_flatbuffers::WriteFlatBufferExt;
16use vortex_flatbuffers::message as fb;
17use vortex_session::VortexSession;
18
19pub enum EncoderMessage<'a> {
21 Array(&'a ArrayRef),
22 Buffer(&'a ByteBuffer),
23 DType(&'a DType),
24}
25
26pub struct MessageEncoder {
27 zeros: Bytes,
29 session: VortexSession,
30}
31
32impl MessageEncoder {
33 pub fn new(session: VortexSession) -> Self {
34 Self {
35 session,
36 zeros: BytesMut::zeroed(u16::MAX as usize).freeze(),
37 }
38 }
39
40 pub fn encode(&mut self, message: EncoderMessage) -> VortexResult<Vec<Bytes>> {
44 let mut buffers = vec![];
45
46 buffers.push(self.zeros.clone());
49 buffers.push(self.zeros.clone());
50
51 let mut fbb = FlatBufferBuilder::from_vec(vec![0u8; 4]);
56
57 let (header, body_len) = match message {
58 EncoderMessage::Array(array) => {
59 let ctx = ArrayContext::empty();
62
63 let array_buffers =
64 array.serialize(&ctx, &self.session, &SerializeOptions::default())?;
65 let body_len = array_buffers.iter().map(|b| b.len() as u64).sum::<u64>();
66
67 let array_encodings = ctx
68 .to_ids()
69 .iter()
70 .map(|e| fbb.create_string(e.as_ref()))
71 .collect::<Vec<_>>();
72 let array_encodings = fbb.create_vector(array_encodings.as_slice());
73
74 let header = fb::ArrayMessage::create(
75 &mut fbb,
76 &fb::ArrayMessageArgs {
77 row_count: u32::try_from(array.len())
78 .map_err(|_| vortex_err!("Array length must fit into u32"))?,
79 encodings: Some(array_encodings),
80 },
81 )
82 .as_union_value();
83
84 buffers.extend(array_buffers.into_iter().map(|b| b.into_inner()));
85
86 (header, body_len)
87 }
88 EncoderMessage::Buffer(buffer) => {
89 let header = fb::BufferMessage::create(
90 &mut fbb,
91 &fb::BufferMessageArgs {
92 alignment_exponent: buffer.alignment().exponent(),
93 },
94 )
95 .as_union_value();
96 let body_len = buffer.len() as u64;
97 buffers.push(buffer.clone().into_inner());
98
99 (header, body_len)
100 }
101 EncoderMessage::DType(dtype) => {
102 let header =
103 fb::DTypeMessage::create(&mut fbb, &fb::DTypeMessageArgs {}).as_union_value();
104
105 let buffer = dtype.write_flatbuffer_bytes()?.into_inner().into_inner();
106 let body_len = buffer.len() as u64;
107 buffers.push(buffer);
108
109 (header, body_len)
110 }
111 };
112
113 let mut msg = fb::MessageBuilder::new(&mut fbb);
114 msg.add_version(Default::default());
115 msg.add_header_type(match message {
116 EncoderMessage::Array(_) => fb::MessageHeader::ArrayMessage,
117 EncoderMessage::Buffer(_) => fb::MessageHeader::BufferMessage,
118 EncoderMessage::DType(_) => fb::MessageHeader::DTypeMessage,
119 });
120 msg.add_header(header);
121 msg.add_body_size(body_len);
122 let msg = msg.finish();
123
124 fbb.finish_minimal(msg);
126 let (fbv, pos) = fbb.collapse();
127 let fb_buffer = FlatBuffer::copy_from(&fbv[pos..]);
128 let fb_buffer_len = u32::try_from(fb_buffer.len())
129 .map_err(|_| vortex_err!("Array flatbuffer length must fit into u32"))?;
130
131 buffers[0] = Bytes::from(fb_buffer_len.to_le_bytes().to_vec());
132 buffers[1] = fb_buffer.into_inner().into_inner();
133
134 Ok(buffers)
135 }
136}