← Commit history

Delete rust/crates/kicad-core/src/ipc/silk_fields.rs.orig

Colby Knox ·9aeac063ac ·14d ago ·parent bda3f5a
1 file changed −255
rust/crates/kicad-core/src/ipc/silk_fields.rs.origdeleted−255
@@ -1,255 +0,0 @@-use super::*;-use crate::silk_fields as fields;-use kicad_ipc_rs::FieldItem;--fn id(item: &EditablePcbItem) -> Option<&str> {-    match item {-        EditablePcbItem::Field(f) => f-            .proto()-            .text-            .as_ref()?-            .id-            .as_ref()-            .map(|x| x.value.as_str()),-        _ => None,-    }-}-fn apply_geometry(mut field: FieldItem, e: &fields::Edit) -> RResult<EditablePcbItem> {-    let f = field.proto_mut();-    if f.name != e.name {-        return Err(RoutingError::new(-            "field_identity_mismatch",-            "Native field name does not match saved reference/value property",-        ));-    }-    f.visible = e.visible;-    let b = f-        .text-        .as_mut()-        .ok_or_else(|| RoutingError::new("field_unavailable", "Native field has no board text"))?;-    if b.locked == 2 || b.knockout {-        return Err(RoutingError::new(-            "field_locked_or_knockout",-            "Locked/knockout fields are not supported",-        ));-    }-    b.layer = BoardLayerInfo::id_from_name(&e.text.layer).unwrap();-    let t = b-        .text-        .as_mut()-        .ok_or_else(|| RoutingError::new("field_unavailable", "Native field has no text"))?;-    if t.text != e.text.text {-        return Err(RoutingError::new(-            "field_identity_mismatch",-            "Native field text differs from the candidate",-        ));-    }-    let p = t.position.get_or_insert_with(Default::default);-    p.x_nm = nm(e.text.x);-    p.y_nm = nm(e.text.y);-    let a = t.attributes.get_or_insert_with(Default::default);-    if a.bold-        || a.italic-        || a.underlined-        || (!a.font_name.is_empty() && a.font_name != "KiCad Font")-    {-        return Err(RoutingError::new(-            "field_style_unsupported",-            "Only plain native stroke-font fields are supported",-        ));-    }-    a.horizontal_alignment = match e.text.align.as_str() {-        "left" => 1,-        "right" => 3,-        _ => 2,-    };-    a.vertical_alignment = 2;-    a.angle.get_or_insert_with(Default::default).value_degrees = e.text.rotation;-    a.line_spacing = 1.;-    a.stroke_width.get_or_insert_with(Default::default).value_nm = nm(e.text.stroke);-    let size = a.size.get_or_insert_with(Default::default);-    size.x_nm = nm(e.text.width);-    size.y_nm = nm(e.text.height);-    a.mirrored = e.text.mirrored;-    a.multiline = t.text.contains('\n');-    Ok(EditablePcbItem::Field(field))-}--pub fn silk_fields_batch(ctx: &Ctx, args: &Value) -> RResult<Value> {-    if args["expectedRevision"]-        .as_str()-        .filter(|s| !s.is_empty())-        .is_none()-    {-        return Err(RoutingError::new(-            "revision_required",-            "Read the board revision before editing fields",-        ));-    }-    let s = connect(ctx, args)?;-    let (text, _, revision) = s.snapshot()?;-    check_revision(args, &revision)?;-    let plan = fields::prepare(&text, args)?;-    let ids: Vec<_> = plan.edits.iter().map(|e| e.text.id.clone()).collect();-    let native = s-        .client-        .get_editable_items_by_id(ids.clone())-        .map_err(map_err)?;-    let mut updates = Vec::new();-    for e in &plan.edits {-        let f = native-            .iter()-            .find(|f| id(f) == Some(e.text.id.as_str()))-            .ok_or_else(|| {-                RoutingError::new(-                    "native_field_unavailable",-                    "KiCad did not return the exact nested field UUID; no whole-footprint fallback",-                )-            })?;-        let EditablePcbItem::Field(f) = f else {-            unreachable!()-        };-        updates.push(apply_geometry(f.clone(), e)?);-    }-    let before = drc_snapshot(ctx.kicad_cli.as_deref(), &s.source_path(), &text)?;-    let after = drc_snapshot(ctx.kicad_cli.as_deref(), &s.source_path(), &plan.candidate)?;-    let all = |mut v: Value| {-        if let Some(a) = v["violations"].as_array_mut() {-            for x in a {-                x["severity"] = json!("error");-            }-        }-        v-    };-    let added = new_errors(&all(before), &all(after.clone()))?;-    if !added.is_empty() {-        return Err(-            RoutingError::new("drc_rejected", "Field geometry adds native DRC findings")-                .with("violations", json!(added))-                .with("mutated", json!(false)),-        );-    }-    if args["dryRun"] == true {-        return Ok(-            json!({"success":true,"mutated":false,"revision":revision,"drc":after,"updatedIds":ids}),-        );-    }-    check_revision(args, &s.revision()?)?;-    transaction(&s, "Adom reference/value fields", || {-        let reply = s.client.update_editable_items(updates.clone())?;-        let actual: HashSet<_> = reply.iter().filter_map(id).collect();-        if actual != ids.iter().map(String::as_str).collect() {-            return Err(IpcFailure::from(-                "Native field update did not preserve all field UUIDs".to_string(),-            ));-        }-        Ok(())-    })?;-    let mut out = json!({"success":true,"committed":true,"mutated":true,"undoSteps":1,"updatedIds":ids,"footprintIds":plan.edits.iter().map(|e|&e.footprint_id).collect::<Vec<_>>(),"saved":false,"drc":after,"_hint":"Only nested reference/value fields were updated; no whole footprint replacement. Inspect postCommit errors before any retry, then refresh the exact linked views and inspect the board."});-    match s.client.get_editable_items_by_id(ids.clone()) {-        Ok(actual) => {-            let matches = updates.iter().all(|want| {-                actual.iter().any(|got| {-                    id(got) == id(want) && got.clone().into_any() == want.clone().into_any()-                })-            });-            out["fieldsVerified"] = json!(matches);-            if !matches {-                out["success"] = json!(false);-                out["postCommitFieldError"]=json!("Native field readback differs from requested geometry or preserved content; inspect before retrying");-            }-        }-        Err(e) => {-            out["success"] = json!(false);-            out["postCommitFieldError"] = json!(e.to_string());-        }-    }-    match s.snapshot() {-        Ok((current, _, rev)) => {-            out["revision"] = json!(rev);-            let set = ids.iter().cloned().collect();-            let preserved = match (-                fields::preserved_geometry(&text, &set),-                fields::preserved_geometry(&current, &set),-            ) {-                (Ok(before), Ok(after)) => before == after,-                _ => false,-            };-            out["otherBoardDataVerified"] = json!(preserved);-            if !preserved {-                out["success"] = json!(false);-                out["postCommitPreservationError"]=json!("Board data outside the requested fields changed; this may also indicate concurrent editing");-            }-        }-        Err(e) => {-            out["success"] = json!(false);-            out["postCommitReadbackError"] = json!(e.message);-        }-    }-    match s.client.get_item_bounding_boxes(ids,false){-        Ok(rows)=>out["bounds"]=json!(rows.iter().map(|b|json!({"id":b.item_id,"boxMm":[b.x_nm as f64/1e6,b.y_nm as f64/1e6,(b.x_nm+b.width_nm) as f64/1e6,(b.y_nm+b.height_nm) as f64/1e6]})).collect::<Vec<_>>()),-        Err(e)=>{out["success"]=json!(false);out["postCommitBoundsError"]=json!(e.to_string());}-    }-    if args["save"] == true && out["success"] == true {-        match s.client.save_document() {-            Ok(()) => out["saved"] = json!(true),-            Err(e) => {-                out["success"] = json!(false);-                out["postCommitSaveError"] = json!(e.to_string());-            }-        }-    }-    Ok(out)-}--#[cfg(test)]-mod tests {-    use super::*;-    #[test]-    fn nested_field_uuid_and_content_survive_geometry_update() {-        let mut f = FieldItem::from_proto(Default::default());-        let p = f.proto_mut();-        p.name = "Reference".into();-        p.id = Some(Default::default());-        p.visible = true;-        let b = p.text.get_or_insert_with(Default::default);-        b.id.get_or_insert_with(Default::default).value = "field-id".into();-        b.locked = 1;-        let text = b.text.get_or_insert_with(Default::default);-        text.text = "R1".into();-        text.hyperlink = "preserve-me".into();-        let e=fields::Edit{text:crate::silk_text::Text::parse(&json!({"text":"R1","layer":"B.SilkS","x":12.,"y":19.,"rotation":90.,"height":0.7,"width":0.6,"stroke":0.1,"align":"right"}),"field-id".into()).unwrap(),visible:false,footprint_id:"parent".into(),name:"Reference".into()};-        let result = apply_geometry(f, &e).unwrap();-        assert_eq!(id(&result), Some("field-id"));-        let EditablePcbItem::Field(field) = result else {-            panic!("not a field")-        };-        let p = field.proto();-        assert_eq!(p.name, "Reference");-        assert!(!p.visible);-        assert_eq!(p.id.as_ref().unwrap().id, 0);-        let b = p.text.as_ref().unwrap();-        let t = b.text.as_ref().unwrap();-        assert_eq!(t.text, "R1");-        assert_eq!(t.hyperlink, "preserve-me");-        assert_eq!(t.position.as_ref().unwrap().x_nm, 12_000_000);-        assert_eq!(b.layer, BoardLayerInfo::id_from_name("B.SilkS").unwrap());-        let a = t.attributes.as_ref().unwrap();-        assert_eq!(a.horizontal_alignment, 3);-        assert!(a.mirrored);-        assert_eq!(a.size.as_ref().unwrap().y_nm, 700_000);-        let mut bold = field.clone();-        bold.proto_mut()-            .text-            .as_mut()-            .unwrap()-            .text-            .as_mut()-            .unwrap()-            .attributes-            .as_mut()-            .unwrap()-            .bold = true;-        assert!(apply_geometry(bold, &e).is_err());-    }-}