Skip to main content

JsonMapStrExt

Trait JsonMapStrExt 

Source
pub trait JsonMapStrExt {
    // Required method
    fn insert_str(
        &mut self,
        key: impl Into<String>,
        value: impl Into<String>,
    ) -> Option<Value>;
}
Expand description

Substrate extension trait over serde_json::Map<String, Value> — the ONE substrate owner of the map.insert(<key>.into(), Value::String(<val>.into())) string-slot insertion shape every JSON-mutating helper in the workspace hand-authored at each callsite.

Peer of ValueObjectExt above on the JSON-mutation axis, split by SHAPE: ValueObjectExt::as_object_mut_or owns the “walk into this Value’s object-shape interior or fail loud” guard; JsonMapStrExt::insert_str owns the “stamp a Value::String at a string-typed key” write shape that every consumer downstream of the guard uses to populate the returned &mut Map.

Pre-lift the shape was hand-authored at SEVENTEEN production emit sites across tatara-reconciler past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:

  • ssapply::inject_annotations × 4 — the SSA-time observed-* annotation stamp family (PID, CONTENT_HASH, GENERATION, ATTESTATION_ROOT) each restated the 2-line annot.insert( <annotation-const>.to_string(), Value::String(<val>.<coerce>)) shape verbatim.
  • render::render_flux × 3 — the Flux Kustomization.spec seeds (interval, path, targetNamespace), each restating the same spec.insert("<key>".into(), Value::String(<val>)) shape.
  • render::render_aplicacao × 3 — the Flux HelmRelease.spec seeds (releaseName, targetNamespace) plus the values-overlay profile slot, each restating the same insert shape.
  • render::render_export_job × 2 — the export-Job outer label map (ROLE, EXPORT_INDEX) each restating the same insert shape.
  • edges::IngressEdge::render × 1 — the cert-manager cluster-issuer annotation, restating the same insert shape.
  • edges::routing_edge_labels × 2 — the routing-edge metadata. labels map’s non-ownership slots (APP, ROUTING_FORM), each restating the same labels.insert(<annotation-const>.to_string(), Value::String(<val>.into())) shape past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold — one of TWO adjacent bypass sites the substrate owner reaches through this lift.
  • render::mark_resources_as_adopting × 2 — the encapsulation- mode + adopted-release annotation stamps on adoption-mode render, each restating the same anns_obj.insert("<key>".into(), Value::String(<val>.into())) shape past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold. The adopted-release value slot also routes its <ns>/<release> join through the sibling crate::qualified_process_ref substrate composer, closing a bare format!("{ns}/{name}") bypass on the <ns>/<name> join axis at this same callsite.

All SEVENTEEN pre-lift sites restated the SAME 2-line shape verbatim, differing only in the &'static str / String key + the &str / String value at each callsite. A copy-paste that dropped the Value::String(...) wrap (a caller who reached for .insert(k, v) after refactoring from a Value slot to a plain String value slot) would type-check silently at every callsite — Map<String, Value>::insert expects a Value, and String: Into<Value> is provided by serde_json via the Value::String arm’s From impl, so the naive .insert(k, v.to_string()) compiles AND writes the byte-identical JSON. Post-lift each callsite reads <map>.insert_str(<key>, <val>) and the string-slot write shape lives at ONE substrate owner here.

§Composability

  • Key slot accepts any impl Into<String>: &str (via String::from), String (identity), Cow<'_, str>, so a callsite with a static annotations::PID (&'static str) reads insert_str(annotations::PID, …) with no .to_string() per site.
  • Value slot accepts any impl Into<String>: &str, String, Cow<'_, str>. Numeric or non-string values still need an explicit .to_string() at the callsite — same as pre-lift, so the wrapping shape stays visible in the caller’s grep footprint.
  • Returns Option<Value> matching the inherent Map<String, Value>::insert return semantics: None on new-key, Some(prev) on overwrite of an existing slot.

§Naming — insert_str, not insert

Same discipline as ValueObjectExt::as_object_mut_or above — the trait method deliberately does NOT collide with the inherent Map::insert (which takes (String, Value) positionally). A name collision would let a caller who has JsonMapStrExt in scope resolve to the inherent method by accident (inherent methods win over trait methods in method resolution) and silently drop the Value::String wrap, stamping the value bytes straight into the map under a different Value variant. The _str suffix names the intent: the value slot IS the Value::String arm at this write.

Theory anchor: THEORY.md §VI.1 (generation over composition — the .insert(<k>.into(), Value::String(<v>.into())) shape recurred at SEVENTEEN hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE substrate owner here). THEORY.md §II.1 invariant 5 (composition preserves proofs — a regression that drifts the string-slot write shape at ONE consumer surfaces at the substrate pin rather than as silent per-emit skew across every ssapply / render / edges JSON emit site).

Required Methods§

Source

fn insert_str( &mut self, key: impl Into<String>, value: impl Into<String>, ) -> Option<Value>

Insert a Value::String(<val>.into()) at <key>.into() into this JSON object map. Returns Option<Value> matching the underlying Map::insert semantics — None for a new key, Some(prev) for an overwrite.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl JsonMapStrExt for Map<String, Value>

Source§

fn insert_str( &mut self, key: impl Into<String>, value: impl Into<String>, ) -> Option<Value>

Implementors§