Skip to main content

somatize_data/
ipc.rs

1//! The codec for frames: Arrow IPC, in both directions.
2
3use crate::Frame;
4use somatize_core::Value;
5use somatize_core::{Codec, CodecError, as_written, written_down};
6
7/// Writes frames down so they can be kept or sent, and reads them back.
8///
9/// The **second implementor of `Codec`, and from another crate** — the first was
10/// `python/`'s registry of `dump`/`load` pairs — which is what keeps the hole a
11/// hole. A unit struct because the format is the format and there is nothing to
12/// configure; whoever runs the engine hands it in, and a store and a wire get
13/// the same bytes because what a frame weighs has one answer.
14///
15/// It refuses an opaque that is not a frame rather than guessing. A graph
16/// carrying tensors **and** rows wants both codecs, which is what `python/`'s
17/// does: a frame comes here, anything else goes to its registry.
18pub struct Ipc;
19
20impl Codec for Ipc {
21    fn packed(&self, value: &Value) -> Result<Value, CodecError> {
22        Ok(match value {
23            Value::Opaque(_) => {
24                let frame = Frame::of(value).ok_or_else(|| {
25                    CodecError::new(
26                        "this opaque value is not a frame, and Arrow IPC is all this codec \
27                         knows how to write down",
28                    )
29                })?;
30                written_down(
31                    Frame::KIND,
32                    frame.written().map_err(|e| CodecError::new(e.message()))?,
33                )
34            }
35            Value::Map(pairs) => Value::map(
36                pairs
37                    .iter()
38                    .map(|(key, value)| Ok((key.clone(), self.packed(value)?)))
39                    .collect::<Result<Vec<_>, CodecError>>()?,
40            ),
41            Value::List(items) => Value::list(
42                items
43                    .iter()
44                    .map(|item| self.packed(item))
45                    .collect::<Result<Vec<_>, CodecError>>()?,
46            ),
47            other => other.clone(),
48        })
49    }
50
51    fn unpacked(&self, value: &Value) -> Result<Value, CodecError> {
52        if let Some((kind, bytes)) = as_written(value) {
53            // Somebody else's kind is left exactly as it arrived: it is not
54            // ours to read and it is not ours to lose, and the process that
55            // does know it may be one hop further on.
56            if kind != Frame::KIND {
57                return Ok(value.clone());
58            }
59            return Ok(Frame::read(bytes)
60                .map_err(|e| CodecError::new(e.message()))?
61                .value());
62        }
63        Ok(match value {
64            Value::Map(pairs) => Value::map(
65                pairs
66                    .iter()
67                    .map(|(key, value)| Ok((key.clone(), self.unpacked(value)?)))
68                    .collect::<Result<Vec<_>, CodecError>>()?,
69            ),
70            Value::List(items) => Value::list(
71                items
72                    .iter()
73                    .map(|item| self.unpacked(item))
74                    .collect::<Result<Vec<_>, CodecError>>()?,
75            ),
76            other => other.clone(),
77        })
78    }
79}