Skip to main content

plexus_serde/
capability.rs

1use crate::plexus_generated::plexus as fb;
2use crate::{
3    CapabilityOrderingContract, CapabilitySemver, CapabilityVersionRange, EngineCapabilityDecl,
4    OpOrderingDecl, SerdeError,
5};
6use flatbuffers::FlatBufferBuilder;
7
8fn to_fb_ordering_contract(contract: CapabilityOrderingContract) -> fb::CapabilityOrderingContract {
9    match contract {
10        CapabilityOrderingContract::EngineDefinedStable => {
11            fb::CapabilityOrderingContract::engine_defined_stable
12        }
13        CapabilityOrderingContract::StablePassThrough => {
14            fb::CapabilityOrderingContract::stable_pass_through
15        }
16        CapabilityOrderingContract::FanOutDeterministicPerInput => {
17            fb::CapabilityOrderingContract::fan_out_deterministic_per_input
18        }
19        CapabilityOrderingContract::DeterministicSortStableTies => {
20            fb::CapabilityOrderingContract::deterministic_sort_stable_ties
21        }
22        CapabilityOrderingContract::UnspecifiedWithoutSort => {
23            fb::CapabilityOrderingContract::unspecified_without_sort
24        }
25        CapabilityOrderingContract::StableConcatOrUnspecifiedDistinct => {
26            fb::CapabilityOrderingContract::stable_concat_or_unspecified_distinct
27        }
28        CapabilityOrderingContract::ScoreDescStableTies => {
29            fb::CapabilityOrderingContract::score_desc_stable_ties
30        }
31    }
32}
33
34fn from_fb_ordering_contract(
35    contract: fb::CapabilityOrderingContract,
36) -> Result<CapabilityOrderingContract, SerdeError> {
37    Ok(match contract {
38        fb::CapabilityOrderingContract::engine_defined_stable => {
39            CapabilityOrderingContract::EngineDefinedStable
40        }
41        fb::CapabilityOrderingContract::stable_pass_through => {
42            CapabilityOrderingContract::StablePassThrough
43        }
44        fb::CapabilityOrderingContract::fan_out_deterministic_per_input => {
45            CapabilityOrderingContract::FanOutDeterministicPerInput
46        }
47        fb::CapabilityOrderingContract::deterministic_sort_stable_ties => {
48            CapabilityOrderingContract::DeterministicSortStableTies
49        }
50        fb::CapabilityOrderingContract::unspecified_without_sort => {
51            CapabilityOrderingContract::UnspecifiedWithoutSort
52        }
53        fb::CapabilityOrderingContract::stable_concat_or_unspecified_distinct => {
54            CapabilityOrderingContract::StableConcatOrUnspecifiedDistinct
55        }
56        fb::CapabilityOrderingContract::score_desc_stable_ties => {
57            CapabilityOrderingContract::ScoreDescStableTies
58        }
59        _ => {
60            return Err(SerdeError::Unsupported(
61                "unknown CapabilityOrderingContract enum value",
62            ))
63        }
64    })
65}
66
67pub fn serialize_engine_capability_decl(
68    decl: &EngineCapabilityDecl,
69) -> Result<Vec<u8>, SerdeError> {
70    let mut fbb = FlatBufferBuilder::new();
71    let version_range = fb::CapabilityVersionRange::create(
72        &mut fbb,
73        &fb::CapabilityVersionRangeArgs {
74            min_major: decl.version_range.min_supported.major,
75            min_minor: decl.version_range.min_supported.minor,
76            min_patch: decl.version_range.min_supported.patch,
77            max_major: decl.version_range.max_supported.major,
78            max_minor: decl.version_range.max_supported.minor,
79            max_patch: decl.version_range.max_supported.patch,
80        },
81    );
82
83    let supported_ops_strs = decl
84        .supported_ops
85        .iter()
86        .map(|x| fbb.create_string(x))
87        .collect::<Vec<_>>();
88    let supported_ops = fbb.create_vector(&supported_ops_strs);
89
90    let supported_exprs_strs = decl
91        .supported_exprs
92        .iter()
93        .map(|x| fbb.create_string(x))
94        .collect::<Vec<_>>();
95    let supported_exprs = fbb.create_vector(&supported_exprs_strs);
96
97    let op_ordering_offsets = decl
98        .op_ordering
99        .iter()
100        .map(|entry| {
101            let op = fbb.create_string(&entry.op);
102            fb::OpOrderingDecl::create(
103                &mut fbb,
104                &fb::OpOrderingDeclArgs {
105                    op: Some(op),
106                    contract: to_fb_ordering_contract(entry.contract),
107                },
108            )
109        })
110        .collect::<Vec<_>>();
111    let op_ordering = fbb.create_vector(&op_ordering_offsets);
112
113    let root = fb::EngineCapabilityDecl::create(
114        &mut fbb,
115        &fb::EngineCapabilityDeclArgs {
116            version_range: Some(version_range),
117            supported_ops: Some(supported_ops),
118            supported_exprs: Some(supported_exprs),
119            op_ordering: Some(op_ordering),
120            supports_graph_ref: decl.supports_graph_ref,
121            supports_multi_graph: decl.supports_multi_graph,
122            supports_graph_params: decl.supports_graph_params,
123        },
124    );
125    fbb.finish(root, None);
126    Ok(fbb.finished_data().to_vec())
127}
128
129pub fn deserialize_engine_capability_decl(
130    bytes: &[u8],
131) -> Result<EngineCapabilityDecl, SerdeError> {
132    let fb_decl = flatbuffers::root::<fb::EngineCapabilityDecl<'_>>(bytes)?;
133    let vr = fb_decl.version_range();
134    let version_range = CapabilityVersionRange {
135        min_supported: CapabilitySemver {
136            major: vr.min_major(),
137            minor: vr.min_minor(),
138            patch: vr.min_patch(),
139        },
140        max_supported: CapabilitySemver {
141            major: vr.max_major(),
142            minor: vr.max_minor(),
143            patch: vr.max_patch(),
144        },
145    };
146
147    let supported_ops = fb_decl
148        .supported_ops()
149        .map(|xs| (0..xs.len()).map(|i| xs.get(i).to_string()).collect())
150        .unwrap_or_default();
151    let supported_exprs = fb_decl
152        .supported_exprs()
153        .map(|xs| (0..xs.len()).map(|i| xs.get(i).to_string()).collect())
154        .unwrap_or_default();
155    let op_ordering = fb_decl
156        .op_ordering()
157        .map(|xs| {
158            (0..xs.len())
159                .map(|i| {
160                    let x = xs.get(i);
161                    let op = x
162                        .op()
163                        .ok_or(SerdeError::MissingField("OpOrderingDecl.op"))?
164                        .to_string();
165                    Ok(OpOrderingDecl {
166                        op,
167                        contract: from_fb_ordering_contract(x.contract())?,
168                    })
169                })
170                .collect::<Result<Vec<_>, SerdeError>>()
171        })
172        .transpose()?
173        .unwrap_or_default();
174
175    Ok(EngineCapabilityDecl {
176        version_range,
177        supported_ops,
178        supported_exprs,
179        op_ordering,
180        supports_graph_ref: fb_decl.supports_graph_ref(),
181        supports_multi_graph: fb_decl.supports_multi_graph(),
182        supports_graph_params: fb_decl.supports_graph_params(),
183    })
184}