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
+184
-132
@@ -16,9 +16,9 @@
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::io::line_read::{lines_capped, MAX_LINE_BYTES};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::io::Write;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde_json::{json, Value};
|
||||
@@ -202,9 +202,7 @@ fn serve_socket_with_idle(
|
||||
|
||||
/// The entities inside block definitions: owned by (or listed in) a block
|
||||
/// record that is not a layout's model or paper space.
|
||||
fn definition_members(
|
||||
document: &codec::CadDocument,
|
||||
) -> std::collections::HashSet<codec::Handle> {
|
||||
fn definition_members(document: &codec::CadDocument) -> std::collections::HashSet<codec::Handle> {
|
||||
let mut layouts: std::collections::HashSet<codec::Handle> = document
|
||||
.objects
|
||||
.values()
|
||||
@@ -297,7 +295,9 @@ pub(crate) fn entity_json(e: &codec::EntityType, detail: &str) -> Value {
|
||||
map.insert("value".into(), json!(t.value));
|
||||
map.insert(
|
||||
"text".into(),
|
||||
json!(crate::entities::text_support::resolve_dxf_special_chars(&t.value)),
|
||||
json!(crate::entities::text_support::resolve_dxf_special_chars(
|
||||
&t.value
|
||||
)),
|
||||
);
|
||||
map.insert("position".into(), v3(t.insertion_point));
|
||||
map.insert("height".into(), json!(t.height));
|
||||
@@ -306,8 +306,7 @@ pub(crate) fn entity_json(e: &codec::EntityType, detail: &str) -> Value {
|
||||
map.insert("value".into(), json!(t.value));
|
||||
map.insert(
|
||||
"text".into(),
|
||||
json!(codec::entities::mtext_format::parse_mtext(&t.value, true)
|
||||
.to_plain_text()),
|
||||
json!(codec::entities::mtext_format::parse_mtext(&t.value, true).to_plain_text()),
|
||||
);
|
||||
map.insert("position".into(), v3(t.insertion_point));
|
||||
map.insert("height".into(), json!(t.height));
|
||||
@@ -341,13 +340,11 @@ pub(crate) fn entity_json(e: &codec::EntityType, detail: &str) -> Value {
|
||||
.edges
|
||||
.iter()
|
||||
.filter_map(|edge| match edge {
|
||||
codec::entities::BoundaryEdge::Polyline(polyline) => Some(
|
||||
json!(polyline
|
||||
.vertices
|
||||
.iter()
|
||||
.map(|v| [v.x, v.y])
|
||||
.collect::<Vec<_>>()),
|
||||
),
|
||||
codec::entities::BoundaryEdge::Polyline(polyline) => Some(json!(polyline
|
||||
.vertices
|
||||
.iter()
|
||||
.map(|v| [v.x, v.y])
|
||||
.collect::<Vec<_>>())),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
@@ -435,7 +432,11 @@ pub(super) fn requested_save_target(
|
||||
let requested_format = match req["target_format"].as_str() {
|
||||
Some(value) if value.eq_ignore_ascii_case("dxf") => Some("dxf".to_string()),
|
||||
Some(value) if value.eq_ignore_ascii_case("dwg") => Some("dwg".to_string()),
|
||||
Some(value) => return Err(format!("unsupported target format {value:?}; use dwg or dxf")),
|
||||
Some(value) => {
|
||||
return Err(format!(
|
||||
"unsupported target format {value:?}; use dwg or dxf"
|
||||
))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
if let (Some(requested), Some(extension)) = (&requested_format, &path_format) {
|
||||
@@ -485,7 +486,9 @@ fn audit_ascii_dxf_references(path: &std::path::Path) -> Result<Value, String> {
|
||||
let text = String::from_utf8_lossy(&bytes).replace("\r\n", "\n");
|
||||
let lines: Vec<&str> = text.lines().collect();
|
||||
if lines.len() % 2 != 0 {
|
||||
return Ok(json!({"ok":false,"malformed_pairs":true,"duplicate_handles":[],"dangling_handles":[]}));
|
||||
return Ok(
|
||||
json!({"ok":false,"malformed_pairs":true,"duplicate_handles":[],"dangling_handles":[]}),
|
||||
);
|
||||
}
|
||||
let mut declared = HashSet::from(["0".to_string()]);
|
||||
let mut duplicate = std::collections::BTreeSet::new();
|
||||
@@ -495,7 +498,9 @@ fn audit_ascii_dxf_references(path: &std::path::Path) -> Result<Value, String> {
|
||||
let mut variable = None;
|
||||
for pair in lines.chunks_exact(2) {
|
||||
let Ok(code) = pair[0].trim().parse::<i32>() else {
|
||||
return Ok(json!({"ok":false,"malformed_pairs":true,"duplicate_handles":[],"dangling_handles":[]}));
|
||||
return Ok(
|
||||
json!({"ok":false,"malformed_pairs":true,"duplicate_handles":[],"dangling_handles":[]}),
|
||||
);
|
||||
};
|
||||
let value = pair[1].trim().to_ascii_uppercase();
|
||||
pairs.push((code, value.clone()));
|
||||
@@ -983,23 +988,16 @@ impl OpenCADStudio {
|
||||
Ok(target) => target,
|
||||
Err(error) => return err(format!("save: {error}")),
|
||||
};
|
||||
let dropped = crate::io::dropped_on_save_count(
|
||||
&self.tabs[i].scene.document,
|
||||
version,
|
||||
is_dxf,
|
||||
);
|
||||
let dropped =
|
||||
crate::io::dropped_on_save_count(&self.tabs[i].scene.document, version, is_dxf);
|
||||
if dropped > 0 && req["allow_lossy"].as_bool() != Some(true) {
|
||||
return err(format!(
|
||||
"save: conversion would drop {dropped} unsupported record(s); set allow_lossy=true to acknowledge"
|
||||
));
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let result = self.save_tab_synchronously_protected_as(
|
||||
i,
|
||||
path.clone(),
|
||||
version,
|
||||
true,
|
||||
);
|
||||
let result =
|
||||
self.save_tab_synchronously_protected_as(i, path.clone(), version, true);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let result = crate::io::save(&self.tabs[i].scene.document, &path)
|
||||
.map_err(crate::io::SaveFailure::other);
|
||||
@@ -1167,8 +1165,18 @@ impl OpenCADStudio {
|
||||
let offset = req["offset"].as_u64().unwrap_or(0) as usize;
|
||||
|
||||
const WHERE_OPS: &[&str] = &[
|
||||
"eq", "ne", "lt", "lte", "gt", "gte", "contains",
|
||||
"starts_with", "ends_with", "in", "exists", "not_exists",
|
||||
"eq",
|
||||
"ne",
|
||||
"lt",
|
||||
"lte",
|
||||
"gt",
|
||||
"gte",
|
||||
"contains",
|
||||
"starts_with",
|
||||
"ends_with",
|
||||
"in",
|
||||
"exists",
|
||||
"not_exists",
|
||||
];
|
||||
if let Some(filters) = req["where"].as_array() {
|
||||
for filter in filters {
|
||||
@@ -1202,7 +1210,9 @@ impl OpenCADStudio {
|
||||
// Filters address with RFC 6901 pointers, the
|
||||
// same contract as the records op.
|
||||
let properties = serde_json::to_value(e).ok().and_then(|wrapper| {
|
||||
wrapper.as_object().and_then(|object| object.values().next().cloned())
|
||||
wrapper
|
||||
.as_object()
|
||||
.and_then(|object| object.values().next().cloned())
|
||||
});
|
||||
let mut matches = true;
|
||||
for filter in filters {
|
||||
@@ -1210,7 +1220,9 @@ impl OpenCADStudio {
|
||||
let actual = if path.is_empty() {
|
||||
properties.as_ref()
|
||||
} else {
|
||||
properties.as_ref().and_then(|properties| properties.pointer(path))
|
||||
properties
|
||||
.as_ref()
|
||||
.and_then(|properties| properties.pointer(path))
|
||||
};
|
||||
match crate::app::record_api::compare(
|
||||
actual,
|
||||
@@ -1230,7 +1242,8 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
if let Some(bounds) = bounds {
|
||||
let (min, max) = crate::scene::convert::tess::entity_bounds_in(&tab.scene.document, e);
|
||||
let (min, max) =
|
||||
crate::scene::convert::tess::entity_bounds_in(&tab.scene.document, e);
|
||||
if max[0] < bounds[0]
|
||||
|| max[1] < bounds[1]
|
||||
|| min[0] > bounds[2]
|
||||
@@ -1312,15 +1325,11 @@ impl OpenCADStudio {
|
||||
.as_str()
|
||||
.map(std::path::Path::new)
|
||||
.or(tab.current_path.as_deref());
|
||||
let (target_version, target_is_dxf) = match requested_save_target(
|
||||
req,
|
||||
document.version,
|
||||
source_is_dxf,
|
||||
path,
|
||||
) {
|
||||
Ok(target) => target,
|
||||
Err(error) => return err(format!("audit: {error}")),
|
||||
};
|
||||
let (target_version, target_is_dxf) =
|
||||
match requested_save_target(req, document.version, source_is_dxf, path) {
|
||||
Ok(target) => target,
|
||||
Err(error) => return err(format!("audit: {error}")),
|
||||
};
|
||||
|
||||
let declared_layers: HashSet<String> = document
|
||||
.layers
|
||||
@@ -1382,14 +1391,12 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
let dropped = crate::io::dropped_on_save_count(
|
||||
document,
|
||||
target_version,
|
||||
target_is_dxf,
|
||||
);
|
||||
let dropped = crate::io::dropped_on_save_count(document, target_version, target_is_dxf);
|
||||
let mut issues = Vec::new();
|
||||
if !missing_layers.is_empty() {
|
||||
issues.push(json!({"severity":"error","code":"undeclared_layer","values":missing_layers}));
|
||||
issues.push(
|
||||
json!({"severity":"error","code":"undeclared_layer","values":missing_layers}),
|
||||
);
|
||||
}
|
||||
if !missing_blocks.is_empty() {
|
||||
issues.push(json!({"severity":"error","code":"missing_block","values":missing_blocks}));
|
||||
@@ -1401,7 +1408,9 @@ impl OpenCADStudio {
|
||||
issues.push(json!({"severity":"error","code":"non_serializable_record","values":serialization_errors}));
|
||||
}
|
||||
if !non_finite_bounds.is_empty() {
|
||||
issues.push(json!({"severity":"error","code":"non_finite_bounds","handles":non_finite_bounds}));
|
||||
issues.push(
|
||||
json!({"severity":"error","code":"non_finite_bounds","handles":non_finite_bounds}),
|
||||
);
|
||||
}
|
||||
if dropped > 0 {
|
||||
issues.push(json!({
|
||||
@@ -1430,10 +1439,19 @@ impl OpenCADStudio {
|
||||
"details":source_dxf_structure.clone(),
|
||||
}));
|
||||
}
|
||||
let errors = issues.iter().filter(|issue| issue["severity"] == "error").count();
|
||||
let warnings = issues.iter().filter(|issue| issue["severity"] == "warning").count();
|
||||
let errors = issues
|
||||
.iter()
|
||||
.filter(|issue| issue["severity"] == "error")
|
||||
.count();
|
||||
let warnings = issues
|
||||
.iter()
|
||||
.filter(|issue| issue["severity"] == "warning")
|
||||
.count();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let source_sha256 = tab.current_path.as_deref().filter(|path| path.is_file())
|
||||
let source_sha256 = tab
|
||||
.current_path
|
||||
.as_deref()
|
||||
.filter(|path| path.is_file())
|
||||
.and_then(|path| sha256_file(path).ok());
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let source_sha256: Option<String> = None;
|
||||
@@ -1466,31 +1484,37 @@ impl OpenCADStudio {
|
||||
pub(super) fn save_verified_request(&mut self, req: &Value) -> Result<Value, Value> {
|
||||
let i = self.active_tab;
|
||||
let Some(raw_path) = req["path"].as_str() else {
|
||||
return Err(json!({"ok":false,"status":"failed","code":"path_required","error":"save_verified requires an explicit absolute path"}));
|
||||
return Err(
|
||||
json!({"ok":false,"status":"failed","code":"path_required","error":"save_verified requires an explicit absolute path"}),
|
||||
);
|
||||
};
|
||||
let path = std::path::PathBuf::from(raw_path);
|
||||
if !path.is_absolute() {
|
||||
return Err(json!({"ok":false,"status":"failed","code":"absolute_path_required","error":"save_verified path must be absolute"}));
|
||||
return Err(
|
||||
json!({"ok":false,"status":"failed","code":"absolute_path_required","error":"save_verified path must be absolute"}),
|
||||
);
|
||||
}
|
||||
let extension = path
|
||||
.extension()
|
||||
.and_then(|value| value.to_str())
|
||||
.map(str::to_ascii_lowercase);
|
||||
if !matches!(extension.as_deref(), Some("dwg" | "dxf")) {
|
||||
return Err(json!({"ok":false,"status":"failed","code":"unsupported_format","error":"save_verified path must end in .dwg or .dxf"}));
|
||||
return Err(
|
||||
json!({"ok":false,"status":"failed","code":"unsupported_format","error":"save_verified path must end in .dwg or .dxf"}),
|
||||
);
|
||||
}
|
||||
if path.exists() && req["overwrite"].as_bool() != Some(true) {
|
||||
return Err(json!({"ok":false,"status":"failed","code":"destination_exists","error":"destination exists; set overwrite=true to replace it"}));
|
||||
return Err(
|
||||
json!({"ok":false,"status":"failed","code":"destination_exists","error":"destination exists; set overwrite=true to replace it"}),
|
||||
);
|
||||
}
|
||||
let document = &self.tabs[i].scene.document;
|
||||
let source_is_dxf = crate::io::source_is_dxf(self.tabs[i].current_path.as_deref(), document);
|
||||
let (version, is_dxf) = requested_save_target(
|
||||
req,
|
||||
document.version,
|
||||
source_is_dxf,
|
||||
Some(&path),
|
||||
)
|
||||
.map_err(|error| json!({"ok":false,"status":"failed","code":"invalid_target","error":error}))?;
|
||||
let source_is_dxf =
|
||||
crate::io::source_is_dxf(self.tabs[i].current_path.as_deref(), document);
|
||||
let (version, is_dxf) =
|
||||
requested_save_target(req, document.version, source_is_dxf, Some(&path)).map_err(
|
||||
|error| json!({"ok":false,"status":"failed","code":"invalid_target","error":error}),
|
||||
)?;
|
||||
let audit = self.document_audit(req);
|
||||
if audit["summary"]["errors"].as_u64().unwrap_or(0) > 0 {
|
||||
return Err(json!({
|
||||
@@ -1518,19 +1542,24 @@ impl OpenCADStudio {
|
||||
let mut baked_view = snapshot.clone();
|
||||
crate::modules::draw::modify::explode::bake_dimension_blocks(&mut baked_view);
|
||||
let before = document_manifest(&baked_view);
|
||||
crate::io::save_as_version(&snapshot, &path, version)
|
||||
.map_err(|error| json!({
|
||||
crate::io::save_as_version(&snapshot, &path, version).map_err(|error| {
|
||||
json!({
|
||||
"ok":false,"status":"failed","code":"save_failed","error":error,
|
||||
}))?;
|
||||
let sha256 = sha256_file(&path).map_err(|error| json!({
|
||||
"ok":false,"status":"failed","code":"hash_failed","error":error,
|
||||
"saved":path,
|
||||
}))?;
|
||||
})
|
||||
})?;
|
||||
let sha256 = sha256_file(&path).map_err(|error| {
|
||||
json!({
|
||||
"ok":false,"status":"failed","code":"hash_failed","error":error,
|
||||
"saved":path,
|
||||
})
|
||||
})?;
|
||||
let dxf_structure = if is_dxf {
|
||||
Some(audit_ascii_dxf_references(&path).map_err(|error| json!({
|
||||
"ok":false,"status":"failed","code":"dxf_audit_failed","error":error,
|
||||
"saved":path,"sha256":sha256,
|
||||
}))?)
|
||||
Some(audit_ascii_dxf_references(&path).map_err(|error| {
|
||||
json!({
|
||||
"ok":false,"status":"failed","code":"dxf_audit_failed","error":error,
|
||||
"saved":path,"sha256":sha256,
|
||||
})
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -1545,10 +1574,12 @@ impl OpenCADStudio {
|
||||
"target_version":format!("{version:?}"),
|
||||
}));
|
||||
}
|
||||
let reopened = crate::io::load_file(&path).map_err(|error| json!({
|
||||
"ok":false,"status":"failed","code":"reopen_failed","error":error,
|
||||
"saved":path,"sha256":sha256,
|
||||
}))?;
|
||||
let reopened = crate::io::load_file(&path).map_err(|error| {
|
||||
json!({
|
||||
"ok":false,"status":"failed","code":"reopen_failed","error":error,
|
||||
"saved":path,"sha256":sha256,
|
||||
})
|
||||
})?;
|
||||
if reopened.version != version {
|
||||
return Err(json!({
|
||||
"ok":false,"status":"failed","code":"version_mismatch",
|
||||
@@ -1653,7 +1684,8 @@ mod tests {
|
||||
.expect("line")
|
||||
.common_mut()
|
||||
.layer = "NOT_DECLARED".into();
|
||||
let audit = app.automation_op(r#"{"op":"audit","target_format":"dwg","target_version":"R14"}"#);
|
||||
let audit =
|
||||
app.automation_op(r#"{"op":"audit","target_format":"dwg","target_version":"R14"}"#);
|
||||
assert_eq!(audit["ok"], false, "{audit}");
|
||||
assert_eq!(audit["issues"][0]["code"], "undeclared_layer", "{audit}");
|
||||
}
|
||||
@@ -1744,10 +1776,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn raw_dxf_audit_detects_dangling_handle_references() {
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"ocs_dangling_handle_{}.dxf",
|
||||
std::process::id()
|
||||
));
|
||||
let path =
|
||||
std::env::temp_dir().join(format!("ocs_dangling_handle_{}.dxf", std::process::id()));
|
||||
std::fs::write(&path, " 0\nLINE\n 5\n1\n330\n2\n").unwrap();
|
||||
let audit = super::audit_ascii_dxf_references(&path).unwrap();
|
||||
assert_eq!(audit["ok"], false, "{audit}");
|
||||
@@ -1757,10 +1787,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn raw_dxf_audit_marks_binary_input_as_skipped() {
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"ocs_binary_dxf_{}.dxf",
|
||||
std::process::id()
|
||||
));
|
||||
let path = std::env::temp_dir().join(format!("ocs_binary_dxf_{}.dxf", std::process::id()));
|
||||
std::fs::write(&path, b"AutoCAD Binary DXF\r\n\x1a\0").unwrap();
|
||||
let audit = super::audit_ascii_dxf_references(&path).unwrap();
|
||||
assert_eq!(audit["ok"], true, "{audit}");
|
||||
@@ -1770,10 +1797,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn raw_dxf_audit_detects_objects_orphaned_from_the_root_dictionary() {
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"ocs_orphaned_object_{}.dxf",
|
||||
std::process::id()
|
||||
));
|
||||
let path =
|
||||
std::env::temp_dir().join(format!("ocs_orphaned_object_{}.dxf", std::process::id()));
|
||||
std::fs::write(
|
||||
&path,
|
||||
"0\nSECTION\n2\nOBJECTS\n0\nDICTIONARY\n5\nC\n330\n0\n0\nDICTIONARY\n5\n23\n330\nC\n0\nENDSEC\n0\nEOF\n",
|
||||
@@ -1863,9 +1888,8 @@ mod tests {
|
||||
|
||||
let line = app.automation_op(r#"{"op":"run","cmd":"LINE 0,0 200,0"}"#);
|
||||
assert_eq!(line["added"], 1, "{line}");
|
||||
let text = app.automation_op(
|
||||
r#"{"op":"run","cmd":"TEXT 100,135 8 0 OPEN CAD MCP ACCEPTANCE"}"#,
|
||||
);
|
||||
let text =
|
||||
app.automation_op(r#"{"op":"run","cmd":"TEXT 100,135 8 0 OPEN CAD MCP ACCEPTANCE"}"#);
|
||||
assert_eq!(text["added"], 1, "{text}");
|
||||
|
||||
app.tabs[i].scene.selection.borrow_mut().view.vp_size = (1600.0, 800.0);
|
||||
@@ -1963,7 +1987,11 @@ mod tests {
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(texts.len(), 1, "expected exactly one Text entity, got {texts:?}");
|
||||
assert_eq!(
|
||||
texts.len(),
|
||||
1,
|
||||
"expected exactly one Text entity, got {texts:?}"
|
||||
);
|
||||
texts.into_iter().next().unwrap()
|
||||
}
|
||||
|
||||
@@ -2108,8 +2136,7 @@ mod tests {
|
||||
.map(|e| format!("\"{}\"", e["handle"].as_str().unwrap()))
|
||||
.collect();
|
||||
|
||||
let path =
|
||||
std::env::temp_dir().join(format!("ocs_wblock_{}.dxf", std::process::id()));
|
||||
let path = std::env::temp_dir().join(format!("ocs_wblock_{}.dxf", std::process::id()));
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let p = path.to_string_lossy().replace('\\', "\\\\");
|
||||
let r = app.automation_op(&format!(
|
||||
@@ -2141,7 +2168,11 @@ mod tests {
|
||||
let mut line = codec::entities::Line::new();
|
||||
line.start = codec::types::Vector3::new(0.0, 0.0, 0.0);
|
||||
line.end = codec::types::Vector3::new(10.0, 0.0, 0.0);
|
||||
let handle = app.tabs[i].scene.document.add_entity(codec::EntityType::Line(line)).unwrap();
|
||||
let handle = app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.add_entity(codec::EntityType::Line(line))
|
||||
.unwrap();
|
||||
let mut br = codec::tables::BlockRecord::new("A_CPT");
|
||||
br.handle = app.tabs[i].scene.document.allocate_handle();
|
||||
br.entity_handles = vec![handle];
|
||||
@@ -2149,7 +2180,8 @@ mod tests {
|
||||
let state = app.automation_op(r#"{"protocol":1,"op":"state"}"#);
|
||||
let doc = state["document_id"].as_u64().unwrap();
|
||||
|
||||
let path = std::env::temp_dir().join(format!("ocs_wblock_block_{}.dxf", std::process::id()));
|
||||
let path =
|
||||
std::env::temp_dir().join(format!("ocs_wblock_block_{}.dxf", std::process::id()));
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let p = path.to_string_lossy().replace('\\', "\\\\");
|
||||
let r = app.automation_op(&format!(
|
||||
@@ -2214,7 +2246,10 @@ mod tests {
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
let state = app.automation_op(r#"{"protocol":1,"op":"state"}"#);
|
||||
let doc = state["document_id"].as_u64().unwrap();
|
||||
let p = std::env::temp_dir().join("ocs_plot_bad.pdf").to_string_lossy().replace('\\', "\\\\");
|
||||
let p = std::env::temp_dir()
|
||||
.join("ocs_plot_bad.pdf")
|
||||
.to_string_lossy()
|
||||
.replace('\\', "\\\\");
|
||||
let r = app.automation_op(&format!(
|
||||
r#"{{"protocol":1,"op":"plot","request_id":"plot-2","document_id":{doc},"path":"{p}","layout":"NOPE"}}"#
|
||||
));
|
||||
@@ -2232,11 +2267,11 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
let i = app.active_tab;
|
||||
let mtext = codec::MText::with_value(
|
||||
"\\A1;10.5000",
|
||||
codec::types::Vector3::new(10.0, 20.0, 0.0),
|
||||
);
|
||||
app.tabs[i].scene.add_entity(codec::EntityType::MText(mtext));
|
||||
let mtext =
|
||||
codec::MText::with_value("\\A1;10.5000", codec::types::Vector3::new(10.0, 20.0, 0.0));
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.add_entity(codec::EntityType::MText(mtext));
|
||||
|
||||
let q = app.automation_op(
|
||||
r#"{"op":"query","type":"MTEXT","detail":"full","fields":["value","text","height","bounds"]}"#,
|
||||
@@ -2277,7 +2312,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn count_type(app: &mut OpenCADStudio, kind: &str) -> u64 {
|
||||
let q = app.automation_op(&format!(r#"{{"op":"query","type":"{kind}","detail":"summary"}}"#));
|
||||
let q = app.automation_op(&format!(
|
||||
r#"{{"op":"query","type":"{kind}","detail":"summary"}}"#
|
||||
));
|
||||
q["count"].as_u64().unwrap()
|
||||
}
|
||||
|
||||
@@ -2396,8 +2433,8 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
app.automation_op(r#"{"op":"run","cmd":"LINE 0,0 10,0"}"#);
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Line","detail":"summary"}"#)["entities"][0]
|
||||
["handle"]
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Line","detail":"summary"}"#)
|
||||
["entities"][0]["handle"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
@@ -2426,7 +2463,12 @@ mod tests {
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|e| (e["start"][0].as_f64().unwrap(), e["start"][1].as_f64().unwrap()))
|
||||
.map(|e| {
|
||||
(
|
||||
e["start"][0].as_f64().unwrap(),
|
||||
e["start"][1].as_f64().unwrap(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
assert!(starts.contains(&(5.0, 0.0)));
|
||||
assert!(starts.contains(&(5.0, 10.0)));
|
||||
@@ -2437,8 +2479,8 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
app.automation_op(r#"{"op":"run","cmd":"LINE 10,0 20,0"}"#);
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Line","detail":"summary"}"#)["entities"][0]
|
||||
["handle"]
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Line","detail":"summary"}"#)
|
||||
["entities"][0]["handle"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
@@ -2501,8 +2543,8 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
app.automation_op(r#"{"op":"run","cmd":"CIRCLE 0,0 1"}"#);
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)["entities"][0]
|
||||
["handle"]
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)
|
||||
["entities"][0]["handle"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
@@ -2536,8 +2578,8 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
app.automation_op(r#"{"op":"run","cmd":"CIRCLE 5,5 2"}"#);
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)["entities"][0]
|
||||
["handle"]
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)
|
||||
["entities"][0]["handle"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
@@ -2631,8 +2673,14 @@ mod tests {
|
||||
let path = std::env::temp_dir().join(format!("ocs_block_{}.dxf", std::process::id()));
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let p = path.to_string_lossy().replace('\\', "\\\\");
|
||||
assert_eq!(app.automation_op(&format!(r#"{{"op":"save","path":"{p}"}}"#))["ok"], true);
|
||||
assert_eq!(app.automation_op(&format!(r#"{{"op":"open","path":"{p}"}}"#))["ok"], true);
|
||||
assert_eq!(
|
||||
app.automation_op(&format!(r#"{{"op":"save","path":"{p}"}}"#))["ok"],
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
app.automation_op(&format!(r#"{{"op":"open","path":"{p}"}}"#))["ok"],
|
||||
true
|
||||
);
|
||||
assert_eq!(count_type(&mut app, "Insert"), 1);
|
||||
drop(app);
|
||||
let sidecar = path.with_file_name(format!(
|
||||
@@ -2648,8 +2696,8 @@ mod tests {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
app.automation_op(r#"{"op":"new"}"#);
|
||||
app.automation_op(r#"{"op":"run","cmd":"CIRCLE 5,5 2"}"#);
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)["entities"][0]
|
||||
["handle"]
|
||||
let handle = app.automation_op(r#"{"op":"query","type":"Circle","detail":"summary"}"#)
|
||||
["entities"][0]["handle"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
@@ -2930,16 +2978,24 @@ mod tests {
|
||||
}
|
||||
{
|
||||
let sel = app.tabs[i].scene.selection.borrow();
|
||||
assert!(sel.input.left_dragging, "drag must start (add={add} rect={rect})");
|
||||
assert!(
|
||||
sel.input.left_dragging,
|
||||
"drag must start (add={add} rect={rect})"
|
||||
);
|
||||
if rect {
|
||||
// Rectangle mode drives the box machinery, not the lasso.
|
||||
assert!(
|
||||
sel.gesture.box_anchor.is_some() && sel.gesture.box_current.is_some() && !sel.gesture.poly_active,
|
||||
sel.gesture.box_anchor.is_some()
|
||||
&& sel.gesture.box_current.is_some()
|
||||
&& !sel.gesture.poly_active,
|
||||
"rect marquee must arm the box (add={add})"
|
||||
);
|
||||
} else {
|
||||
assert!(sel.gesture.poly_active, "lasso must start (add={add})");
|
||||
assert!(sel.gesture.poly_points.len() >= 3, "lasso points (add={add})");
|
||||
assert!(
|
||||
sel.gesture.poly_points.len() >= 3,
|
||||
"lasso points (add={add})"
|
||||
);
|
||||
}
|
||||
}
|
||||
let _ = app.update(Message::ViewportLeftRelease);
|
||||
@@ -3218,8 +3274,7 @@ mod tests {
|
||||
corrupt.center = codec::types::Vector3::new(1.0, 1.0, 0.0);
|
||||
// An absurd radius is rejected; a zero radius is valid.
|
||||
corrupt.radius = 1.0e11;
|
||||
doc.add_entity(codec::EntityType::Circle(corrupt))
|
||||
.unwrap();
|
||||
doc.add_entity(codec::EntityType::Circle(corrupt)).unwrap();
|
||||
let bytes = crate::io::save_to_bytes(&doc, "dxf", doc.version)
|
||||
.expect("save a document containing a corrupt entity");
|
||||
std::fs::write(&path, bytes).unwrap();
|
||||
@@ -3572,12 +3627,7 @@ mod tests {
|
||||
let listen_bound = bound.clone();
|
||||
std::thread::spawn(move || {
|
||||
let mut app = super::OpenCADStudio::new_for_test();
|
||||
super::serve_socket_with_idle(
|
||||
&mut app,
|
||||
0,
|
||||
&listen_bound,
|
||||
Duration::from_millis(300),
|
||||
);
|
||||
super::serve_socket_with_idle(&mut app, 0, &listen_bound, Duration::from_millis(300));
|
||||
});
|
||||
let mut port = 0;
|
||||
for _ in 0..50 {
|
||||
@@ -3613,7 +3663,9 @@ mod tests {
|
||||
.expect("read timeout");
|
||||
let mut reader2 = BufReader::new(second.try_clone().expect("clone"));
|
||||
let mut banner2 = String::new();
|
||||
reader2.read_line(&mut banner2).expect("second ready banner");
|
||||
reader2
|
||||
.read_line(&mut banner2)
|
||||
.expect("second ready banner");
|
||||
assert!(banner2.contains("ready"), "{banner2}");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user