use crate::ir::{AccessChain, PrimitiveLeaf, StringyBase};
use quote::quote;
use super::idents;
use super::leaf::{LeafArm, LeafArmKind, named_from_buf, vec_decl};
use super::{BaseCtx, Encoder, LeafCtx, access_chain_to_ref};
pub(super) fn wrap_option_access_chain_primitive(
leaf: PrimitiveLeaf<'_>,
ctx: &LeafCtx<'_>,
access: &AccessChain,
layers: usize,
) -> Encoder {
debug_assert!(layers >= 1);
if let PrimitiveLeaf::AsStr(stringy) = leaf {
return wrap_option_access_chain_as_str(stringy, ctx, access);
}
let orig_access = ctx.base.access.clone();
let local = idents::multi_option_local(ctx.base.idx);
let local_access = quote! { #local };
let collapsed_chain = super::access_chain_to_option_ref("e! { &(#orig_access) }, access);
let setup = if leaf.is_copy() {
quote! {
let #local: ::std::option::Option<_> = #collapsed_chain.copied();
}
} else {
quote! {
let #local: ::std::option::Option<_> = #collapsed_chain;
}
};
let new_ctx = LeafCtx {
base: BaseCtx {
access: &local_access,
idx: ctx.base.idx,
name: ctx.base.name,
},
decimal128_encode_trait: ctx.decimal128_encode_trait,
paths: ctx.paths,
};
let LeafArm {
decls,
push,
series,
} = super::vec::build_leaf(
leaf,
&new_ctx,
LeafArmKind::Option {
some_receiver: crate::codegen::type_registry::PrimitiveExprReceiver::RefRef,
},
);
Encoder::Leaf {
decls,
push: quote! {
#setup
#push
},
series,
}
}
fn wrap_option_access_chain_as_str(
base: &StringyBase,
ctx: &LeafCtx<'_>,
access: &AccessChain,
) -> Encoder {
let buf = idents::primitive_buf(ctx.base.idx);
let name = ctx.base.name;
let orig_access = ctx.base.access;
let collapsed_ref = access_chain_to_ref("e! { &(#orig_access) }, access).expr;
let value = super::stringy_value_expr(
base,
&collapsed_ref,
super::StringyExprKind::CollapsedOption,
);
let push = quote! { #buf.push(#value); };
let finish_series = named_from_buf(name, &buf, ctx.paths.prelude());
Encoder::Leaf {
decls: vec![vec_decl(&buf, "e! { ::std::option::Option<&str> })],
push,
series: finish_series,
}
}