forked from 1b-agent/opencadstudio-upstream
style: apply cargo fmt across workspace
This commit is contained in:
1 parent
85710e5454
commit
9cf9ff2c5c
531 files changed
+57740
-33906
No files matched your search
+320
-105
@@ -4,8 +4,8 @@
|
||||
use serde_json::{json, Map, Value};
|
||||
|
||||
pub const TARGET_VERSIONS: &[&str] = &[
|
||||
"R14", "2000", "2004", "2007", "2010", "2013", "2018",
|
||||
"AC1014", "AC1015", "AC1018", "AC1021", "AC1024", "AC1027", "AC1032",
|
||||
"R14", "2000", "2004", "2007", "2010", "2013", "2018", "AC1014", "AC1015", "AC1018", "AC1021",
|
||||
"AC1024", "AC1027", "AC1032",
|
||||
];
|
||||
|
||||
pub const ENVELOPE_KEYS: &[&str] = &[
|
||||
@@ -72,11 +72,21 @@ pub struct OpDef {
|
||||
}
|
||||
|
||||
const fn req(name: &'static str, ty: Ty, doc: &'static str) -> Param {
|
||||
Param { name, ty, required: true, doc }
|
||||
Param {
|
||||
name,
|
||||
ty,
|
||||
required: true,
|
||||
doc,
|
||||
}
|
||||
}
|
||||
|
||||
const fn opt(name: &'static str, ty: Ty, doc: &'static str) -> Param {
|
||||
Param { name, ty, required: false, doc }
|
||||
Param {
|
||||
name,
|
||||
ty,
|
||||
required: false,
|
||||
doc,
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -87,9 +97,11 @@ pub static NEW: OpDef = OpDef {
|
||||
name: "new",
|
||||
doc: "Start an empty document, optionally seeded from a DWG/DXF/DWT template.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("template", Ty::Str, "Optional template drawing path whose styles and tables survive."),
|
||||
],
|
||||
params: &[opt(
|
||||
"template",
|
||||
Ty::Str,
|
||||
"Optional template drawing path whose styles and tables survive.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"new"}"#,
|
||||
};
|
||||
@@ -98,9 +110,7 @@ pub static OPEN: OpDef = OpDef {
|
||||
name: "open",
|
||||
doc: "Open an existing drawing file (DWG or DXF).",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("path", Ty::Str, "Absolute path to the drawing file."),
|
||||
],
|
||||
params: &[req("path", Ty::Str, "Absolute path to the drawing file.")],
|
||||
rules: &[],
|
||||
example: r#"{"op":"open","path":"drawing.dxf"}"#,
|
||||
};
|
||||
@@ -109,9 +119,11 @@ pub static ACTIVATE: OpDef = OpDef {
|
||||
name: "activate",
|
||||
doc: "Switch the active drawing tab to another open document.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("document_id", Ty::Int, "Target document ID to activate."),
|
||||
],
|
||||
params: &[req(
|
||||
"document_id",
|
||||
Ty::Int,
|
||||
"Target document ID to activate.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"activate","document_id":1}"#,
|
||||
};
|
||||
@@ -120,20 +132,21 @@ pub static SWITCH_DOCUMENT: OpDef = OpDef {
|
||||
name: "switch_document",
|
||||
doc: "Alias for activate. Switch the active drawing tab to another open document.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("document_id", Ty::Int, "Target document ID to activate."),
|
||||
],
|
||||
params: &[req(
|
||||
"document_id",
|
||||
Ty::Int,
|
||||
"Target document ID to activate.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"switch_document","document_id":1}"#,
|
||||
};
|
||||
|
||||
pub static RUN: OpDef = OpDef {
|
||||
name: "run",
|
||||
doc: "Execute a command string with prompt answers separated by spaces (e.g. 'LINE 0,0 10,10').",
|
||||
doc:
|
||||
"Execute a command string with prompt answers separated by spaces (e.g. 'LINE 0,0 10,10').",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("cmd", Ty::Str, "Command name and arguments."),
|
||||
],
|
||||
params: &[req("cmd", Ty::Str, "Command name and arguments.")],
|
||||
rules: &[],
|
||||
example: r#"{"op":"run","cmd":"LINE 0,0 10,10"}"#,
|
||||
};
|
||||
@@ -142,9 +155,7 @@ pub static START: OpDef = OpDef {
|
||||
name: "start",
|
||||
doc: "Start an interactive command waiting for subsequent 'input' steps.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("cmd", Ty::Str, "Command name to start."),
|
||||
],
|
||||
params: &[req("cmd", Ty::Str, "Command name to start.")],
|
||||
rules: &[],
|
||||
example: r#"{"op":"start","cmd":"LINE"}"#,
|
||||
};
|
||||
@@ -154,17 +165,53 @@ pub static INPUT: OpDef = OpDef {
|
||||
doc: "Feed the next step input to an active command.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("kind", Ty::Enum(&["text", "token", "point", "entity", "structure", "selection", "enter"]), "Input kind."),
|
||||
req(
|
||||
"kind",
|
||||
Ty::Enum(&[
|
||||
"text",
|
||||
"token",
|
||||
"point",
|
||||
"entity",
|
||||
"structure",
|
||||
"selection",
|
||||
"enter",
|
||||
]),
|
||||
"Input kind.",
|
||||
),
|
||||
opt("text", Ty::Str, "Free text or token option."),
|
||||
opt("point", Ty::Point, "Point coordinates."),
|
||||
opt("space", Ty::Enum(&["wcs", "ucs", "relative"]), "Coordinate space for point (defaults to wcs)."),
|
||||
opt("handle", Ty::Handle, "Target entity handle for entity/structure pick."),
|
||||
opt(
|
||||
"space",
|
||||
Ty::Enum(&["wcs", "ucs", "relative"]),
|
||||
"Coordinate space for point (defaults to wcs).",
|
||||
),
|
||||
opt(
|
||||
"handle",
|
||||
Ty::Handle,
|
||||
"Target entity handle for entity/structure pick.",
|
||||
),
|
||||
],
|
||||
rules: &[
|
||||
Rule::RequiredWhen { key: "kind", equals: "token", then: &["text"] },
|
||||
Rule::RequiredWhen { key: "kind", equals: "point", then: &["point"] },
|
||||
Rule::RequiredWhen { key: "kind", equals: "entity", then: &["handle", "point"] },
|
||||
Rule::RequiredWhen { key: "kind", equals: "structure", then: &["handle", "point"] },
|
||||
Rule::RequiredWhen {
|
||||
key: "kind",
|
||||
equals: "token",
|
||||
then: &["text"],
|
||||
},
|
||||
Rule::RequiredWhen {
|
||||
key: "kind",
|
||||
equals: "point",
|
||||
then: &["point"],
|
||||
},
|
||||
Rule::RequiredWhen {
|
||||
key: "kind",
|
||||
equals: "entity",
|
||||
then: &["handle", "point"],
|
||||
},
|
||||
Rule::RequiredWhen {
|
||||
key: "kind",
|
||||
equals: "structure",
|
||||
then: &["handle", "point"],
|
||||
},
|
||||
],
|
||||
example: r#"{"op":"input","kind":"point","point":[10,20]}"#,
|
||||
};
|
||||
@@ -219,7 +266,11 @@ pub static PROPERTY: OpDef = OpDef {
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("field", Ty::Str, "Property field name."),
|
||||
req("value", Ty::Raw(r#"{"description":"New property value"}"#), "New value for the field."),
|
||||
req(
|
||||
"value",
|
||||
Ty::Raw(r#"{"description":"New property value"}"#),
|
||||
"New value for the field.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"property","field":"color","value":1}"#,
|
||||
@@ -257,7 +308,13 @@ pub static SET_PROPERTIES: OpDef = OpDef {
|
||||
params: &[
|
||||
req("collection", Ty::Str, "Record collection name."),
|
||||
opt("handle", Ty::Handle, "Target record handle if applicable."),
|
||||
req("updates", Ty::ArrayOf(&Ty::Raw(r#"{"type":"object","properties":{"path":{"type":"string"},"value":{},"expected":{}},"required":["path","value"]}"#)), "List of pointer replacements."),
|
||||
req(
|
||||
"updates",
|
||||
Ty::ArrayOf(&Ty::Raw(
|
||||
r#"{"type":"object","properties":{"path":{"type":"string"},"value":{},"expected":{}},"required":["path","value"]}"#,
|
||||
)),
|
||||
"List of pointer replacements.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"set_properties","collection":"entities","handle":"2A","updates":[{"path":"/common/layer","value":"Walls"}]}"#,
|
||||
@@ -267,9 +324,11 @@ pub static ACTION: OpDef = OpDef {
|
||||
name: "action",
|
||||
doc: "Trigger a named GUI action or dialog command.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("name", Ty::ActionName, "Name of the UI action to execute."),
|
||||
],
|
||||
params: &[req(
|
||||
"name",
|
||||
Ty::ActionName,
|
||||
"Name of the UI action to execute.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"action","name":"zoom_extents"}"#,
|
||||
};
|
||||
@@ -301,8 +360,16 @@ pub static WBLOCK: OpDef = OpDef {
|
||||
req("path", Ty::Str, "Target drawing path for export."),
|
||||
opt("handles", Ty::Handles, "Entity handles to export."),
|
||||
opt("block", Ty::Str, "Block name to export."),
|
||||
opt("template", Ty::Str, "Base template file to carry styles and tables."),
|
||||
opt("normalize", Ty::Bool, "Translate exported entities to origin [0,0,0]."),
|
||||
opt(
|
||||
"template",
|
||||
Ty::Str,
|
||||
"Base template file to carry styles and tables.",
|
||||
),
|
||||
opt(
|
||||
"normalize",
|
||||
Ty::Bool,
|
||||
"Translate exported entities to origin [0,0,0].",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"wblock","path":"part.dwg","handles":["2A"]}"#,
|
||||
@@ -340,9 +407,13 @@ pub static ENTITIES_CREATE: OpDef = OpDef {
|
||||
name: "entities_create",
|
||||
doc: "Create new CAD entities from typed definitions.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("entities", Ty::ArrayOf(&Ty::Raw(r#"{"type":"object","properties":{"type":{"type":"string"}},"required":["type"]}"#)), "List of entity definitions to create."),
|
||||
],
|
||||
params: &[req(
|
||||
"entities",
|
||||
Ty::ArrayOf(&Ty::Raw(
|
||||
r#"{"type":"object","properties":{"type":{"type":"string"}},"required":["type"]}"#,
|
||||
)),
|
||||
"List of entity definitions to create.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"entities_create","entities":[{"type":"Line","start":[0,0],"end":[10,10]}]}"#,
|
||||
};
|
||||
@@ -351,9 +422,11 @@ pub static ENTITIES_DELETE: OpDef = OpDef {
|
||||
name: "entities_delete",
|
||||
doc: "Delete entities by their handles.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("handles", Ty::Handles, "Handles of entities to delete."),
|
||||
],
|
||||
params: &[req(
|
||||
"handles",
|
||||
Ty::Handles,
|
||||
"Handles of entities to delete.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"entities_delete","handles":["2A"]}"#,
|
||||
};
|
||||
@@ -364,21 +437,49 @@ pub static ENTITIES_TRANSFORM: OpDef = OpDef {
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("handles", Ty::Handles, "Entities to transform."),
|
||||
opt("action", Ty::EnumCi(&["move", "copy", "rotate", "scale", "mirror", "array"]), "Transform action (defaults to move)."),
|
||||
opt("vector", Ty::Point, "move/copy: displacement [dx, dy] or [dx, dy, dz]."),
|
||||
opt(
|
||||
"action",
|
||||
Ty::EnumCi(&["move", "copy", "rotate", "scale", "mirror", "array"]),
|
||||
"Transform action (defaults to move).",
|
||||
),
|
||||
opt(
|
||||
"vector",
|
||||
Ty::Point,
|
||||
"move/copy: displacement [dx, dy] or [dx, dy, dz].",
|
||||
),
|
||||
opt("center", Ty::Point, "rotate/scale: base point."),
|
||||
opt("angle_deg", Ty::Num, "rotate: angle in degrees CCW."),
|
||||
opt("factor", Ty::Num, "scale: non-zero scale factor."),
|
||||
opt("axis", Ty::ArrayOf(&Ty::Point), "mirror: axis as two points [[x1, y1], [x2, y2]]."),
|
||||
opt("copy", Ty::Bool, "mirror/copy: keep originals and return new copies."),
|
||||
opt(
|
||||
"axis",
|
||||
Ty::ArrayOf(&Ty::Point),
|
||||
"mirror: axis as two points [[x1, y1], [x2, y2]].",
|
||||
),
|
||||
opt(
|
||||
"copy",
|
||||
Ty::Bool,
|
||||
"mirror/copy: keep originals and return new copies.",
|
||||
),
|
||||
opt("rows", Ty::Int, "array: row count (1..100, defaults to 1)."),
|
||||
opt("columns", Ty::Int, "array: column count (1..100, defaults to 1)."),
|
||||
opt(
|
||||
"columns",
|
||||
Ty::Int,
|
||||
"array: column count (1..100, defaults to 1).",
|
||||
),
|
||||
opt("row_spacing", Ty::Num, "array: row spacing."),
|
||||
opt("column_spacing", Ty::Num, "array: column spacing."),
|
||||
],
|
||||
rules: &[
|
||||
Rule::RequiredWhen { key: "action", equals: "scale", then: &["factor"] },
|
||||
Rule::RequiredWhen { key: "action", equals: "mirror", then: &["axis"] },
|
||||
Rule::RequiredWhen {
|
||||
key: "action",
|
||||
equals: "scale",
|
||||
then: &["factor"],
|
||||
},
|
||||
Rule::RequiredWhen {
|
||||
key: "action",
|
||||
equals: "mirror",
|
||||
then: &["axis"],
|
||||
},
|
||||
],
|
||||
example: r#"{"op":"entities_transform","handles":["2A"],"action":"move","vector":[10,0]}"#,
|
||||
};
|
||||
@@ -416,8 +517,16 @@ pub static BLOCK_DEFINE: OpDef = OpDef {
|
||||
req("name", Ty::Str, "Block name."),
|
||||
req("handles", Ty::Handles, "Entities that form the block."),
|
||||
req("base", Ty::Point, "Block origin point."),
|
||||
opt("insert_at", Ty::Point, "Placement coordinates for the replacement Insert reference (defaults to base)."),
|
||||
opt("replace", Ty::Bool, "Overwrite an existing block definition of the same name."),
|
||||
opt(
|
||||
"insert_at",
|
||||
Ty::Point,
|
||||
"Placement coordinates for the replacement Insert reference (defaults to base).",
|
||||
),
|
||||
opt(
|
||||
"replace",
|
||||
Ty::Bool,
|
||||
"Overwrite an existing block definition of the same name.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"block_define","name":"DOOR_90","handles":["2A","2B"],"base":[0,0]}"#,
|
||||
@@ -427,9 +536,7 @@ pub static BLOCK_DELETE: OpDef = OpDef {
|
||||
name: "block_delete",
|
||||
doc: "Delete a block definition and all its child entities and inserts.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("name", Ty::Str, "Block name to delete."),
|
||||
],
|
||||
params: &[req("name", Ty::Str, "Block name to delete.")],
|
||||
rules: &[],
|
||||
example: r#"{"op":"block_delete","name":"DOOR"}"#,
|
||||
};
|
||||
@@ -441,7 +548,13 @@ pub static XDATA_SET: OpDef = OpDef {
|
||||
params: &[
|
||||
req("app", Ty::Str, "Application name."),
|
||||
req("handles", Ty::Handles, "Target entity handles."),
|
||||
opt("data", Ty::ArrayOf(&Ty::Raw(r#"{"type":"object","properties":{"code":{"type":"integer"},"value":{}},"required":["code","value"]}"#)), "Typed XData entries [{code, value}]. Empty list removes app record."),
|
||||
opt(
|
||||
"data",
|
||||
Ty::ArrayOf(&Ty::Raw(
|
||||
r#"{"type":"object","properties":{"code":{"type":"integer"},"value":{}},"required":["code","value"]}"#,
|
||||
)),
|
||||
"Typed XData entries [{code, value}]. Empty list removes app record.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"xdata_set","app":"APP","handles":["2A"],"data":[{"code":1000,"value":"tag"}]}"#,
|
||||
@@ -453,7 +566,11 @@ pub static VIEW_FOCUS: OpDef = OpDef {
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("handles", Ty::Handles, "Entities to focus on."),
|
||||
opt("highlight", Ty::Bool, "Also select the entities (defaults to true)."),
|
||||
opt(
|
||||
"highlight",
|
||||
Ty::Bool,
|
||||
"Also select the entities (defaults to true).",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"view_focus","handles":["2A"]}"#,
|
||||
@@ -464,9 +581,21 @@ pub static ENTITIES_COPY_TO: OpDef = OpDef {
|
||||
doc: "Copy entities from the current document into another open document.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("handles", Ty::Handles, "Entities in the current active document to copy."),
|
||||
opt("target_document_id", Ty::Int, "Target document ID to receive the copied entities."),
|
||||
opt("document_id", Ty::Int, "Deprecated alias for target_document_id."),
|
||||
req(
|
||||
"handles",
|
||||
Ty::Handles,
|
||||
"Entities in the current active document to copy.",
|
||||
),
|
||||
opt(
|
||||
"target_document_id",
|
||||
Ty::Int,
|
||||
"Target document ID to receive the copied entities.",
|
||||
),
|
||||
opt(
|
||||
"document_id",
|
||||
Ty::Int,
|
||||
"Deprecated alias for target_document_id.",
|
||||
),
|
||||
],
|
||||
rules: &[Rule::AnyOf(&["target_document_id", "document_id"])],
|
||||
example: r#"{"op":"entities_copy_to","handles":["2A"],"target_document_id":2}"#,
|
||||
@@ -502,7 +631,11 @@ pub static SELECTION_SET_LOAD: OpDef = OpDef {
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("name", Ty::Str, "Selection set name."),
|
||||
opt("select", Ty::Bool, "Also select the recalled entities in the viewport (defaults to true)."),
|
||||
opt(
|
||||
"select",
|
||||
Ty::Bool,
|
||||
"Also select the recalled entities in the viewport (defaults to true).",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"selection_set_load","name":"Sel1"}"#,
|
||||
@@ -513,11 +646,23 @@ pub static USER_SELECT: OpDef = OpDef {
|
||||
doc: "Prompt the user at the desktop screen to interactively pick entities.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("prompt", Ty::Str, "Prompt text pinned on screen while user picks."),
|
||||
opt("detail", Ty::EnumCi(&["summary", "geometry", "full"]), "Returned entity detail level (defaults to full)."),
|
||||
opt(
|
||||
"prompt",
|
||||
Ty::Str,
|
||||
"Prompt text pinned on screen while user picks.",
|
||||
),
|
||||
opt(
|
||||
"detail",
|
||||
Ty::EnumCi(&["summary", "geometry", "full"]),
|
||||
"Returned entity detail level (defaults to full).",
|
||||
),
|
||||
opt("type", Ty::Str, "Entity type filter."),
|
||||
opt("layer", Ty::Str, "Layer filter."),
|
||||
opt("clear", Ty::Bool, "Clear current selection before pick begins (defaults to true)."),
|
||||
opt(
|
||||
"clear",
|
||||
Ty::Bool,
|
||||
"Clear current selection before pick begins (defaults to true).",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"user_select","prompt":"Pick entities"}"#,
|
||||
@@ -527,9 +672,11 @@ pub static GETPOINT: OpDef = OpDef {
|
||||
name: "getpoint",
|
||||
doc: "Prompt the user at the desktop screen to click one point in the viewport.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("prompt", Ty::Str, "Prompt text displayed while waiting for click."),
|
||||
],
|
||||
params: &[opt(
|
||||
"prompt",
|
||||
Ty::Str,
|
||||
"Prompt text displayed while waiting for click.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"getpoint","prompt":"Click start point"}"#,
|
||||
};
|
||||
@@ -538,9 +685,11 @@ pub static CLOSE: OpDef = OpDef {
|
||||
name: "close",
|
||||
doc: "Close the active drawing document.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("discard", Ty::Bool, "Erase unsaved changes instead of refusing a dirty document."),
|
||||
],
|
||||
params: &[opt(
|
||||
"discard",
|
||||
Ty::Bool,
|
||||
"Erase unsaved changes instead of refusing a dirty document.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"close"}"#,
|
||||
};
|
||||
@@ -550,8 +699,16 @@ pub static SYSVAR: OpDef = OpDef {
|
||||
doc: "Read or write CAD system variables (ltscale, pdmode, pdsize, clayer, etc.).",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("get", Ty::ArrayOf(&Ty::Str), "List of variable names to read."),
|
||||
opt("set", Ty::Raw(r#"{"type":"object","description":"Variable name=value pairs to set"}"#), "Key-value map of variables to set in one undo transaction."),
|
||||
opt(
|
||||
"get",
|
||||
Ty::ArrayOf(&Ty::Str),
|
||||
"List of variable names to read.",
|
||||
),
|
||||
opt(
|
||||
"set",
|
||||
Ty::Raw(r#"{"type":"object","description":"Variable name=value pairs to set"}"#),
|
||||
"Key-value map of variables to set in one undo transaction.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"sysvar","get":["LTSCALE"]}"#,
|
||||
@@ -561,9 +718,7 @@ pub static LAYOUT_CREATE: OpDef = OpDef {
|
||||
name: "layout_create",
|
||||
doc: "Create a new paper-space layout tab.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
req("name", Ty::Str, "Layout tab name."),
|
||||
],
|
||||
params: &[req("name", Ty::Str, "Layout tab name.")],
|
||||
rules: &[],
|
||||
example: r#"{"op":"layout_create","name":"Sheet1"}"#,
|
||||
};
|
||||
@@ -575,17 +730,37 @@ pub static PAGE_SETUP_SET: OpDef = OpDef {
|
||||
params: &[
|
||||
req("layout", Ty::Str, "Target layout name."),
|
||||
opt("paper", Ty::Str, "Paper size name."),
|
||||
opt("orientation", Ty::EnumCi(&["Portrait", "Landscape"]), "Paper orientation."),
|
||||
opt(
|
||||
"orientation",
|
||||
Ty::EnumCi(&["Portrait", "Landscape"]),
|
||||
"Paper orientation.",
|
||||
),
|
||||
opt("fit", Ty::Bool, "Fit to paper (defaults to true)."),
|
||||
opt("scale", Ty::Str, "Paper-to-drawing scale ratio."),
|
||||
opt("center", Ty::Bool, "Center drawing on sheet (defaults to true)."),
|
||||
opt(
|
||||
"center",
|
||||
Ty::Bool,
|
||||
"Center drawing on sheet (defaults to true).",
|
||||
),
|
||||
opt("offset_x", Ty::Num, "X offset in mm."),
|
||||
opt("offset_y", Ty::Num, "Y offset in mm."),
|
||||
opt("plot_style", Ty::Str, "CTB file path or named style."),
|
||||
opt("area", Ty::EnumCi(&["extents", "display", "limits", "layout", "window"]), "Plot area."),
|
||||
opt("window", Ty::Window, "World [x0, y0, x1, y1] rectangle; required when area=window."),
|
||||
opt(
|
||||
"area",
|
||||
Ty::EnumCi(&["extents", "display", "limits", "layout", "window"]),
|
||||
"Plot area.",
|
||||
),
|
||||
opt(
|
||||
"window",
|
||||
Ty::Window,
|
||||
"World [x0, y0, x1, y1] rectangle; required when area=window.",
|
||||
),
|
||||
],
|
||||
rules: &[Rule::RequiredWhen { key: "area", equals: "window", then: &["window"] }],
|
||||
rules: &[Rule::RequiredWhen {
|
||||
key: "area",
|
||||
equals: "window",
|
||||
then: &["window"],
|
||||
}],
|
||||
example: r#"{"op":"page_setup_set","layout":"Sheet1","paper":"A4"}"#,
|
||||
};
|
||||
|
||||
@@ -593,9 +768,11 @@ pub static FILE_IDENTITY: OpDef = OpDef {
|
||||
name: "file_identity",
|
||||
doc: "Inspect or refresh internal drawing UUIDs and fingerprint identity.",
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("renew", Ty::Bool, "Generate fresh document identity tokens."),
|
||||
],
|
||||
params: &[opt(
|
||||
"renew",
|
||||
Ty::Bool,
|
||||
"Generate fresh document identity tokens.",
|
||||
)],
|
||||
rules: &[],
|
||||
example: r#"{"op":"file_identity"}"#,
|
||||
};
|
||||
@@ -606,9 +783,21 @@ pub static SAVE: OpDef = OpDef {
|
||||
batchable: true,
|
||||
params: &[
|
||||
opt("path", Ty::Str, "Destination file path."),
|
||||
opt("target_format", Ty::Enum(&["dwg", "dxf"]), "Target CAD format."),
|
||||
opt("target_version", Ty::Enum(TARGET_VERSIONS), "Target AutoCAD version."),
|
||||
opt("allow_lossy", Ty::Bool, "Acknowledge dropping unsupported passthrough records."),
|
||||
opt(
|
||||
"target_format",
|
||||
Ty::Enum(&["dwg", "dxf"]),
|
||||
"Target CAD format.",
|
||||
),
|
||||
opt(
|
||||
"target_version",
|
||||
Ty::Enum(TARGET_VERSIONS),
|
||||
"Target AutoCAD version.",
|
||||
),
|
||||
opt(
|
||||
"allow_lossy",
|
||||
Ty::Bool,
|
||||
"Acknowledge dropping unsupported passthrough records.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"save"}"#,
|
||||
@@ -620,10 +809,26 @@ pub static SAVE_VERIFIED: OpDef = OpDef {
|
||||
batchable: false,
|
||||
params: &[
|
||||
req("path", Ty::Str, "Destination file path (.dwg or .dxf)."),
|
||||
opt("target_format", Ty::Enum(&["dwg", "dxf"]), "Explicit output format matching extension."),
|
||||
opt("target_version", Ty::Enum(TARGET_VERSIONS), "Explicit CAD version."),
|
||||
opt("allow_lossy", Ty::Bool, "Acknowledge dropping unsupported records."),
|
||||
opt("overwrite", Ty::Bool, "Replace destination if file already exists."),
|
||||
opt(
|
||||
"target_format",
|
||||
Ty::Enum(&["dwg", "dxf"]),
|
||||
"Explicit output format matching extension.",
|
||||
),
|
||||
opt(
|
||||
"target_version",
|
||||
Ty::Enum(TARGET_VERSIONS),
|
||||
"Explicit CAD version.",
|
||||
),
|
||||
opt(
|
||||
"allow_lossy",
|
||||
Ty::Bool,
|
||||
"Acknowledge dropping unsupported records.",
|
||||
),
|
||||
opt(
|
||||
"overwrite",
|
||||
Ty::Bool,
|
||||
"Replace destination if file already exists.",
|
||||
),
|
||||
],
|
||||
rules: &[],
|
||||
example: r#"{"op":"save_verified","path":"drawing.dwg"}"#,
|
||||
@@ -753,7 +958,10 @@ fn rules_text(op: &OpDef) -> String {
|
||||
out.push_str(&format!(" Requires at least one of: {}.", keys.join(", ")));
|
||||
}
|
||||
Rule::RequiredWhen { key, equals, then } => {
|
||||
out.push_str(&format!(" When {key}={equals}, requires: {}.", then.join(", ")));
|
||||
out.push_str(&format!(
|
||||
" When {key}={equals}, requires: {}.",
|
||||
then.join(", ")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -924,8 +1132,7 @@ fn validate_type(ty: &Ty, val: &Value) -> Result<(), String> {
|
||||
return Err("expected array".into());
|
||||
};
|
||||
for (idx, item) in arr.iter().enumerate() {
|
||||
validate_type(inner, item)
|
||||
.map_err(|e| format!("item {idx}: {e}"))?;
|
||||
validate_type(inner, item).map_err(|e| format!("item {idx}: {e}"))?;
|
||||
}
|
||||
}
|
||||
Ty::Raw(_) => {}
|
||||
@@ -933,10 +1140,7 @@ fn validate_type(ty: &Ty, val: &Value) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_request(
|
||||
request: &Value,
|
||||
is_batch_step: bool,
|
||||
) -> Result<ValidationResult, String> {
|
||||
pub fn validate_request(request: &Value, is_batch_step: bool) -> Result<ValidationResult, String> {
|
||||
let Some(obj) = request.as_object() else {
|
||||
return Err("request must be a JSON object".into());
|
||||
};
|
||||
@@ -950,7 +1154,9 @@ pub fn validate_request(
|
||||
};
|
||||
|
||||
if is_batch_step && !op_def.batchable {
|
||||
return Err(format!("operation '{op_name}' cannot be used in a batch step"));
|
||||
return Err(format!(
|
||||
"operation '{op_name}' cannot be used in a batch step"
|
||||
));
|
||||
}
|
||||
|
||||
// Check required params
|
||||
@@ -970,7 +1176,9 @@ pub fn validate_request(
|
||||
for r in op_def.rules {
|
||||
match r {
|
||||
Rule::AnyOf(keys) => {
|
||||
let any_present = keys.iter().any(|k| obj.get(*k).is_some_and(|v| !v.is_null()));
|
||||
let any_present = keys
|
||||
.iter()
|
||||
.any(|k| obj.get(*k).is_some_and(|v| !v.is_null()));
|
||||
if !any_present {
|
||||
return Err(format!(
|
||||
"Missing {} for {}. Example request: {}",
|
||||
@@ -981,7 +1189,10 @@ pub fn validate_request(
|
||||
}
|
||||
}
|
||||
Rule::RequiredWhen { key, equals, then } => {
|
||||
let matches = obj.get(*key).and_then(Value::as_str).is_some_and(|v| v.eq_ignore_ascii_case(equals));
|
||||
let matches = obj
|
||||
.get(*key)
|
||||
.and_then(Value::as_str)
|
||||
.is_some_and(|v| v.eq_ignore_ascii_case(equals));
|
||||
if matches {
|
||||
for req_key in *then {
|
||||
let val = obj.get(*req_key);
|
||||
@@ -1001,9 +1212,8 @@ pub fn validate_request(
|
||||
for p in op_def.params {
|
||||
if let Some(val) = obj.get(p.name) {
|
||||
if !val.is_null() {
|
||||
validate_type(&p.ty, val).map_err(|e| {
|
||||
format!("parameter '{}' for op '{}': {e}", p.name, op_name)
|
||||
})?;
|
||||
validate_type(&p.ty, val)
|
||||
.map_err(|e| format!("parameter '{}' for op '{}': {e}", p.name, op_name))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1020,9 +1230,14 @@ pub fn validate_request(
|
||||
for (k, _) in obj {
|
||||
if !allowed.contains(&k.as_str()) {
|
||||
if k == "data_base64" {
|
||||
warnings.push("data_base64 is supported only in the Web/WASM build, not in native desktop".into());
|
||||
warnings.push(
|
||||
"data_base64 is supported only in the Web/WASM build, not in native desktop"
|
||||
.into(),
|
||||
);
|
||||
} else {
|
||||
warnings.push(format!("unknown parameter '{k}' ignored for op '{op_name}'"));
|
||||
warnings.push(format!(
|
||||
"unknown parameter '{k}' ignored for op '{op_name}'"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user