big_code_analysis/wire/ops_view.rs
1//! `crate::Ops`'s serialize path: a borrowed mirror of [`super::Ops`].
2//!
3//! Every other compute type serializes by materializing its owned wire
4//! projection first, and [`super`]'s module docs explain why that is the
5//! right default. `Ops` is the exception, because there the projection is
6//! the expensive part of the operation rather than a rounding error on
7//! it. `ops::finalize` merges each child space's Halstead maps into its
8//! parent, so a parent's vocabulary is a superset of every descendant's
9//! and an owned projection re-clones an entry once per enclosing space.
10//! Building the owned tree was 80% of `serde_json::to_string` on a
11//! hundred-level nest of functions with distinct identifiers, and *all*
12//! of it on a tree past [`MAX_SPACE_SERIALIZE_DEPTH`] — 2 000 levels
13//! cloned in full and then dropped unserialized (#1110).
14//!
15//! The price is a second field list, which is the drift the parent
16//! module exists to prevent, so [`OpsView`]'s fields must match
17//! [`super::Ops`]'s in name, order, type and `skip_serializing_if`.
18//! `borrowed_and_owned_ops_projections_serialize_alike` pins that in all
19//! four output formats, and its sibling covers the two fields a parsed
20//! fixture cannot reach.
21
22use serde::{Serialize, Serializer};
23
24use super::{MAX_SPACE_SERIALIZE_DEPTH, SpaceKind, ops};
25
26/// Borrowed, serialize-only mirror of [`super::Ops`].
27#[derive(Serialize)]
28struct OpsView<'a> {
29 name: &'a Option<String>,
30 #[serde(skip_serializing_if = "std::ops::Not::not")]
31 name_was_lossy: bool,
32 start_line: usize,
33 end_line: usize,
34 kind: SpaceKind,
35 #[serde(serialize_with = "serialize_ops_view_spaces")]
36 spaces: &'a [ops::Ops],
37 operands: &'a [String],
38 operators: &'a [String],
39}
40
41/// Serializes a `crate::Ops` node's children one level deeper, under
42/// the bound [`super::serialize_ops_spaces`] applies to the owned tree.
43/// Each child re-enters [`OpsView`], so nothing below the emitted levels
44/// is ever visited.
45fn serialize_ops_view_spaces<S: Serializer>(
46 spaces: &&[ops::Ops],
47 serializer: S,
48) -> Result<S::Ok, S::Error> {
49 crate::recursion::serialize_bounded(spaces, MAX_SPACE_SERIALIZE_DEPTH, "Ops", serializer)
50}
51
52impl Serialize for ops::Ops {
53 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
54 OpsView {
55 name: &self.name,
56 name_was_lossy: self.name_was_lossy,
57 start_line: self.start_line,
58 end_line: self.end_line,
59 kind: self.kind,
60 spaces: &self.spaces,
61 operands: &self.operands,
62 operators: &self.operators,
63 }
64 .serialize(serializer)
65 }
66}