diff --git a/.gitignore b/.gitignore index 1e7caa9..15e0fe1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Cargo.lock target/ +.vscode/ \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 013552f..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "check", - "type": "shell", - "command": "cargo check", - "group": "build", - "problemMatcher": "$rustc" - }, - { - "label": "build", - "type": "shell", - "command": "cargo build", - "group": "build", - "problemMatcher": "$rustc" - }, - { - "label": "test", - "type": "shell", - "command": "cargo test", - "group": { - "kind": "test", - "isDefault": true - }, - "dependsOn": [ - "build" - ], - "problemMatcher": "$rustc" - } - ] -} \ No newline at end of file diff --git a/build/build.rs b/build/build.rs index cf39fad..26bb1eb 100644 --- a/build/build.rs +++ b/build/build.rs @@ -57,6 +57,6 @@ pub mod tables; fn rerun_if_changed(s: &S) { let s = format!("{:?}", s) .replace("\\\\", "/") // normalize directory separators - .replace("\"", ""); // ignore surrounding quotes + .replace('\"', ""); // ignore surrounding quotes println!("cargo:rerun-if-changed={}", s); } diff --git a/build/entity_generator.rs b/build/entity_generator.rs index 6d29c2d..f4e53b3 100644 --- a/build/entity_generator.rs +++ b/build/entity_generator.rs @@ -43,7 +43,7 @@ use crate::enums::*; use crate::enum_primitive::FromPrimitive; use crate::objects::*; ".trim_start()); - fun.push_str("\n"); + fun.push('\n'); generate_base_entity(&mut fun, &element); generate_entity_types(&mut fun, &element); @@ -62,20 +62,20 @@ use crate::objects::*; fn generate_base_entity(fun: &mut String, element: &Element) { let entity = &element.children[0]; - if name(&entity) != "Entity" { + if name(entity) != "Entity" { panic!("Expected first entity to be 'Entity'."); } fun.push_str("#[derive(Debug, Clone)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); fun.push_str("pub struct EntityCommon {\n"); for c in &entity.children { - let t = if allow_multiples(&c) { + let t = if allow_multiples(c) { format!("Vec<{}>", typ(c)) } else { typ(c) }; - if !comment(&c).is_empty() { - fun.push_str(&format!(" /// {}\n", comment(&c))); + if !comment(c).is_empty() { + fun.push_str(&format!(" /// {}\n", comment(c))); } match &*c.name { "Field" => { @@ -86,7 +86,7 @@ fn generate_base_entity(fun: &mut String, element: &Element) { )); } "Pointer" => { - let typ = if allow_multiples(&c) { + let typ = if allow_multiples(c) { "Vec" } else { "Handle" @@ -104,7 +104,7 @@ fn generate_base_entity(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("#[derive(Debug, Clone)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); @@ -112,7 +112,7 @@ fn generate_base_entity(fun: &mut String, element: &Element) { fun.push_str(" pub common: EntityCommon,\n"); fun.push_str(" pub specific: EntityType,\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("impl Default for EntityCommon {\n"); fun.push_str(" fn default() -> EntityCommon {\n"); @@ -123,7 +123,7 @@ fn generate_base_entity(fun: &mut String, element: &Element) { fun.push_str(&format!( " {name}: {val},\n", name = name(c), - val = default_value(&c) + val = default_value(c) )); } "Pointer" => { @@ -140,14 +140,14 @@ fn generate_base_entity(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("impl EntityCommon {\n"); /////////////////////////////////////////////////////////////////// pointers for p in &entity.children { if p.name == "Pointer" { - fun.push_str(&*methods_for_pointer_access(p)); + fun.push_str(&methods_for_pointer_access(p)); } } @@ -164,10 +164,10 @@ fn generate_base_entity(fun: &mut String, element: &Element) { } else if name(c) == "x_data" && code(c) == 1001 { // handled below: x_data::XDATA_APPLICATIONNAME } else { - let read_fun = if allow_multiples(&c) { - format!(".push({})", field_reader(&c)) + let read_fun = if allow_multiples(c) { + format!(".push({})", field_reader(c)) } else { - format!(" = {}", field_reader(&c)) + format!(" = {}", field_reader(c)) }; fun.push_str(&format!( " {code} => {{ self.{field}{read_fun} }},\n", @@ -179,7 +179,7 @@ fn generate_base_entity(fun: &mut String, element: &Element) { } else if c.name == "Pointer" { fun.push_str(&format!( " {code} => {{ self.__{field}_handle = pair.as_handle()? }},\n", - code = code(&c), + code = code(c), field = name(c) )); } @@ -197,14 +197,14 @@ fn generate_base_entity(fun: &mut String, element: &Element) { ///////////////////////////////////////////////////////////// add_code_pairs fun.push_str(" pub(crate) fn add_code_pairs(&self, pairs: &mut Vec, version: AcadVersion, write_handles: bool) {\n"); fun.push_str(" let ent = self;\n"); - for line in generate_write_code_pairs(&entity) { + for line in generate_write_code_pairs(entity) { fun.push_str(&format!(" {}\n", line)); } fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } fn generate_entity_types(fun: &mut String, element: &Element) { @@ -221,7 +221,7 @@ fn generate_entity_types(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); // individual structs for c in &element.children { @@ -233,18 +233,18 @@ fn generate_entity_types(fun: &mut String, element: &Element) { fun.push_str("#[derive(Clone, Debug, PartialEq)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); fun.push_str(&format!("pub struct {typ} {{\n", typ = name(c))); - if base_class(&c) == "DimensionBase" { + if base_class(c) == "DimensionBase" { fun.push_str(" pub dimension_base: DimensionBase,\n"); } for f in &c.children { - let t = if allow_multiples(&f) { + let t = if allow_multiples(f) { format!("Vec<{}>", typ(f)) } else { typ(f) }; - let is_private = name(f).starts_with("_"); - if !comment(&f).is_empty() { - fun.push_str(&format!(" /// {}\n", comment(&f))); + let is_private = name(f).starts_with('_'); + if !comment(f).is_empty() { + fun.push_str(&format!(" /// {}\n", comment(f))); } if is_private { fun.push_str(" #[doc(hidden)]\n"); @@ -258,7 +258,7 @@ fn generate_entity_types(fun: &mut String, element: &Element) { )); } "Pointer" => { - let typ = if allow_multiples(&f) { + let typ = if allow_multiples(f) { "Vec" } else { "Handle" @@ -276,13 +276,14 @@ fn generate_entity_types(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); // implementation + fun.push_str("#[allow(clippy::derivable_impls)]\n"); fun.push_str(&format!("impl Default for {typ} {{\n", typ = name(c))); fun.push_str(&format!(" fn default() -> {typ} {{\n", typ = name(c))); fun.push_str(&format!(" {typ} {{\n", typ = name(c))); - if base_class(&c) == "DimensionBase" { + if base_class(c) == "DimensionBase" { fun.push_str(" dimension_base: Default::default(),\n"); } for f in &c.children { @@ -291,11 +292,11 @@ fn generate_entity_types(fun: &mut String, element: &Element) { fun.push_str(&format!( " {name}: {val},\n", name = name(f), - val = default_value(&f) + val = default_value(f) )); } "Pointer" => { - let val = if allow_multiples(&f) { + let val = if allow_multiples(f) { "vec![]" } else { "Handle::empty()" @@ -314,20 +315,20 @@ fn generate_entity_types(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); - generate_implementation(fun, &c); + generate_implementation(fun, c); - if name(&c) == "DimensionBase" { + if name(c) == "DimensionBase" { fun.push_str("impl DimensionBase {\n"); fun.push_str(" pub(crate) fn add_code_pairs(&self, pairs: &mut Vec, version: AcadVersion) {\n"); fun.push_str(" let ent = self;\n"); - for line in generate_write_code_pairs(&c) { + for line in generate_write_code_pairs(c) { fun.push_str(&format!(" {}\n", line)); } fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } } @@ -341,15 +342,15 @@ fn generate_implementation(fun: &mut String, element: &Element) { if field.name == "Field" { for flag in &field.children { if flag.name == "Flag" { - let flag_name = name(&flag); - let mask = attr(&flag, "Mask"); + let flag_name = name(flag); + let mask = attr(flag, "Mask"); implementation.push_str(&format!( " pub fn {name}(&self) -> bool {{\n", name = flag_name )); implementation.push_str(&format!( " self.{name} & {mask} != 0\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); @@ -360,14 +361,14 @@ fn generate_implementation(fun: &mut String, element: &Element) { implementation.push_str(" if val {\n"); implementation.push_str(&format!( " self.{name} |= {mask};\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); implementation.push_str(" else {\n"); implementation.push_str(&format!( " self.{name} &= !{mask};\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); @@ -380,15 +381,15 @@ fn generate_implementation(fun: &mut String, element: &Element) { // generate pointer methods for field in &element.children { if field.name == "Pointer" { - implementation.push_str(&*methods_for_pointer_access(field)); + implementation.push_str(&methods_for_pointer_access(field)); } } if !implementation.is_empty() { - fun.push_str(&format!("impl {typ} {{\n", typ = name(&element))); + fun.push_str(&format!("impl {typ} {{\n", typ = name(element))); fun.push_str(&implementation); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } @@ -396,24 +397,21 @@ fn generate_is_supported_on_version(fun: &mut String, element: &Element) { fun.push_str( " pub(crate) fn is_supported_on_version(&self, version: AcadVersion) -> bool {\n", ); - fun.push_str(" match self {\n"); + fun.push_str(" match *self {\n"); for entity in &element.children { - if name(&entity) != "Entity" && name(&entity) != "DimensionBase" { - let mut predicates = vec![]; - if !min_version(&entity).is_empty() { - predicates.push(format!("version >= AcadVersion::{}", min_version(&entity))); - } - if !max_version(&entity).is_empty() { - predicates.push(format!("version <= AcadVersion::{}", max_version(&entity))); - } - let predicate = if predicates.len() == 0 { - String::from("true") - } else { - predicates.join(" && ") + if name(entity) != "Entity" && name(entity) != "DimensionBase" { + let predicate = match (min_version(entity).as_str(), max_version(entity).as_str()) { + ("", "") => "true".into(), + ("", max) => format!("version <= AcadVersion::{max}"), + (min, "") => format!("version >= AcadVersion::{min}"), + (min, max) if min == max => format!("version == AcadVersion::{min}"), + (min, max) => { + format!("version >= AcadVersion::{min} && version <= AcadVersion::{max}") + } }; fun.push_str(&format!( - " &EntityType::{typ}(_) => {{ {predicate} }},\n", - typ = name(&entity), + " EntityType::{typ}(_) => {{ {predicate} }},\n", + typ = name(entity), predicate = predicate )); } @@ -428,10 +426,10 @@ fn generate_type_string(fun: &mut String, element: &Element) { for c in &element.children { if name(c) != "Entity" && name(c) != "DimensionBase" - && base_class(&c) != "DimensionBase" - && !attr(&c, "TypeString").is_empty() + && base_class(c) != "DimensionBase" + && !attr(c, "TypeString").is_empty() { - let type_string = attr(&c, "TypeString"); + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); for t in type_strings { fun.push_str(&format!(" \"{type_string}\" => Some(EntityType::{typ}(Default::default())),\n", type_string=t, typ=name(c))); @@ -444,14 +442,14 @@ fn generate_type_string(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" pub(crate) fn to_type_string(&self) -> &str {\n"); - fun.push_str(" match self {\n"); + fun.push_str(" match *self {\n"); for c in &element.children { // only write the first type string given - let type_string = attr(&c, "TypeString"); + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); if name(c) != "Entity" && name(c) != "DimensionBase" && !type_string.is_empty() { fun.push_str(&format!( - " &EntityType::{typ}(_) => {{ \"{type_string}\" }},\n", + " EntityType::{typ}(_) => {{ \"{type_string}\" }},\n", typ = name(c), type_string = type_strings[0] )); @@ -465,77 +463,80 @@ fn generate_try_apply_code_pair(fun: &mut String, element: &Element) { fun.push_str( " pub(crate) fn try_apply_code_pair(&mut self, pair: &CodePair) -> DxfResult {\n", ); - fun.push_str(" match self {\n"); + fun.push_str(" match *self {\n"); for c in &element.children { if c.name != "Entity" { panic!("expected top level entity"); } if name(c) != "Entity" && name(c) != "DimensionBase" { - if generate_reader_function(&c) { - let ent = if name(&c) == "Seqend" { "_ent" } else { "ent" }; // SEQEND doesn't use this variable + if generate_reader_function(c) { + let ent = if name(c) == "Seqend" { "_ent" } else { "ent" }; // SEQEND doesn't use this variable fun.push_str(&format!( - " &mut EntityType::{typ}(ref mut {ent}) => {{\n", + " EntityType::{typ}(ref mut {ent}) => {{\n", typ = name(c), ent = ent )); - fun.push_str(" match pair.code {\n"); - let mut seen_codes = HashSet::new(); - for f in &c.children { - if f.name == "Field" && generate_reader(&f) { - for (i, &cd) in codes(&f).iter().enumerate() { - if !seen_codes.contains(&cd) { - seen_codes.insert(cd); // TODO: allow for duplicates - let reader = field_reader(&f); - let codes = codes(&f); - let write_cmd = match codes.len() { - 1 => { - let read_fun = if allow_multiples(&f) { - format!(".push({})", reader) - } else { - format!(" = {}", reader) - }; - format!( - "ent.{field}{read_fun}", - field = name(&f), - read_fun = read_fun - ) - } - _ => { - let suffix = match i { - 0 => "x", - 1 => "y", - 2 => "z", - _ => panic!("impossible"), - }; - format!( - "ent.{field}.{suffix} = {reader}", - field = name(&f), - suffix = suffix, - reader = reader - ) - } - }; - fun.push_str(&format!( - " {code} => {{ {cmd}; }},\n", - code = cd, - cmd = write_cmd - )); + if ent == "ent" { + fun.push_str(" match pair.code {\n"); + let mut seen_codes = HashSet::new(); + for f in &c.children { + if f.name == "Field" && generate_reader(f) { + for (i, &cd) in codes(f).iter().enumerate() { + if !seen_codes.contains(&cd) { + seen_codes.insert(cd); // TODO: allow for duplicates + let reader = field_reader(f); + let codes = codes(f); + let write_cmd = match codes.len() { + 1 => { + let read_fun = if allow_multiples(f) { + format!(".push({})", reader) + } else { + format!(" = {}", reader) + }; + format!( + "ent.{field}{read_fun}", + field = name(f), + read_fun = read_fun + ) + } + _ => { + let suffix = match i { + 0 => "x", + 1 => "y", + 2 => "z", + _ => panic!("impossible"), + }; + format!( + "ent.{field}.{suffix} = {reader}", + field = name(f), + suffix = suffix, + reader = reader + ) + } + }; + fun.push_str(&format!( + " {code} => {{ {cmd}; }},\n", + code = cd, + cmd = write_cmd + )); + } + } + } else if f.name == "Pointer" { + if allow_multiples(f) { + fun.push_str(&format!(" {code} => {{ ent.__{field}_handle.push(pair.as_handle()?); }},\n", code=code(f), field=name(f))); + } else { + fun.push_str(&format!(" {code} => {{ ent.__{field}_handle = pair.as_handle()?; }},\n", code=code(f), field=name(f))); } - } - } else if f.name == "Pointer" { - if allow_multiples(&f) { - fun.push_str(&format!(" {code} => {{ ent.__{field}_handle.push(pair.as_handle()?); }},\n", code=code(&f), field=name(&f))); - } else { - fun.push_str(&format!(" {code} => {{ ent.__{field}_handle = pair.as_handle()?; }},\n", code=code(&f), field=name(&f))); } } + fun.push_str(" _ => return Ok(false),\n"); + fun.push_str(" }\n"); + } else { + fun.push_str(" return Ok(false);\n") } - - fun.push_str(" _ => return Ok(false),\n"); - fun.push_str(" }\n"); fun.push_str(" },\n"); } else { - fun.push_str(&format!(" &mut EntityType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom reader\"); }},\n", typ=name(&c))); + fun.push_str(&format!(" EntityType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom reader\"); }},\n", typ=name(c))); } } } @@ -547,27 +548,27 @@ fn generate_try_apply_code_pair(fun: &mut String, element: &Element) { fn generate_get_code_pairs(fun: &mut String, element: &Element) { fun.push_str(" pub(crate) fn add_code_pairs(&self, pairs: &mut Vec, common: &EntityCommon, version: AcadVersion) {\n"); - fun.push_str(" match self {\n"); + fun.push_str(" match *self {\n"); for entity in &element.children { - if name(&entity) != "Entity" && name(&entity) != "DimensionBase" { - if generate_writer_function(&entity) { - let ent = if name(&entity) == "Seqend" { + if name(entity) != "Entity" && name(entity) != "DimensionBase" { + if generate_writer_function(entity) { + let ent = if name(entity) == "Seqend" { "_ent" } else { "ent" }; // SEQEND doesn't use this variable fun.push_str(&format!( - " &EntityType::{typ}(ref {ent}) => {{\n", - typ = name(&entity), + " EntityType::{typ}(ref {ent}) => {{\n", + typ = name(entity), ent = ent )); - for line in generate_write_code_pairs(&entity) { + for line in generate_write_code_pairs(entity) { fun.push_str(&format!(" {}\n", line)); } fun.push_str(" },\n"); } else { - fun.push_str(&format!(" &EntityType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom writer\"); }},\n", typ=name(&entity))); + fun.push_str(&format!(" EntityType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom writer\"); }},\n", typ=name(entity))); } } } @@ -577,7 +578,7 @@ fn generate_get_code_pairs(fun: &mut String, element: &Element) { fn field_with_name<'a>(entity: &'a Element, field_name: &String) -> &'a Element { for field in &entity.children { - if name(&field) == *field_name { + if name(field) == *field_name { return field; } } @@ -591,7 +592,7 @@ fn generate_write_code_pairs(entity: &Element) -> Vec { if f.name == "WriteOrder" { // order was specifically given to us for write_command in &f.children { - for line in generate_write_code_pairs_for_write_order(&entity, &write_command) { + for line in generate_write_code_pairs_for_write_order(entity, write_command) { commands.push(line); } } @@ -600,7 +601,7 @@ fn generate_write_code_pairs(entity: &Element) -> Vec { } // no order given, use declaration order - let subclass = attr(&entity, "SubclassMarker"); + let subclass = attr(entity, "SubclassMarker"); if !subclass.is_empty() { commands.push("if version >= AcadVersion::R13 {".to_string()); commands.push(format!( @@ -610,10 +611,10 @@ fn generate_write_code_pairs(entity: &Element) -> Vec { commands.push("}".to_string()); } for field in &entity.children { - if generate_writer(&field) { + if generate_writer(field) { match &*field.name { "Field" => { - for line in write_lines_for_field(&field, vec![]) { + for line in write_lines_for_field(field, vec![]) { commands.push(line); } } @@ -624,7 +625,7 @@ fn generate_write_code_pairs(entity: &Element) -> Vec { } } } - return commands; + commands } fn generate_write_code_pairs_for_write_order( @@ -635,70 +636,70 @@ fn generate_write_code_pairs_for_write_order( match &*write_command.name { "WriteField" => { let field_name = write_command.attributes.get("Field").unwrap(); - let field = field_with_name(&entity, &field_name); + let field = field_with_name(entity, field_name); let normalized_field_name = if field.name == "Pointer" { format!("__{}_handle", field_name) } else { field_name.clone() }; - let mut write_conditions = vec![attr(&write_command, "WriteCondition")]; - if !attr(&write_command, "DontWriteIfValueIs").is_empty() { + let mut write_conditions = vec![attr(write_command, "WriteCondition")]; + if !attr(write_command, "DontWriteIfValueIs").is_empty() { write_conditions.push(format!( "ent.{} != {}", normalized_field_name, - attr(&write_command, "DontWriteIfValueIs") + attr(write_command, "DontWriteIfValueIs") )); } - for line in write_lines_for_field(&field, write_conditions) { + for line in write_lines_for_field(field, write_conditions) { commands.push(line); } } "WriteSpecificValue" => { let mut predicates = vec![]; - if !min_version(&write_command).is_empty() { + if !min_version(write_command).is_empty() { predicates.push(format!( "version >= AcadVersion::{}", - min_version(&write_command) + min_version(write_command) )); } - if !max_version(&write_command).is_empty() { + if !max_version(write_command).is_empty() { predicates.push(format!( "version <= AcadVersion::{}", - max_version(&write_command) + max_version(write_command) )); } - if !attr(&write_command, "DontWriteIfValueIs").is_empty() { + if !attr(write_command, "DontWriteIfValueIs").is_empty() { predicates.push(format!( "{} != {}", - attr(&write_command, "Value"), - attr(&write_command, "DontWriteIfValueIs") + attr(write_command, "Value"), + attr(write_command, "DontWriteIfValueIs") )); } - if !attr(&write_command, "WriteCondition").is_empty() { - predicates.push(attr(&write_command, "WriteCondition")); + if !attr(write_command, "WriteCondition").is_empty() { + predicates.push(attr(write_command, "WriteCondition")); } - let code = code(&write_command); - let expected_type = ExpectedType::expected_type(code).unwrap(); + let code = code(write_command); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(format!("if {} {{", predicates.join(" && "))); } - let indent = if predicates.len() > 0 { " " } else { "" }; + let indent = if !predicates.is_empty() { " " } else { "" }; commands.push(format!( "{indent}pairs.push(CodePair::new_{typ}({code}, {val}));", indent = indent, typ = typ, code = code, - val = attr(&write_command, "Value") + val = attr(write_command, "Value") )); - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(String::from("}")); } } "Foreach" => { - commands.push(format!("for item in &{} {{", attr(&write_command, "Field"))); + commands.push(format!("for item in &{} {{", attr(write_command, "Field"))); for write_command in &write_command.children { - for line in generate_write_code_pairs_for_write_order(&entity, &write_command) { + for line in generate_write_code_pairs_for_write_order(entity, write_command) { commands.push(format!(" {}", line)); } } @@ -722,44 +723,51 @@ fn generate_write_code_pairs_for_write_order( fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec { let mut commands = vec![]; let mut predicates = vec![]; - if !min_version(&field).is_empty() { - predicates.push(format!("version >= AcadVersion::{}", min_version(&field))); - } - if !max_version(&field).is_empty() { - predicates.push(format!("version <= AcadVersion::{}", max_version(&field))); - } - if disable_writing_default(&field) { - predicates.push(format!( - "ent.{field} != {default}", - field = name(&field), - default = default_value(&field) - )); + if !min_version(field).is_empty() { + predicates.push(format!("version >= AcadVersion::{}", min_version(field))); + } + if !max_version(field).is_empty() { + predicates.push(format!("version <= AcadVersion::{}", max_version(field))); + } + if disable_writing_default(field) { + predicates.push(match default_value(field).as_str() { + "true" => format!("!ent.{field}", field = name(field)), + "false" => format!("ent.{field}", field = name(field)), + default => format!( + "ent.{} != {}", + name(field), + match typ(field).as_str() { + "String" => default.replace("String::from(", "").replace(')', ""), + _ => default.into(), + } + ), + }); } for wc in write_conditions { if !wc.is_empty() { predicates.push(wc); } } - let indent = if predicates.len() == 0 { "" } else { " " }; - if predicates.len() > 0 { + let indent = if predicates.is_empty() { "" } else { " " }; + if !predicates.is_empty() { commands.push(format!("if {} {{", predicates.join(" && "))); } - if allow_multiples(&field) { - let expected_type = ExpectedType::expected_type(codes(&field)[0]).unwrap(); + if allow_multiples(field) { + let expected_type = ExpectedType::new(codes(field)[0]).unwrap(); let val = if field.name == "Pointer" { "&v.as_string()" } else { match expected_type { - ExpectedType::Str => "&v", + ExpectedType::Str => "v", ExpectedType::Binary => "v.clone()", _ => "*v", } }; let normalized_field_name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; let typ = code_pair_type(&expected_type); commands.push(format!( @@ -771,12 +779,12 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< "{indent} pairs.push(CodePair::new_{typ}({code}, {val}));", indent = indent, typ = typ, - code = codes(&field)[0], + code = codes(field)[0], val = val )); commands.push(format!("{indent}}}", indent = indent)); } else { - for command in code_pairs_for_field(&field) { + for command in code_pairs_for_field(field) { commands.push(format!( "{indent}pairs.push({command});", indent = indent, @@ -785,7 +793,7 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< } } - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(String::from("}")); } @@ -793,9 +801,9 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< } fn code_pairs_for_field(field: &Element) -> Vec { - let codes = codes(&field); + let codes = codes(field); match codes.len() { - 1 => vec![code_pair_for_field_and_code(codes[0], &field, None)], + 1 => vec![code_pair_for_field_and_code(codes[0], field, None)], _ => { let mut pairs = vec![]; for (i, &cd) in codes.iter().enumerate() { @@ -805,7 +813,7 @@ fn code_pairs_for_field(field: &Element) -> Vec { 2 => "z", _ => panic!("unexpected multiple codes"), }; - pairs.push(code_pair_for_field_and_code(cd, &field, Some(suffix))); + pairs.push(code_pair_for_field_and_code(cd, field, Some(suffix))); } pairs } @@ -813,9 +821,9 @@ fn code_pairs_for_field(field: &Element) -> Vec { } fn code_pair_for_field_and_code(code: i32, field: &Element, suffix: Option<&str>) -> String { - let expected_type = ExpectedType::expected_type(code).unwrap(); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); - let mut write_converter = attr(&field, "WriteConverter"); + let mut write_converter = attr(field, "WriteConverter"); if field.name == "Pointer" { write_converter = String::from("&{}.as_string()"); } @@ -827,16 +835,16 @@ fn code_pair_for_field_and_code(code: i32, field: &Element, suffix: Option<&str> } } let normalized_field_name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; let mut field_access = format!("ent.{field}", field = normalized_field_name); if let Some(suffix) = suffix { field_access = format!("{}.{}", field_access, suffix); } let writer = write_converter.replace("{}", &field_access); - if name(&field) == "handle" && code == 5 { + if name(field) == "handle" && code == 5 { String::from("CodePair::new_string(5, &self.handle.as_string())") } else { format!( @@ -855,13 +863,13 @@ fn load_xml() -> Element { } fn generate_reader_function(element: &Element) -> bool { - attr(&element, "GenerateReaderFunction") != "false" + attr(element, "GenerateReaderFunction") != "false" } fn generate_writer_function(element: &Element) -> bool { - attr(&element, "GenerateWriterFunction") != "false" + attr(element, "GenerateWriterFunction") != "false" } fn base_class(element: &Element) -> String { - attr(&element, "BaseClass") + attr(element, "BaseClass") } diff --git a/build/header_generator.rs b/build/header_generator.rs index 6580f10..43c46a7 100644 --- a/build/header_generator.rs +++ b/build/header_generator.rs @@ -66,24 +66,24 @@ fn generate_struct(fun: &mut String, element: &Element) { let field_name = field(v); if !seen_fields.contains(&field_name) { seen_fields.insert(field_name.clone()); - let mut comment = format!("The ${} header variable. {}", name(&v), comment(&v)); - if !min_version(&v).is_empty() { - comment.push_str(&format!(" Minimum AutoCAD version: {}.", min_version(&v))); + let mut comment = format!("The ${} header variable. {}", name(v), comment(v)); + if !min_version(v).is_empty() { + comment.push_str(&format!(" Minimum AutoCAD version: {}.", min_version(v))); } - if !max_version(&v).is_empty() { - comment.push_str(&format!(" Maximum AutoCAD version: {}.", max_version(&v))); + if !max_version(v).is_empty() { + comment.push_str(&format!(" Maximum AutoCAD version: {}.", max_version(v))); } fun.push_str(&format!(" /// {}\n", comment)); fun.push_str(&format!( " pub {field}: {typ},\n", - field = field(&v), - typ = typ(&v) + field = field(v), + typ = typ(v) )); } } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } fn generate_default(fun: &mut String, element: &Element) { @@ -92,13 +92,13 @@ fn generate_default(fun: &mut String, element: &Element) { fun.push_str(" fn default() -> Self {\n"); fun.push_str(" Header {\n"); for v in &element.children { - if !seen_fields.contains(&field(&v)) { - seen_fields.insert(field(&v)); + if !seen_fields.contains(&field(v)) { + seen_fields.insert(field(v)); fun.push_str(&format!( " {field}: {default_value}, // ${name}\n", - field = field(&v), - default_value = default_value(&v), - name = name(&v) + field = field(v), + default_value = default_value(v), + name = name(v) )); } } @@ -106,53 +106,53 @@ fn generate_default(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } fn generate_flags(fun: &mut String, element: &Element) { let mut seen_fields = HashSet::new(); for v in &element.children { - if !seen_fields.contains(&field(&v)) { - seen_fields.insert(field(&v)); - if v.children.len() > 0 { - fun.push_str(&format!(" // {} flags\n", field(&v))); + if !seen_fields.contains(&field(v)) { + seen_fields.insert(field(v)); + if !v.children.is_empty() { + fun.push_str(&format!(" // {} flags\n", field(v))); } for f in &v.children { - let mut comment = format!("{}", comment(&f)); - if !min_version(&v).is_empty() { - comment.push_str(&format!(" Minimum AutoCAD version: {}.", min_version(&v))); + let mut comment = comment(f).to_string(); + if !min_version(v).is_empty() { + comment.push_str(&format!(" Minimum AutoCAD version: {}.", min_version(v))); } - if !max_version(&v).is_empty() { - comment.push_str(&format!(" Maximum AutoCAD version: {}.", max_version(&v))); + if !max_version(v).is_empty() { + comment.push_str(&format!(" Maximum AutoCAD version: {}.", max_version(v))); } fun.push_str(&format!(" /// {}\n", comment)); fun.push_str(&format!( " pub fn {flag}(&self) -> bool {{\n", - flag = name(&f) + flag = name(f) )); fun.push_str(&format!( " self.{field} & {mask} != 0\n", - field = field(&v), - mask = mask(&f) + field = field(v), + mask = mask(f) )); fun.push_str(" }\n"); fun.push_str(&format!(" /// {}\n", comment)); fun.push_str(&format!( " pub fn set_{flag}(&mut self, val: bool) {{\n", - flag = name(&f) + flag = name(f) )); - fun.push_str(&format!(" if val {{\n")); + fun.push_str(" if val {\n"); fun.push_str(&format!( " self.{field} |= {mask};\n", - field = field(&v), - mask = mask(&f) + field = field(v), + mask = mask(f) )); fun.push_str(" }\n"); fun.push_str(" else {\n"); fun.push_str(&format!( " self.{field} &= !{mask};\n", - field = field(&v), - mask = mask(&f) + field = field(v), + mask = mask(f) )); fun.push_str(" }\n"); fun.push_str(" }\n"); @@ -166,13 +166,13 @@ fn generate_set_defaults(fun: &mut String, element: &Element) { fun.push_str(" /// Sets the default values on the header.\n"); fun.push_str(" pub fn set_defaults(&mut self) {\n"); for v in &element.children { - if !seen_fields.contains(&field(&v)) { - seen_fields.insert(field(&v)); + if !seen_fields.contains(&field(v)) { + seen_fields.insert(field(v)); fun.push_str(&format!( " self.{field} = {default_value}; // ${name}\n", - field = field(&v), - default_value = default_value(&v), - name = name(&v) + field = field(v), + default_value = default_value(v), + name = name(v) )); } } @@ -186,42 +186,42 @@ fn generate_set_header_value(fun: &mut String, element: &Element) { fun.push_str(" pub(crate) fn set_header_value(&mut self, variable: &str, pair: &CodePair) -> DxfResult<()> {\n"); fun.push_str(" match variable {\n"); for v in &element.children { - if !seen_fields.contains(&field(&v)) { - seen_fields.insert(field(&v)); - fun.push_str(&format!(" \"${name}\" => {{", name = name(&v))); + if !seen_fields.contains(&field(v)) { + seen_fields.insert(field(v)); + fun.push_str(&format!(" \"${name}\" => {{", name = name(v))); let variables_with_name: Vec<&Element> = element .children .iter() - .filter(|&vv| name(&vv) == name(&v)) + .filter(|&vv| name(vv) == name(v)) .collect(); if variables_with_name.len() == 1 { // only one variable with that name - fun.push_str(" "); - if code(&v) < 0 { - fun.push_str(&format!("self.{field}.set(&pair)?;", field = field(&v))); + fun.push(' '); + if code(v) < 0 { + fun.push_str(&format!("self.{field}.set(pair)?;", field = field(v))); } else { - let read_cmd = read_command(&v); + let read_cmd = read_command(v); fun.push_str(&format!( - "verify_code(&pair, {code})?; self.{field} = {cmd};", - code = code(&v), - field = field(&v), + "verify_code(pair, {code})?; self.{field} = {cmd};", + code = code(v), + field = field(v), cmd = read_cmd )); } - fun.push_str(" "); + fun.push(' '); } else { // multiple variables with that name - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" match pair.code {\n"); let expected_codes: Vec = - variables_with_name.iter().map(|&vv| code(&vv)).collect(); + variables_with_name.iter().map(|&vv| code(vv)).collect(); for v in &variables_with_name { - let read_cmd = read_command(&v); + let read_cmd = read_command(v); fun.push_str(&format!( " {code} => self.{field} = {cmd},\n", - code = code(&v), - field = field(&v), + code = code(v), + field = field(v), cmd = read_cmd )); } @@ -235,22 +235,22 @@ fn generate_set_header_value(fun: &mut String, element: &Element) { } fun.push_str(" _ => (),\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" Ok(())\n"); fun.push_str(" }\n"); } fn read_command(element: &Element) -> String { - let reader_override = reader_override(&element); + let reader_override = reader_override(element); if !reader_override.is_empty() { reader_override } else { - let expected_type = ExpectedType::expected_type(code(element)).unwrap(); + let expected_type = ExpectedType::new(code(element)).unwrap(); let reader_fun = reader_function(&expected_type); - let converter = if read_converter(&element).is_empty() { + let converter = if read_converter(element).is_empty() { String::from("{}") } else { - read_converter(&element).clone() + read_converter(element) }; converter.replace("{}", &format!("pair.{}()?", reader_fun)) } @@ -260,20 +260,24 @@ fn generate_get_code_pairs_internal(fun: &mut String, element: &Element) { fun.push_str(" #[allow(clippy::cognitive_complexity)] // long function, no good way to simplify this\n"); fun.push_str(" pub(crate) fn add_code_pairs_internal(&self, pairs: &mut Vec) {\n"); for v in &element.children { - if suppress_writing(&v) { + if suppress_writing(v) { continue; } // prepare writing predicate let mut parts = vec![]; - if !min_version(&v).is_empty() { - parts.push(format!("self.version >= AcadVersion::{}", min_version(&v))); - } - if !max_version(&v).is_empty() { - parts.push(format!("self.version <= AcadVersion::{}", max_version(&v))); + match (min_version(v).as_str(), max_version(v).as_str()) { + ("", "") => (), + (min, "") => parts.push(format!("self.version >= AcadVersion::{min}")), + ("", max) => parts.push(format!("self.version <= AcadVersion::{max}")), + (min, max) if min == max => parts.push(format!("self.version == AcadVersion::{min}")), + (min, max) => { + parts.push(format!("self.version >= AcadVersion::{min}")); + parts.push(format!("self.version <= AcadVersion::{max}")); + } } - if dont_write_default(&v) { - parts.push(format!("self.{} != {}", field(&v), default_value(&v))); + if do_not_write_default(v) { + parts.push(format!("self.{} != {}", field(v), default_value(v))); } let indent = match parts.len() { 0 => "", @@ -281,42 +285,42 @@ fn generate_get_code_pairs_internal(fun: &mut String, element: &Element) { }; // write the value - fun.push_str(&format!(" // ${}\n", name(&v))); - if parts.len() > 0 { + fun.push_str(&format!(" // ${}\n", name(v))); + if !parts.is_empty() { fun.push_str(&format!(" if {} {{\n", parts.join(" && "))); } fun.push_str(&format!( " {indent}pairs.push(CodePair::new_str(9, \"${name}\"));\n", - name = name(&v), + name = name(v), indent = indent )); - let write_converter = if write_converter(&v).is_empty() { + let write_converter = if write_converter(v).is_empty() { String::from("{}") } else { - write_converter(&v).clone() + write_converter(v).clone() }; - if code(&v) > 0 { - let expected_type = code_pair_type(&ExpectedType::expected_type(code(&v)).unwrap()); - let field_name = field(&v); + if code(v) > 0 { + let expected_type = code_pair_type(&ExpectedType::new(code(v)).unwrap()); + let field_name = field(v); let value = format!("self.{}", field_name); - let value = write_converter.replace("{}", &*value); + let value = write_converter.replace("{}", &value); fun.push_str(&format!( " {indent}pairs.push(CodePair::new_{typ}({code}, {value}));\n", - code = code(&v), + code = code(v), value = value, typ = expected_type, indent = indent )); } else { // write a point or vector as it's components - for i in 0..code(&v).abs() { + for i in 0..code(v).abs() { let (code, fld) = match i { 0 => (10, "x"), 1 => (20, "y"), 2 => (30, "z"), _ => panic!("unexpected number of values"), }; - let value = write_converter.replace("{}", &format!("self.{}.{}", field(&v), fld)); + let value = write_converter.replace("{}", &format!("self.{}.{}", field(v), fld)); fun.push_str(&format!( " {indent}pairs.push(CodePair::new_f64({code}, {value}));\n", code = code, @@ -325,12 +329,12 @@ fn generate_get_code_pairs_internal(fun: &mut String, element: &Element) { )); } } - if parts.len() > 0 { + if !parts.is_empty() { fun.push_str(" }\n"); } // newline between values - fun.push_str("\n"); + fun.push('\n'); } fun.push_str(" }\n"); @@ -342,7 +346,7 @@ fn load_xml() -> Element { Element::parse(file).unwrap() } -fn dont_write_default(element: &Element) -> bool { +fn do_not_write_default(element: &Element) -> bool { attr(element, "DontWriteDefault") == "true" } diff --git a/build/object_generator.rs b/build/object_generator.rs index e6dddc5..7e6f645 100644 --- a/build/object_generator.rs +++ b/build/object_generator.rs @@ -52,7 +52,7 @@ use std::collections::HashMap; extern crate chrono; use self::chrono::{DateTime, Local}; ".trim_start()); - fun.push_str("\n"); + fun.push('\n'); generate_base_object(&mut fun, &element); generate_object_types(&mut fun, &element); @@ -69,20 +69,20 @@ use self::chrono::{DateTime, Local}; fn generate_base_object(fun: &mut String, element: &Element) { let object = &element.children[0]; - if name(&object) != "Object" { + if name(object) != "Object" { panic!("Expected first object to be 'Object'."); } fun.push_str("#[derive(Clone, Debug)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); fun.push_str("pub struct ObjectCommon {\n"); for c in &object.children { - let t = if allow_multiples(&c) { + let t = if allow_multiples(c) { format!("Vec<{}>", typ(c)) } else { typ(c) }; - if !comment(&c).is_empty() { - fun.push_str(&format!(" /// {}\n", comment(&c))); + if !comment(c).is_empty() { + fun.push_str(&format!(" /// {}\n", comment(c))); } match &*c.name { "Field" => { @@ -93,7 +93,7 @@ fn generate_base_object(fun: &mut String, element: &Element) { )); } "Pointer" => { - let typ = if allow_multiples(&c) { + let typ = if allow_multiples(c) { "Vec" } else { "Handle" @@ -111,7 +111,7 @@ fn generate_base_object(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("#[derive(Clone, Debug)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); @@ -119,7 +119,7 @@ fn generate_base_object(fun: &mut String, element: &Element) { fun.push_str(" pub common: ObjectCommon,\n"); fun.push_str(" pub specific: ObjectType,\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("impl Default for ObjectCommon {\n"); fun.push_str(" fn default() -> ObjectCommon {\n"); @@ -130,7 +130,7 @@ fn generate_base_object(fun: &mut String, element: &Element) { fun.push_str(&format!( " {name}: {val},\n", name = name(c), - val = default_value(&c) + val = default_value(c) )); } "Pointer" => { @@ -147,14 +147,14 @@ fn generate_base_object(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str("impl ObjectCommon {\n"); /////////////////////////////////////////////////////////////////// pointers for p in &object.children { if p.name == "Pointer" { - fun.push_str(&*methods_for_pointer_access(p)); + fun.push_str(&methods_for_pointer_access(p)); } } @@ -171,10 +171,10 @@ fn generate_base_object(fun: &mut String, element: &Element) { } else if name(c) == "x_data" && code(c) == 1001 { // handled below: x_data::XDATA_APPLICATIONNAME } else { - let read_fun = if allow_multiples(&c) { - format!(".push({})", field_reader(&c)) + let read_fun = if allow_multiples(c) { + format!(".push({})", field_reader(c)) } else { - format!(" = {}", field_reader(&c)) + format!(" = {}", field_reader(c)) }; fun.push_str(&format!( " {code} => {{ self.{field}{read_fun} }},\n", @@ -186,7 +186,7 @@ fn generate_base_object(fun: &mut String, element: &Element) { } else if c.name == "Pointer" { fun.push_str(&format!( " {code} => {{ self.__{field}_handle = pair.as_handle()? }},\n", - code = code(&c), + code = code(c), field = name(c) )); } @@ -206,17 +206,18 @@ fn generate_base_object(fun: &mut String, element: &Element) { " pub(crate) fn add_code_pairs(&self, pairs: &mut Vec, version: AcadVersion) {\n", ); fun.push_str(" let obj = self;\n"); - for line in generate_write_code_pairs(&object) { + for line in generate_write_code_pairs(object) { fun.push_str(&format!(" {}\n", line)); } fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } fn generate_object_types(fun: &mut String, element: &Element) { + fun.push_str("#[allow(clippy::large_enum_variant)]\n"); fun.push_str("#[derive(Clone, Debug, PartialEq)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); fun.push_str("pub enum ObjectType {\n"); @@ -230,7 +231,7 @@ fn generate_object_types(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); // individual structs for c in &element.children { @@ -243,14 +244,14 @@ fn generate_object_types(fun: &mut String, element: &Element) { fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); fun.push_str(&format!("pub struct {typ} {{\n", typ = name(c))); for f in &c.children { - let t = if allow_multiples(&f) { + let t = if allow_multiples(f) { format!("Vec<{}>", typ(f)) } else { typ(f) }; - let is_private = name(f).starts_with("_"); - if !comment(&f).is_empty() { - fun.push_str(&format!(" /// {}\n", comment(&f))); + let is_private = name(f).starts_with('_'); + if !comment(f).is_empty() { + fun.push_str(&format!(" /// {}\n", comment(f))); } if is_private { fun.push_str(" #[doc(hidden)]\n"); @@ -264,7 +265,7 @@ fn generate_object_types(fun: &mut String, element: &Element) { )); } "Pointer" => { - let typ = if allow_multiples(&f) { + let typ = if allow_multiples(f) { "Vec" } else { "Handle" @@ -282,9 +283,10 @@ fn generate_object_types(fun: &mut String, element: &Element) { } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); // implementation + fun.push_str("#[allow(clippy::derivable_impls)]\n"); fun.push_str(&format!("impl Default for {typ} {{\n", typ = name(c))); fun.push_str(&format!(" fn default() -> {typ} {{\n", typ = name(c))); fun.push_str(&format!(" {typ} {{\n", typ = name(c))); @@ -294,11 +296,11 @@ fn generate_object_types(fun: &mut String, element: &Element) { fun.push_str(&format!( " {name}: {val},\n", name = name(f), - val = default_value(&f) + val = default_value(f) )); } "Pointer" => { - let val = if allow_multiples(&f) { + let val = if allow_multiples(f) { "vec![]" } else { "Handle::empty()" @@ -317,9 +319,9 @@ fn generate_object_types(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); - generate_implementation(fun, &c); + generate_implementation(fun, c); } } } @@ -332,15 +334,15 @@ fn generate_implementation(fun: &mut String, element: &Element) { if field.name == "Field" { for flag in &field.children { if flag.name == "Flag" { - let flag_name = name(&flag); - let mask = attr(&flag, "Mask"); + let flag_name = name(flag); + let mask = attr(flag, "Mask"); implementation.push_str(&format!( " pub fn {name}(&self) -> bool {{\n", name = flag_name )); implementation.push_str(&format!( " self.{name} & {mask} != 0\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); @@ -351,14 +353,14 @@ fn generate_implementation(fun: &mut String, element: &Element) { implementation.push_str(" if val {\n"); implementation.push_str(&format!( " self.{name} |= {mask};\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); implementation.push_str(" else {\n"); implementation.push_str(&format!( " self.{name} &= !{mask};\n", - name = name(&field), + name = name(field), mask = mask )); implementation.push_str(" }\n"); @@ -371,15 +373,15 @@ fn generate_implementation(fun: &mut String, element: &Element) { // generate pointer methods for field in &element.children { if field.name == "Pointer" { - implementation.push_str(&*methods_for_pointer_access(field)); + implementation.push_str(&methods_for_pointer_access(field)); } } if !implementation.is_empty() { - fun.push_str(&format!("impl {typ} {{\n", typ = name(&element))); + fun.push_str(&format!("impl {typ} {{\n", typ = name(element))); fun.push_str(&implementation); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } @@ -389,22 +391,22 @@ fn generate_is_supported_on_version(fun: &mut String, element: &Element) { ); fun.push_str(" match self {\n"); for object in &element.children { - if name(&object) != "Object" { + if name(object) != "Object" { let mut predicates = vec![]; - if !min_version(&object).is_empty() { - predicates.push(format!("version >= AcadVersion::{}", min_version(&object))); + if !min_version(object).is_empty() { + predicates.push(format!("version >= AcadVersion::{}", min_version(object))); } - if !max_version(&object).is_empty() { - predicates.push(format!("version <= AcadVersion::{}", max_version(&object))); + if !max_version(object).is_empty() { + predicates.push(format!("version <= AcadVersion::{}", max_version(object))); } - let predicate = if predicates.len() == 0 { + let predicate = if predicates.is_empty() { String::from("true") } else { predicates.join(" && ") }; fun.push_str(&format!( " ObjectType::{typ}(_) => {{ {predicate} }},\n", - typ = name(&object), + typ = name(object), predicate = predicate )); } @@ -417,8 +419,8 @@ fn generate_type_string(fun: &mut String, element: &Element) { fun.push_str(" pub(crate) fn from_type_string(type_string: &str) -> Option {\n"); fun.push_str(" match type_string {\n"); for c in &element.children { - if name(c) != "Object" && !attr(&c, "TypeString").is_empty() { - let type_string = attr(&c, "TypeString"); + if name(c) != "Object" && !attr(c, "TypeString").is_empty() { + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); for t in type_strings { fun.push_str(&format!(" \"{type_string}\" => Some(ObjectType::{typ}(Default::default())),\n", type_string=t, typ=name(c))); @@ -434,7 +436,7 @@ fn generate_type_string(fun: &mut String, element: &Element) { fun.push_str(" match *self {\n"); for c in &element.children { // only write the first type string given - let type_string = attr(&c, "TypeString"); + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); if name(c) != "Object" && !type_string.is_empty() { fun.push_str(&format!( @@ -460,8 +462,8 @@ fn generate_try_apply_code_pair(fun: &mut String, element: &Element) { panic!("expected top level object"); } if name(c) != "Object" { - if generate_reader_function(&c) { - let obj = if name(&c) == "PlaceHolder" || name(&c) == "ObjectPointer" { + if generate_reader_function(c) { + let obj = if name(c) == "PlaceHolder" || name(c) == "ObjectPointer" { "_obj" } else { "obj" @@ -471,70 +473,74 @@ fn generate_try_apply_code_pair(fun: &mut String, element: &Element) { typ = name(c), obj = obj )); - fun.push_str(" match pair.code {\n"); - let mut seen_codes = HashSet::new(); - for f in &c.children { - if f.name == "Field" && generate_reader(&f) { - for (i, &cd) in codes(&f).iter().enumerate() { - if !seen_codes.contains(&cd) { - seen_codes.insert(cd); // TODO: allow for duplicates - let reader = field_reader(&f); - let codes = codes(&f); - let write_cmd = match codes.len() { - 1 => { - let read_fun = if allow_multiples(&f) { - format!(".push({})", reader) - } else { - format!(" = {}", reader) - }; - format!( - "obj.{field}{read_fun}", - field = name(&f), - read_fun = read_fun - ) - } - _ => { - let suffix = match i { - 0 => "x", - 1 => "y", - 2 => "z", - _ => panic!("impossible"), - }; - format!( - "obj.{field}.{suffix} = {reader}", - field = name(&f), - suffix = suffix, - reader = reader - ) - } - }; - fun.push_str(&format!( - " {code} => {{ {cmd}; }},\n", - code = cd, - cmd = write_cmd - )); + if obj == "obj" { + fun.push_str(" match pair.code {\n"); + let mut seen_codes = HashSet::new(); + for f in &c.children { + if f.name == "Field" && generate_reader(f) { + for (i, &cd) in codes(f).iter().enumerate() { + if !seen_codes.contains(&cd) { + seen_codes.insert(cd); // TODO: allow for duplicates + let reader = field_reader(f); + let codes = codes(f); + let write_cmd = match codes.len() { + 1 => { + let read_fun = if allow_multiples(f) { + format!(".push({})", reader) + } else { + format!(" = {}", reader) + }; + format!( + "obj.{field}{read_fun}", + field = name(f), + read_fun = read_fun + ) + } + _ => { + let suffix = match i { + 0 => "x", + 1 => "y", + 2 => "z", + _ => panic!("impossible"), + }; + format!( + "obj.{field}.{suffix} = {reader}", + field = name(f), + suffix = suffix, + reader = reader + ) + } + }; + fun.push_str(&format!( + " {code} => {{ {cmd}; }},\n", + code = cd, + cmd = write_cmd + )); + } + } + } else if f.name == "Pointer" { + if allow_multiples(f) { + fun.push_str(&format!(" {code} => {{ obj.__{field}_handle.push(pair.as_handle()?); }},\n", code=code(f), field=name(f))); + } else { + fun.push_str(&format!(" {code} => {{ obj.__{field}_handle = pair.as_handle()?; }},\n", code=code(f), field=name(f))); } - } - } else if f.name == "Pointer" { - if allow_multiples(&f) { - fun.push_str(&format!(" {code} => {{ obj.__{field}_handle.push(pair.as_handle()?); }},\n", code=code(&f), field=name(&f))); - } else { - fun.push_str(&format!(" {code} => {{ obj.__{field}_handle = pair.as_handle()?; }},\n", code=code(&f), field=name(&f))); } } - } - fun.push_str(" _ => return Ok(false),\n"); - fun.push_str(" }\n"); + fun.push_str(" _ => return Ok(false),\n"); + fun.push_str(" }\n"); + } else { + fun.push_str(" return Ok(false);\n"); + } fun.push_str(" },\n"); } else { // ensure no read converters were specified (because they won't be used) for f in &c.children { - if f.name == "Field" && !attr(&f, "ReadConverter").is_empty() { + if f.name == "Field" && !attr(f, "ReadConverter").is_empty() { unused_readers.push(format!("{}.{}", name(c), name(f))); } } - fun.push_str(&format!(" ObjectType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom reader\"); }},\n", typ=name(&c))); + fun.push_str(&format!(" ObjectType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom reader\"); }},\n", typ=name(c))); } } } @@ -543,32 +549,32 @@ fn generate_try_apply_code_pair(fun: &mut String, element: &Element) { fun.push_str(" Ok(true)\n"); fun.push_str(" }\n"); - if unused_readers.len() > 0 { + if !unused_readers.is_empty() { panic!("There were unused reader functions: {:?}", unused_readers); } } fn generate_write(fun: &mut String, element: &Element) { let mut unused_writers = vec![]; - fun.push_str(" #[allow(clippy::cognitive_complexity)] // long function, no good way to simplify this\n"); + fun.push_str("\n #[allow(clippy::cognitive_complexity)] // long function, no good way to simplify this\n"); fun.push_str( " pub(crate) fn add_code_pairs(&self, pairs: &mut Vec, version: AcadVersion) {\n", ); fun.push_str(" match *self {\n"); for object in &element.children { - if name(&object) != "Object" { - if generate_writer_function(&object) { - let obj = if name(&object) == "PlaceHolder" || name(&object) == "ObjectPointer" { + if name(object) != "Object" { + if generate_writer_function(object) { + let obj = if name(object) == "PlaceHolder" || name(object) == "ObjectPointer" { "_obj" } else { "obj" }; // ACDBPLACEHOLDER and OBJECT_PTR don't use this variable fun.push_str(&format!( " ObjectType::{typ}(ref {obj}) => {{\n", - typ = name(&object), + typ = name(object), obj = obj )); - for line in generate_write_code_pairs(&object) { + for line in generate_write_code_pairs(object) { fun.push_str(&format!(" {}\n", line)); } @@ -576,25 +582,25 @@ fn generate_write(fun: &mut String, element: &Element) { } else { // ensure no write converters were specified (because they won't be used) for f in &element.children { - if f.name == "Field" && !attr(&f, "WriteConverter").is_empty() { + if f.name == "Field" && !attr(f, "WriteConverter").is_empty() { unused_writers.push(format!("{}.{}", name(element), name(f))); } } - fun.push_str(&format!(" ObjectType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom writer\"); }},\n", typ=name(&object))); + fun.push_str(&format!(" ObjectType::{typ}(_) => {{ panic!(\"this case should have been covered in a custom writer\"); }},\n", typ=name(object))); } } } fun.push_str(" }\n"); fun.push_str(" }\n"); - if unused_writers.len() > 0 { + if !unused_writers.is_empty() { panic!("There were unused writer functions: {:?}", unused_writers); } } fn field_with_name<'a>(object: &'a Element, field_name: &String) -> &'a Element { for field in &object.children { - if name(&field) == *field_name { + if name(field) == *field_name { return field; } } @@ -608,7 +614,7 @@ fn generate_write_code_pairs(object: &Element) -> Vec { if f.name == "WriteOrder" { // order was specifically given to us for write_command in &f.children { - for line in generate_write_code_pairs_for_write_order(&object, &write_command) { + for line in generate_write_code_pairs_for_write_order(object, write_command) { commands.push(line); } } @@ -617,7 +623,7 @@ fn generate_write_code_pairs(object: &Element) -> Vec { } // no order given, use declaration order - let subclass = attr(&object, "SubclassMarker"); + let subclass = attr(object, "SubclassMarker"); if !subclass.is_empty() { commands.push(format!( "pairs.push(CodePair::new_str(100, \"{subclass}\"));", @@ -625,10 +631,10 @@ fn generate_write_code_pairs(object: &Element) -> Vec { )); } for field in &object.children { - if generate_writer(&field) { + if generate_writer(field) { match &*field.name { "Field" | "Pointer" => { - for line in write_lines_for_field(&field, vec![]) { + for line in write_lines_for_field(field, vec![]) { commands.push(line); } } @@ -636,7 +642,7 @@ fn generate_write_code_pairs(object: &Element) -> Vec { } } } - return commands; + commands } fn generate_write_code_pairs_for_write_order( @@ -647,67 +653,67 @@ fn generate_write_code_pairs_for_write_order( match &*write_command.name { "WriteField" => { let field_name = write_command.attributes.get("Field").unwrap(); - let field = field_with_name(&object, &field_name); + let field = field_with_name(object, field_name); let normalized_field_name = if field.name == "Pointer" { format!("__{}_handle", field_name) } else { field_name.clone() }; - let mut write_conditions = vec![attr(&write_command, "WriteCondition")]; - if !attr(&write_command, "DontWriteIfValueIs").is_empty() { + let mut write_conditions = vec![attr(write_command, "WriteCondition")]; + if !attr(write_command, "DontWriteIfValueIs").is_empty() { write_conditions.push(format!( "obj.{} != {}", normalized_field_name, - attr(&write_command, "DontWriteIfValueIs") + attr(write_command, "DontWriteIfValueIs") )); } - for line in write_lines_for_field(&field, write_conditions) { + for line in write_lines_for_field(field, write_conditions) { commands.push(line); } } "WriteSpecificValue" => { let mut predicates = vec![]; - if !min_version(&write_command).is_empty() { + if !min_version(write_command).is_empty() { predicates.push(format!( "version >= AcadVersion::{}", - min_version(&write_command) + min_version(write_command) )); } - if !max_version(&write_command).is_empty() { + if !max_version(write_command).is_empty() { predicates.push(format!( "version <= AcadVersion::{}", - max_version(&write_command) + max_version(write_command) )); } - if !attr(&write_command, "DontWriteIfValueIs").is_empty() { + if !attr(write_command, "DontWriteIfValueIs").is_empty() { predicates.push(format!( "{} != {}", - attr(&write_command, "Value"), - attr(&write_command, "DontWriteIfValueIs") + attr(write_command, "Value"), + attr(write_command, "DontWriteIfValueIs") )); } - let code = code(&write_command); - let expected_type = ExpectedType::expected_type(code).unwrap(); + let code = code(write_command); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(format!("if {} {{", predicates.join(" && "))); } - let indent = if predicates.len() > 0 { " " } else { "" }; + let indent = if !predicates.is_empty() { " " } else { "" }; commands.push(format!( "{indent}pairs.push(CodePair::new_{typ}({code}, {val}));", indent = indent, typ = typ, code = code, - val = attr(&write_command, "Value") + val = attr(write_command, "Value") )); - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(String::from("}")); } } "Foreach" => { - commands.push(format!("for item in &{} {{", attr(&write_command, "Field"))); + commands.push(format!("for item in &{} {{", attr(write_command, "Field"))); for write_command in &write_command.children { - for line in generate_write_code_pairs_for_write_order(&object, &write_command) { + for line in generate_write_code_pairs_for_write_order(object, write_command) { commands.push(format!(" {}", line)); } } @@ -731,17 +737,17 @@ fn generate_write_code_pairs_for_write_order( fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec { let mut commands = vec![]; let mut predicates = vec![]; - if !min_version(&field).is_empty() { - predicates.push(format!("version >= AcadVersion::{}", min_version(&field))); + if !min_version(field).is_empty() { + predicates.push(format!("version >= AcadVersion::{}", min_version(field))); } - if !max_version(&field).is_empty() { - predicates.push(format!("version <= AcadVersion::{}", max_version(&field))); + if !max_version(field).is_empty() { + predicates.push(format!("version <= AcadVersion::{}", max_version(field))); } - if disable_writing_default(&field) { + if disable_writing_default(field) { predicates.push(format!( "obj.{field} != {default}", - field = name(&field), - default = default_value(&field) + field = name(field), + default = default_value(field) )); } for wc in write_conditions { @@ -749,26 +755,26 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< predicates.push(wc); } } - let indent = if predicates.len() == 0 { "" } else { " " }; - if predicates.len() > 0 { + let indent = if predicates.is_empty() { "" } else { " " }; + if !predicates.is_empty() { commands.push(format!("if {} {{", predicates.join(" && "))); } - if allow_multiples(&field) { - let expected_type = ExpectedType::expected_type(codes(&field)[0]).unwrap(); + if allow_multiples(field) { + let expected_type = ExpectedType::new(codes(field)[0]).unwrap(); let val = match (&*field.name, &expected_type) { - ("Pointer", _) => "*v", + ("Pointer", _) => "v", (_, &ExpectedType::Str) => "&v", (_, &ExpectedType::Binary) => "v.clone()", _ => "*v", }; - let write_converter = write_converter(&field); - let to_write = write_converter.replace("{}", val); + let write_converter = write_converter(field); + let to_write = write_converter.replace("{}", val).replace("&&", ""); let typ = code_pair_type(&expected_type); let normalized_field_name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; commands.push(format!( "{indent}for v in &obj.{field} {{", @@ -779,12 +785,12 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< "{indent} pairs.push(CodePair::new_{typ}({code}, {to_write}));", indent = indent, typ = typ, - code = codes(&field)[0], + code = codes(field)[0], to_write = to_write )); commands.push(format!("{indent}}}", indent = indent)); } else { - for command in code_pairs_for_field(&field) { + for command in code_pairs_for_field(field) { commands.push(format!( "{indent}pairs.push({command});", indent = indent, @@ -793,7 +799,7 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< } } - if predicates.len() > 0 { + if !predicates.is_empty() { commands.push(String::from("}")); } @@ -801,9 +807,9 @@ fn write_lines_for_field(field: &Element, write_conditions: Vec) -> Vec< } fn code_pairs_for_field(field: &Element) -> Vec { - let codes = codes(&field); + let codes = codes(field); match codes.len() { - 1 => vec![code_pair_for_field_and_code(codes[0], &field, None)], + 1 => vec![code_pair_for_field_and_code(codes[0], field, None)], _ => { let mut pairs = vec![]; for (i, &cd) in codes.iter().enumerate() { @@ -813,7 +819,7 @@ fn code_pairs_for_field(field: &Element) -> Vec { 2 => "z", _ => panic!("unexpected multiple codes"), }; - pairs.push(code_pair_for_field_and_code(cd, &field, Some(suffix))); + pairs.push(code_pair_for_field_and_code(cd, field, Some(suffix))); } pairs } @@ -821,14 +827,14 @@ fn code_pairs_for_field(field: &Element) -> Vec { } fn write_converter(field: &Element) -> String { - let code = codes(&field)[0]; - write_converter_with_code(code, &field) + let code = codes(field)[0]; + write_converter_with_code(code, field) } fn write_converter_with_code(code: i32, field: &Element) -> String { - let expected_type = ExpectedType::expected_type(code).unwrap(); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); - let mut write_converter = attr(&field, "WriteConverter"); + let mut write_converter = attr(field, "WriteConverter"); if field.name == "Pointer" { write_converter = String::from("&{}.as_string()"); } @@ -844,20 +850,20 @@ fn write_converter_with_code(code: i32, field: &Element) -> String { } fn code_pair_for_field_and_code(code: i32, field: &Element, suffix: Option<&str>) -> String { - let expected_type = ExpectedType::expected_type(code).unwrap(); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); - let write_converter = write_converter_with_code(code, &field); + let write_converter = write_converter_with_code(code, field); let normalized_field_name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; let mut field_access = format!("obj.{field}", field = normalized_field_name); if let Some(suffix) = suffix { field_access = format!("{}.{}", field_access, suffix); } let writer = write_converter.replace("{}", &field_access); - if name(&field) == "handle" && code == 5 { + if name(field) == "handle" && code == 5 { String::from("CodePair::new_string(5, &self.handle.as_string())") } else { format!( @@ -876,9 +882,9 @@ fn load_xml() -> Element { } fn generate_reader_function(element: &Element) -> bool { - attr(&element, "GenerateReaderFunction") != "false" + attr(element, "GenerateReaderFunction") != "false" } fn generate_writer_function(element: &Element) -> bool { - attr(&element, "GenerateWriterFunction") != "false" + attr(element, "GenerateWriterFunction") != "false" } diff --git a/build/other_helpers.rs b/build/other_helpers.rs index 7d47855..58d0de6 100644 --- a/build/other_helpers.rs +++ b/build/other_helpers.rs @@ -1,25 +1,27 @@ use crate::ExpectedType; pub fn reader_function(typ: &ExpectedType) -> &str { - match typ { - &ExpectedType::Boolean => "assert_bool", - &ExpectedType::Integer => "assert_i32", - &ExpectedType::Long => "assert_i64", - &ExpectedType::Short => "assert_i16", - &ExpectedType::Double => "assert_f64", - &ExpectedType::Str => "assert_string", - &ExpectedType::Binary => "assert_binary", + use ExpectedType::*; + match *typ { + Boolean => "assert_bool", + Integer => "assert_i32", + Long => "assert_i64", + Short => "assert_i16", + Double => "assert_f64", + Str => "assert_string", + Binary => "assert_binary", } } pub fn code_pair_type(typ: &ExpectedType) -> String { - match typ { - &ExpectedType::Boolean => String::from("bool"), - &ExpectedType::Integer => String::from("i32"), - &ExpectedType::Long => String::from("i64"), - &ExpectedType::Short => String::from("i16"), - &ExpectedType::Double => String::from("f64"), - &ExpectedType::Str => String::from("string"), - &ExpectedType::Binary => String::from("binary"), + use ExpectedType::*; + match *typ { + Boolean => String::from("bool"), + Integer => String::from("i32"), + Long => String::from("i64"), + Short => String::from("i16"), + Double => String::from("f64"), + Str => String::from("string"), + Binary => String::from("binary"), } } diff --git a/build/table_generator.rs b/build/table_generator.rs index b43f1f8..8e54e36 100644 --- a/build/table_generator.rs +++ b/build/table_generator.rs @@ -43,7 +43,7 @@ use crate::x_data; use crate::enums::*; use crate::enum_primitive::FromPrimitive; ".trim_start()); - fun.push_str("\n"); + fun.push('\n'); generate_table_items(&mut fun, &element); generate_table_reader(&mut fun, &element); generate_table_writer(&mut fun, &element); @@ -58,7 +58,7 @@ fn generate_table_items(fun: &mut String, element: &Element) { let table_item = &table.children[0]; fun.push_str("#[derive(Debug)]\n"); fun.push_str("#[cfg_attr(feature = \"serialize\", derive(Serialize, Deserialize))]\n"); - fun.push_str(&format!("pub struct {name} {{\n", name = name(&table_item))); + fun.push_str(&format!("pub struct {name} {{\n", name = name(table_item))); fun.push_str(" pub name: String,\n"); fun.push_str(" pub handle: Handle,\n"); fun.push_str(" #[doc(hidden)]\n"); @@ -67,21 +67,21 @@ fn generate_table_items(fun: &mut String, element: &Element) { fun.push_str(" pub x_data: Vec,\n"); for field in &table_item.children { let name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; if !seen_fields.contains(&name) { seen_fields.insert(name.clone()); let mut typ = if field.name == "Pointer" { String::from("Handle") } else { - attr(&field, "Type") + attr(field, "Type") }; - if allow_multiples(&field) { + if allow_multiples(field) { typ = format!("Vec<{}>", typ); } - let is_private = name.starts_with("_"); + let is_private = name.starts_with('_'); if is_private { fun.push_str(" #[doc(hidden)]\n"); } @@ -89,15 +89,15 @@ fn generate_table_items(fun: &mut String, element: &Element) { } } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); seen_fields.clear(); fun.push_str(&format!( "impl Default for {name} {{\n", - name = name(&table_item) + name = name(table_item) )); fun.push_str(" fn default() -> Self {\n"); - fun.push_str(&format!(" {name} {{\n", name = name(&table_item))); + fun.push_str(&format!(" {name} {{\n", name = name(table_item))); fun.push_str(" name: String::new(),\n"); fun.push_str(" handle: Handle::empty(),\n"); fun.push_str(" __owner_handle: Handle::empty(),\n"); @@ -105,16 +105,16 @@ fn generate_table_items(fun: &mut String, element: &Element) { fun.push_str(" x_data: vec![],\n"); for field in &table_item.children { let name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; if !seen_fields.contains(&name) { seen_fields.insert(name.clone()); - let default_value = match (&*field.name, allow_multiples(&field)) { + let default_value = match (&*field.name, allow_multiples(field)) { ("Pointer", true) => String::from("vec![]"), ("Pointer", false) => String::from("Handle::empty()"), - (_, _) => attr(&field, "DefaultValue"), + (_, _) => attr(field, "DefaultValue"), }; fun.push_str(&format!( " {field}: {default_value},\n", @@ -127,9 +127,9 @@ fn generate_table_items(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); - fun.push_str(&format!("impl {name} {{\n", name = name(&table_item))); + fun.push_str(&format!("impl {name} {{\n", name = name(table_item))); fun.push_str( " pub fn owner<'a>(&self, drawing: &'a Drawing) -> Option> {\n", ); @@ -139,7 +139,7 @@ fn generate_table_items(fun: &mut String, element: &Element) { fun.push_str(" self.__owner_handle = drawing.assign_and_get_handle(item);\n"); fun.push_str(" }\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } @@ -150,20 +150,20 @@ fn generate_table_reader(fun: &mut String, element: &Element) { fun.push_str(" if pair.code != 2 {\n"); fun.push_str(" return Err(DxfError::ExpectedTableType(pair.offset));\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" match &*pair.assert_string()? {\n"); for table in &element.children { fun.push_str(&format!( " \"{table_name}\" => read_{collection}(drawing, iter)?,\n", - table_name = attr(&table, "TypeString"), - collection = attr(&table, "Collection") + table_name = attr(table, "TypeString"), + collection = attr(table, "Collection") )); } fun.push_str(" _ => Drawing::swallow_table(iter)?,\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" match iter.next() {\n"); fun.push_str(" Some(Ok(CodePair { code: 0, value: CodePairValue::Str(ref s), .. })) if s == \"ENDTAB\" => (),\n"); fun.push_str(" Some(Ok(pair)) => return Err(DxfError::UnexpectedCodePair(pair, String::from(\"expected 0/ENDTAB\"))),\n"); @@ -174,32 +174,32 @@ fn generate_table_reader(fun: &mut String, element: &Element) { fun.push_str(" Some(Err(e)) => return Err(e),\n"); fun.push_str(" None => return Err(DxfError::UnexpectedEndOfInput),\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" Ok(())\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); for table in &element.children { let table_item = &table.children[0]; - let collection = attr(&table, "Collection"); + let collection = attr(table, "Collection"); let (item_type, _) = collection.split_at(collection.len() - 1); // remove the 's' suffix - fun.push_str(&format!("fn read_{collection}(drawing: &mut Drawing, iter: &mut CodePairPutBack) -> DxfResult<()> {{\n", collection=attr(&table, "Collection"))); + fun.push_str(&format!("fn read_{collection}(drawing: &mut Drawing, iter: &mut CodePairPutBack) -> DxfResult<()> {{\n", collection=attr(table, "Collection"))); fun.push_str(" loop {\n"); fun.push_str(" match iter.next() {\n"); fun.push_str(" Some(Ok(pair)) => {\n"); fun.push_str(" if pair.code == 0 {\n"); fun.push_str(&format!( " if pair.assert_string()? != \"{table_type}\" {{\n", - table_type = attr(&table, "TypeString") + table_type = attr(table, "TypeString") )); fun.push_str(" iter.put_back(Ok(pair));\n"); fun.push_str(" break;\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(&format!( " let mut item = {typ}::default();\n", - typ = attr(&table_item, "Name") + typ = attr(table_item, "Name") )); fun.push_str(" loop {\n"); fun.push_str(" match iter.next() {\n"); @@ -231,21 +231,21 @@ fn generate_table_reader(fun: &mut String, element: &Element) { " 330 => item.__owner_handle = pair.as_handle()?,\n", ); for field in &table_item.children { - if generate_reader(&field) { - for (i, &cd) in codes(&field).iter().enumerate() { - let reader = field_reader(&field); - let codes = codes(&field); + if generate_reader(field) { + for (i, &cd) in codes(field).iter().enumerate() { + let reader = field_reader(field); + let codes = codes(field); let write_cmd = match codes.len() { 1 => { - let read_fun = if allow_multiples(&field) { + let read_fun = if allow_multiples(field) { format!(".push({})", reader) } else { format!(" = {}", reader) }; let normalized_field_name = if field.name == "Pointer" { - format!("__{}_handle", name(&field)) + format!("__{}_handle", name(field)) } else { - name(&field) + name(field) }; format!( "item.{field}{read_fun}", @@ -262,7 +262,7 @@ fn generate_table_reader(fun: &mut String, element: &Element) { }; format!( "item.{field}.{suffix} = {reader}", - field = name(&field), + field = name(field), suffix = suffix, reader = reader ) @@ -286,7 +286,7 @@ fn generate_table_reader(fun: &mut String, element: &Element) { ); fun.push_str(" }\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" if item.handle.is_empty() {\n"); fun.push_str(&format!( " drawing.add_{item_type}(item);\n", @@ -308,10 +308,10 @@ fn generate_table_reader(fun: &mut String, element: &Element) { fun.push_str(" None => return Err(DxfError::UnexpectedEndOfInput),\n"); fun.push_str(" }\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" Ok(())\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } @@ -322,14 +322,14 @@ fn generate_table_writer(fun: &mut String, element: &Element) { for table in &element.children { let mut indention = ""; let mut predicates = vec![]; - if !min_version(&table).is_empty() { + if !min_version(table).is_empty() { indention = " "; predicates.push(format!( "drawing.header.version >= AcadVersion::{}", - min_version(&table) + min_version(table) )); } - if predicates.len() != 0 { + if !predicates.is_empty() { fun.push_str(&format!( " if {predicate} {{\n", predicate = predicates.join(" && ") @@ -337,32 +337,32 @@ fn generate_table_writer(fun: &mut String, element: &Element) { } fun.push_str(&format!( " {indention}add_{collection}_code_pairs(pairs, drawing, write_handles);\n", - collection = attr(&table, "Collection"), + collection = attr(table, "Collection"), indention = indention )); - if predicates.len() != 0 { + if !predicates.is_empty() { fun.push_str(" }\n"); } } fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); for table in &element.children { let table_item = &table.children[0]; fun.push_str("#[allow(clippy::cognitive_complexity)] // long function, no good way to simplify this\n"); - fun.push_str(&format!("fn add_{collection}_code_pairs(pairs: &mut Vec, drawing: &Drawing, write_handles: bool) {{\n", collection=attr(&table, "Collection"))); + fun.push_str(&format!("fn add_{collection}_code_pairs(pairs: &mut Vec, drawing: &Drawing, write_handles: bool) {{\n", collection=attr(table, "Collection"))); fun.push_str(&format!( " if !drawing.{collection}().any(|_| true) {{ // is empty\n", - collection = attr(&table, "Collection") + collection = attr(table, "Collection") )); fun.push_str(" return; // nothing to add\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" pairs.push(CodePair::new_str(0, \"TABLE\"));\n"); fun.push_str(&format!( " pairs.push(CodePair::new_str(2, \"{type_string}\"));\n", - type_string = attr(&table, "TypeString") + type_string = attr(table, "TypeString") )); // TODO: assign and write table handles @@ -371,81 +371,81 @@ fn generate_table_writer(fun: &mut String, element: &Element) { // fun.push_str(" }\n"); // fun.push_str("\n"); - let item_type = name(&table_item); + let item_type = name(table_item); fun.push_str(" pairs.push(CodePair::new_str(100, \"AcDbSymbolTable\"));\n"); fun.push_str(" pairs.push(CodePair::new_i16(70, 0));\n"); fun.push_str(&format!( " for item in drawing.{collection}() {{\n", - collection = attr(&table, "Collection") + collection = attr(table, "Collection") )); fun.push_str(&format!( " pairs.push(CodePair::new_str(0, \"{type_string}\"));\n", - type_string = attr(&table, "TypeString") + type_string = attr(table, "TypeString") )); fun.push_str(" if write_handles {\n"); - fun.push_str(&format!(" pairs.push(CodePair::new_string(5, &DrawingItem::{item_type}(&item).handle().as_string()));\n", + fun.push_str(&format!(" pairs.push(CodePair::new_string(5, &DrawingItem::{item_type}(item).handle().as_string()));\n", item_type=item_type)); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" if drawing.header.version >= AcadVersion::R14 {\n"); fun.push_str(" for group in &item.extension_data_groups {\n"); fun.push_str(" group.add_code_pairs(pairs);\n"); fun.push_str(" }\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" pairs.push(CodePair::new_str(100, \"AcDbSymbolTableRecord\"));\n"); fun.push_str(&format!( " pairs.push(CodePair::new_str(100, \"{class_name}\"));\n", - class_name = attr(&table_item, "ClassName") + class_name = attr(table_item, "ClassName") )); fun.push_str(" pairs.push(CodePair::new_string(2, &item.name));\n"); fun.push_str(" pairs.push(CodePair::new_i16(70, 0));\n"); // TODO: flags for field in &table_item.children { - if generate_writer(&field) { + if generate_writer(field) { let mut predicates = vec![]; - if !min_version(&field).is_empty() { + if !min_version(field).is_empty() { predicates.push(format!( "drawing.header.version >= AcadVersion::{}", - min_version(&field) + min_version(field) )); } - if !max_version(&field).is_empty() { + if !max_version(field).is_empty() { predicates.push(format!( "drawing.header.version <= AcadVersion::{}", - max_version(&field) + max_version(field) )); } - if !write_condition(&field).is_empty() { - predicates.push(write_condition(&field)); + if !write_condition(field).is_empty() { + predicates.push(write_condition(field)); } - if disable_writing_default(&field) { + if disable_writing_default(field) { predicates.push(format!( "item.{field} != {default_value}", - field = name(&field), - default_value = default_value(&field) + field = name(field), + default_value = default_value(field) )); } - let indent = if predicates.len() == 0 { "" } else { " " }; - if predicates.len() != 0 { + let indent = if predicates.is_empty() { "" } else { " " }; + if !predicates.is_empty() { fun.push_str(&format!( " if {predicate} {{\n", predicate = predicates.join(" && ") )); } - if allow_multiples(&field) { - let code = code(&field); + if allow_multiples(field) { + let code = code(field); if field.name == "Pointer" { fun.push_str(&format!( "{indent} for x in &item.__{field}_handle {{\n", indent = indent, - field = name(&field) + field = name(field) )); fun.push_str(&format!("{indent} pairs.push(CodePair::new_string({code}, &x.as_string()));\n", indent=indent, code=code)); } else { - let expected_type = ExpectedType::expected_type(code).unwrap(); + let expected_type = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&expected_type); let val = match expected_type { ExpectedType::Str => "x", @@ -455,7 +455,7 @@ fn generate_table_writer(fun: &mut String, element: &Element) { fun.push_str(&format!( "{indent} for x in &item.{field} {{\n", indent = indent, - field = name(&field) + field = name(field) )); fun.push_str(&format!( "{indent} pairs.push(CodePair::new_{typ}({code}, {val}));\n", @@ -467,20 +467,20 @@ fn generate_table_writer(fun: &mut String, element: &Element) { } fun.push_str(&format!("{indent} }}\n", indent = indent)); } else { - let codes = codes(&field); + let codes = codes(field); if codes.len() == 1 { let code = codes[0]; if field.name == "Pointer" { fun.push_str(&format!("{indent} pairs.push(CodePair::new_string({code}, &item.__{field}_handle.as_string()));\n", - indent=indent, code=code, field=name(&field))); + indent=indent, code=code, field=name(field))); } else { - let typ = ExpectedType::expected_type(code).unwrap(); + let typ = ExpectedType::new(code).unwrap(); let typ = code_pair_type(&typ); - let value = format!("item.{}", name(&field)); - let write_converter = if attr(&field, "WriteConverter").is_empty() { + let value = format!("item.{}", name(field)); + let write_converter = if attr(field, "WriteConverter").is_empty() { String::from("{}") } else { - attr(&field, "WriteConverter") + attr(field, "WriteConverter") }; let value = write_converter.replace("{}", &value); fun.push_str(&format!("{indent} pairs.push(CodePair::new_{typ}({code}, {value}));\n", @@ -495,12 +495,12 @@ fn generate_table_writer(fun: &mut String, element: &Element) { _ => panic!("impossible"), }; fun.push_str(&format!("{indent} pairs.push(CodePair::new_f64({code}, item.{field}.{suffix}));\n", - indent=indent, code=code, field=name(&field), suffix=suffix)); + indent=indent, code=code, field=name(field), suffix=suffix)); } } } - if predicates.len() != 0 { + if !predicates.is_empty() { fun.push_str(" }\n"); } } @@ -511,10 +511,10 @@ fn generate_table_writer(fun: &mut String, element: &Element) { fun.push_str(" }\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" pairs.push(CodePair::new_str(0, \"ENDTAB\"));\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } } diff --git a/build/test_helper_generator.rs b/build/test_helper_generator.rs index 3fbdf66..47e7422 100644 --- a/build/test_helper_generator.rs +++ b/build/test_helper_generator.rs @@ -28,7 +28,7 @@ use crate::enums::*; use crate::entities::*; use crate::objects::*; ".trim_start()); - fun.push_str("\n"); + fun.push('\n'); let mut file = File::create(generated_dir.join("tests/all_types.rs")) .ok() .unwrap(); @@ -48,9 +48,9 @@ fn generate_entity_helpers(fun: &mut String) { fun.push_str(" vec![\n"); for c in &element.children { if name(c) != "Entity" && name(c) != "DimensionBase" { - let type_string = attr(&c, "TypeString"); + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); - let subclass = attr(&c, "SubclassMarker"); + let subclass = attr(c, "SubclassMarker"); let maxver = max_version(c); let maxver = if maxver.is_empty() { String::from("R2018") @@ -68,7 +68,7 @@ fn generate_entity_helpers(fun: &mut String) { } fun.push_str(" ]\n"); fun.push_str("}\n"); - fun.push_str("\n"); + fun.push('\n'); } fn generate_object_helpers(fun: &mut String) { @@ -82,7 +82,7 @@ fn generate_object_helpers(fun: &mut String) { fun.push_str(" vec![\n"); for c in &element.children { if name(c) != "Object" { - let type_string = attr(&c, "TypeString"); + let type_string = attr(c, "TypeString"); let type_strings = type_string.split(',').collect::>(); let maxver = max_version(c); let maxver = if maxver.is_empty() { diff --git a/build/xml_helpers.rs b/build/xml_helpers.rs index 10d13b9..840b71f 100644 --- a/build/xml_helpers.rs +++ b/build/xml_helpers.rs @@ -4,9 +4,9 @@ use crate::other_helpers::*; use crate::ExpectedType; pub fn attr(element: &Element, name: &str) -> String { - match &element.attributes.get(name) { - &Some(v) => v.clone(), - &None => String::new(), + match element.attributes.get(name) { + Some(v) => v.clone(), + None => String::new(), } } @@ -23,41 +23,41 @@ pub fn code(element: &Element) -> i32 { } pub fn codes(element: &Element) -> Vec { - let code_overrides = attr(&element, "CodeOverrides"); + let code_overrides = attr(element, "CodeOverrides"); if code_overrides.is_empty() { - return vec![code(&element)]; + vec![code(element)] } else { return code_overrides - .split(",") + .split(',') .map(|c| c.parse::().unwrap()) .collect::>(); } } pub fn default_value(element: &Element) -> String { - attr(&element, "DefaultValue") + attr(element, "DefaultValue") } pub fn disable_writing_default(element: &Element) -> bool { - attr(&element, "DisableWritingDefault") == "true" + attr(element, "DisableWritingDefault") == "true" } pub fn generate_reader(element: &Element) -> bool { - attr(&element, "GenerateReader") != "false" + attr(element, "GenerateReader") != "false" } pub fn generate_writer(element: &Element) -> bool { - attr(&element, "GenerateWriter") != "false" + attr(element, "GenerateWriter") != "false" } pub fn field_reader(element: &Element) -> String { - let reader_override = attr(&element, "ReaderOverride"); + let reader_override = attr(element, "ReaderOverride"); if !reader_override.is_empty() { reader_override } else { - let expected_type = ExpectedType::expected_type(code(&element)).unwrap(); + let expected_type = ExpectedType::new(code(element)).unwrap(); let reader_fun = reader_function(&expected_type); - let mut read_converter = attr(&element, "ReadConverter"); + let mut read_converter = attr(element, "ReadConverter"); if read_converter.is_empty() { read_converter = String::from("{}"); } @@ -73,10 +73,10 @@ pub fn field_reader(element: &Element) -> String { pub fn methods_for_pointer_access(pointer: &Element) -> String { let mut fun = String::new(); - let typ = attr(&pointer, "Type"); - let sub_type = attr(&pointer, "SubType"); - let normalized_field_name = format!("__{}_handle", name(&pointer)); - let return_type = match (allow_multiples(&pointer), typ.is_empty()) { + let typ = attr(pointer, "Type"); + let sub_type = attr(pointer, "SubType"); + let normalized_field_name = format!("__{}_handle", name(pointer)); + let return_type = match (allow_multiples(pointer), typ.is_empty()) { (true, true) => String::from("Vec>"), (true, false) => format!("Vec<&'a {}>", typ), (false, true) => String::from("Option>"), @@ -86,45 +86,45 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { // get method fun.push_str(&format!( " pub fn {name}<'a>(&self, drawing: &'a Drawing) -> {return_type} {{\n", - name = name(&pointer), + name = name(pointer), return_type = return_type )); if !typ.is_empty() { - if allow_multiples(&pointer) { + if allow_multiples(pointer) { if !sub_type.is_empty() { fun.push_str(&format!( " self.{field}.iter().filter_map(|&h| {{\n", field = normalized_field_name )); - fun.push_str(&format!(" match drawing.item_by_handle(h) {{\n")); + fun.push_str(" match drawing.item_by_handle(h) {\n"); fun.push_str(&format!( " Some(DrawingItem::{typ}(val)) => {{\n", typ = typ )); - fun.push_str(&format!(" match val.specific {{\n")); + fun.push_str(" match val.specific {\n"); fun.push_str(&format!( " {typ}Type::{sub_type}(_) => Some(val),\n", typ = typ, sub_type = sub_type )); - fun.push_str(&format!(" _ => None,\n")); - fun.push_str(&format!(" }}\n")); - fun.push_str(&format!(" }},\n")); - fun.push_str(&format!(" _ => None,\n")); - fun.push_str(&format!(" }}\n")); + fun.push_str(" _ => None,\n"); + fun.push_str(" }\n"); + fun.push_str(" },\n"); + fun.push_str(" _ => None,\n"); + fun.push_str(" }\n"); fun.push_str(" }).collect()\n"); } else { fun.push_str(&format!( " self.{field}.iter().filter_map(|&h| {{\n", field = normalized_field_name )); - fun.push_str(&format!(" match drawing.item_by_handle(h) {{\n")); + fun.push_str(" match drawing.item_by_handle(h) {\n"); fun.push_str(&format!( " Some(DrawingItem::{typ}(val)) => Some(val),\n", typ = typ )); - fun.push_str(&format!(" _ => None,\n")); - fun.push_str(&format!(" }}\n")); + fun.push_str(" _ => None,\n"); + fun.push_str(" }\n"); fun.push_str(" }).collect()\n"); } } else { @@ -155,27 +155,28 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { fun.push_str(" _ => None,\n"); fun.push_str(" }\n"); } + } else if allow_multiples(pointer) { + fun.push_str(&format!( + " self.{field}.iter().filter_map(|&h| drawing.item_by_handle(h)).collect()\n", + field = normalized_field_name + )); } else { - if allow_multiples(&pointer) { - fun.push_str(&format!(" self.{field}.iter().filter_map(|&h| drawing.item_by_handle(h)).collect()\n", field=normalized_field_name)); - } else { - fun.push_str(&format!( - " drawing.item_by_handle(self.{field})\n", - field = normalized_field_name - )); - } + fun.push_str(&format!( + " drawing.item_by_handle(self.{field})\n", + field = normalized_field_name + )); } fun.push_str(" }\n"); // add/set method - if allow_multiples(&pointer) { + if allow_multiples(pointer) { match (typ.is_empty(), sub_type.is_empty()) { (false, false) => { // we know the very specific type and should fail if it's not correct fun.push_str(&format!( " pub fn add_{name}(&mut self, item: &{typ}) -> DxfResult<()> {{\n", - name = name(&pointer), + name = name(pointer), typ = typ )); fun.push_str(" match item.specific {\n"); @@ -183,14 +184,14 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { typ=typ, sub_type=sub_type, field=normalized_field_name)); fun.push_str(" _ => return Err(DxfError::WrongItemType),\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" Ok(())\n"); } (false, true) => { // we know the high level type fun.push_str(&format!( " pub fn add_{name}(&mut self, item: &{typ}) {{\n", - name = name(&pointer), + name = name(pointer), typ = typ )); fun.push_str(&format!( @@ -203,7 +204,7 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { // we don't know what type this should be fun.push_str(&format!( " pub fn add_{name}(&mut self, item: &DrawingItemMut) {{\n", - name = name(&pointer) + name = name(pointer) )); fun.push_str(&format!( " self.{field}.push(item.handle());\n", @@ -218,7 +219,7 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { // we know the very specific type and should fail if it's not correct fun.push_str(&format!( " pub fn set_{name}(&mut self, item: &{typ}) -> DxfResult<()> {{\n", - name = name(&pointer), + name = name(pointer), typ = typ )); fun.push_str(" match item.specific {\n"); @@ -226,14 +227,14 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { typ=typ, sub_type=sub_type, field=normalized_field_name)); fun.push_str(" _ => return Err(DxfError::WrongItemType),\n"); fun.push_str(" }\n"); - fun.push_str("\n"); + fun.push('\n'); fun.push_str(" Ok(())\n"); } (false, true) => { // we know the high level type fun.push_str(&format!( " pub fn set_{name}(&mut self, item: &{typ}) {{\n", - name = name(&pointer), + name = name(pointer), typ = typ )); fun.push_str(&format!( @@ -246,7 +247,7 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { // we don't know what type this should be fun.push_str(&format!( " pub fn set_{name}(&mut self, item: &DrawingItemMut) {{\n", - name = name(&pointer) + name = name(pointer) )); fun.push_str(&format!( " self.{field} = item.handle();\n", @@ -262,11 +263,11 @@ pub fn methods_for_pointer_access(pointer: &Element) -> String { } pub fn min_version(element: &Element) -> String { - attr(&element, "MinVersion") + attr(element, "MinVersion") } pub fn max_version(element: &Element) -> String { - attr(&element, "MaxVersion") + attr(element, "MaxVersion") } pub fn name(element: &Element) -> String { diff --git a/examples/src/block_examples.rs b/examples/src/block_examples.rs index c1b8414..83fee5c 100644 --- a/examples/src/block_examples.rs +++ b/examples/src/block_examples.rs @@ -14,8 +14,10 @@ fn basic_block_and_insert() -> dxf::DxfResult<()> { // // create a block with a unique name... // - let mut block = Block::default(); - block.name = "my-block-name".to_string(); + let mut block = Block { + name: "my-block-name".to_string(), + ..Default::default() + }; // // ...and populate it with entities @@ -37,8 +39,10 @@ fn basic_block_and_insert() -> dxf::DxfResult<()> { // // add a reference to the block with an `INSERT` entity // - let mut insert = Insert::default(); - insert.name = "my-block-name".to_string(); // use the same name as the block defined above + let mut insert = Insert { + name: "my-block-name".to_string(), // use the same name as the block defined above + ..Default::default() + }; insert.location = Point::new(3.0, 3.0, 0.0); // select the base-point of the insertion drawing.add_entity(Entity { common: Default::default(), diff --git a/examples/src/line_type_examples.rs b/examples/src/line_type_examples.rs index 9e63a54..3e15a2f 100644 --- a/examples/src/line_type_examples.rs +++ b/examples/src/line_type_examples.rs @@ -12,8 +12,10 @@ fn apply_line_types_to_entities() -> dxf::DxfResult<()> { // // create a new line type named "dashed-lines"... // - let mut line_type = dxf::tables::LineType::default(); - line_type.name = String::from("dashed-lines"); + let mut line_type = dxf::tables::LineType { + name: "dash-lines".to_string(), + ..Default::default() + }; line_type.total_pattern_length = 1.0; // line pattern contains 2 elements; positive values draw a line, negative values draw a gap // the following draws 3/4 of a line with a 1/4 gap diff --git a/src/block.rs b/src/block.rs index 2560a08..34f33c9 100644 --- a/src/block.rs +++ b/src/block.rs @@ -711,8 +711,10 @@ mod tests { fn write_block_r12_compat() { let mut drawing = Drawing::new(); drawing.header.version = AcadVersion::R12; - let mut block = Block::default(); - block.name = "block-name".to_string(); + let mut block = Block { + name: "block-name".to_string(), + ..Default::default() + }; block.entities.push(Entity { common: Default::default(), specific: EntityType::Line(Line::new( diff --git a/src/code_pair.rs b/src/code_pair.rs index 743e30d..dbf74c7 100644 --- a/src/code_pair.rs +++ b/src/code_pair.rs @@ -99,7 +99,7 @@ impl CodePair { impl CodePair { pub(crate) fn as_handle(&self) -> DxfResult { let mut bytes = vec![]; - parse_hex_string(&self.assert_string()?.trim(), &mut bytes, self.offset)?; + parse_hex_string(self.assert_string()?.trim(), &mut bytes, self.offset)?; while bytes.len() < 8 { bytes.insert(0, 0); } diff --git a/src/code_pair_iter.rs b/src/code_pair_iter.rs index c43428a..c724880 100644 --- a/src/code_pair_iter.rs +++ b/src/code_pair_iter.rs @@ -110,7 +110,7 @@ impl TextCodePairIter { }; // construct the value pair - let expected_type = match ExpectedType::expected_type(code) { + let expected_type = match ExpectedType::new(code) { Some(t) => t, None => return Some(Err(DxfError::UnexpectedEnumValue(self.offset))), }; @@ -204,7 +204,7 @@ impl BinaryCodePairIter { } // Read value. If no data is available die horribly. - let expected_type = match ExpectedType::expected_type(code) { + let expected_type = match ExpectedType::new(code) { Some(t) => t, None => return Some(Err(DxfError::UnexpectedEnumValue(self.offset))), }; @@ -239,7 +239,7 @@ impl BinaryCodePairIter { ), ExpectedType::Str => { let mut value = try_from_dxf_result!(self.read_string_binary()); - if !self.code_size_detection_complete && code == 0 && value == "" { + if !self.code_size_detection_complete && code == 0 && value.is_empty() { // If this is the first pair being read and the code is 0, the only valid string value is "SECTION". // If the read value is instead empty, that means the string reader found a single 0x00 byte which // indicates that this is a post R13 binary file where codes are always read as 2 bytes. The 0x00 diff --git a/src/code_pair_value.rs b/src/code_pair_value.rs index 917c626..0263538 100644 --- a/src/code_pair_value.rs +++ b/src/code_pair_value.rs @@ -214,13 +214,9 @@ pub(crate) fn un_escape_ascii_to_unicode(val: &str) -> String { seq.push(c); if i == sequence_start + 6 { in_escape_sequence = false; - if seq.starts_with("\\U+") { - let code_str = &seq[3..]; + if let Some(code_str) = seq.strip_prefix("\\U+") { let decoded = match u32::from_str_radix(code_str, 16) { - Ok(code) => match std::char::from_u32(code) { - Some(c) => c, - None => '?', - }, + Ok(code) => std::char::from_u32(code).unwrap_or('?'), Err(_) => '?', }; result.push(decoded); diff --git a/src/code_pair_writer.rs b/src/code_pair_writer.rs index 1a6e7fb..8d94715 100644 --- a/src/code_pair_writer.rs +++ b/src/code_pair_writer.rs @@ -53,7 +53,7 @@ impl<'a, T: Write + ?Sized> CodePairWriter<'a, T> { .write_fmt(format_args!("{: >3}\r\n", pair.code))?; match pair.value { CodePairValue::Str(ref s) => { - let s = escape_control_characters(&s); + let s = escape_control_characters(s); let s = if self.text_as_ascii { escape_unicode_to_ascii(&s) } else { @@ -124,7 +124,7 @@ mod tests { version: AcadVersion::R2004, }; writer - .write_binary_code_pair(&pair) + .write_binary_code_pair(pair) .expect("expected write to succeed"); buf.seek(SeekFrom::Start(0)) .expect("expected seek to succeed"); @@ -140,7 +140,7 @@ mod tests { version: AcadVersion::R2004, }; writer - .write_ascii_code_pair(&pair) + .write_ascii_code_pair(pair) .expect("expected write to succeed"); buf.seek(SeekFrom::Start(0)) .expect("expected seek to succeed"); diff --git a/src/drawing.rs b/src/drawing.rs index 496f821..9f1159d 100644 --- a/src/drawing.rs +++ b/src/drawing.rs @@ -781,7 +781,7 @@ impl Drawing { _ => None, }; if let Some(dim_style_name) = dim_style_name { - self.ensure_dimension_style_is_present(&dim_style_name); + self.ensure_dimension_style_is_present(dim_style_name); } } fn ensure_dimension_style_is_present(&mut self, dim_style_name: &str) { @@ -802,12 +802,12 @@ impl Drawing { match &obj.specific { ObjectType::LayerFilter(ref l) => { for layer_name in &l.layer_names { - self.ensure_layer_is_present(&layer_name); + self.ensure_layer_is_present(layer_name); } } ObjectType::LayerIndex(ref l) => { for layer_name in &l.layer_names { - self.ensure_layer_is_present(&layer_name); + self.ensure_layer_is_present(layer_name); } } _ => (), @@ -860,7 +860,7 @@ impl Drawing { _ => None, }; if let Some(text_style_name) = text_style_name { - self.ensure_text_style_is_present(&text_style_name); + self.ensure_text_style_is_present(text_style_name); } } fn ensure_text_style_is_present_for_object(&mut self, obj: &Object) { @@ -918,7 +918,7 @@ impl Drawing { pub(crate) fn add_tables_pairs(&self, pairs: &mut Vec, write_handles: bool) { pairs.push(CodePair::new_str(0, "SECTION")); pairs.push(CodePair::new_str(2, "TABLES")); - add_table_code_pairs(&self, pairs, write_handles); + add_table_code_pairs(self, pairs, write_handles); pairs.push(CodePair::new_str(0, "ENDSEC")); } pub(crate) fn add_blocks_pairs(&self, pairs: &mut Vec, write_handles: bool) { diff --git a/src/drawing_item.rs b/src/drawing_item.rs index 86e2df3..47f78aa 100644 --- a/src/drawing_item.rs +++ b/src/drawing_item.rs @@ -22,18 +22,18 @@ pub enum DrawingItem<'a> { impl<'a> DrawingItem<'a> { pub fn handle(&self) -> Handle { match self { - DrawingItem::AppId(ref app_id) => app_id.handle, - DrawingItem::Block(ref b) => b.handle, - DrawingItem::BlockRecord(ref br) => br.handle, - DrawingItem::DimStyle(ref ds) => ds.handle, - DrawingItem::Entity(&Entity { ref common, .. }) => common.handle, - DrawingItem::Layer(ref l) => l.handle, - DrawingItem::LineType(ref l) => l.handle, - DrawingItem::Object(&Object { ref common, .. }) => common.handle, - DrawingItem::Style(ref s) => s.handle, - DrawingItem::Ucs(ref u) => u.handle, - DrawingItem::View(ref v) => v.handle, - DrawingItem::ViewPort(ref v) => v.handle, + DrawingItem::AppId(app_id) => app_id.handle, + DrawingItem::Block(b) => b.handle, + DrawingItem::BlockRecord(br) => br.handle, + DrawingItem::DimStyle(ds) => ds.handle, + DrawingItem::Entity(Entity { common, .. }) => common.handle, + DrawingItem::Layer(l) => l.handle, + DrawingItem::LineType(l) => l.handle, + DrawingItem::Object(Object { common, .. }) => common.handle, + DrawingItem::Style(s) => s.handle, + DrawingItem::Ucs(u) => u.handle, + DrawingItem::View(v) => v.handle, + DrawingItem::ViewPort(v) => v.handle, } } } diff --git a/src/dxb_reader.rs b/src/dxb_reader.rs index 489b5ba..36a6dda 100644 --- a/src/dxb_reader.rs +++ b/src/dxb_reader.rs @@ -114,7 +114,7 @@ impl DxbReader { // other DxbItemType::BlockBase => { let loc = Point::new(self.read_n()?, self.read_n()?, 0.0); - if block_base == None && entities.is_empty() { + if block_base.is_none() && entities.is_empty() { // only if this is the first item encountered block_base = Some(loc); } else { @@ -161,8 +161,10 @@ impl DxbReader { drawing.clear(); match block_base { Some(location) => { - let mut block = Block::default(); - block.base_point = location; + let mut block = Block { + base_point: location, + ..Default::default() + }; block.entities = gathered_entities; drawing.add_block(block); } diff --git a/src/dxb_writer.rs b/src/dxb_writer.rs index d28f881..4e86ad5 100644 --- a/src/dxb_writer.rs +++ b/src/dxb_writer.rs @@ -48,7 +48,7 @@ impl DxbWriter { let groups = drawing.entities().group_by(|&e| e.common.layer.clone()); for (layer, entities) in &groups { self.write_item_type(DxbItemType::NewLayer)?; - self.write_null_terminated_string(&*layer)?; + self.write_null_terminated_string(&layer)?; for entity in entities { match entity.common.color.raw_value() { c if c == last_color => (), // same color, do nothing @@ -58,7 +58,7 @@ impl DxbWriter { self.write_w(last_color)?; } } - self.write_entity(&entity)?; + self.write_entity(entity)?; } } } @@ -69,41 +69,41 @@ impl DxbWriter { } fn write_entities(&mut self, entities: &[Entity]) -> DxfResult<()> { for entity in entities.iter() { - self.write_entity(&entity)?; + self.write_entity(entity)?; } Ok(()) } fn write_entity(&mut self, entity: &Entity) -> DxfResult<()> { match &entity.specific { EntityType::Arc(ref arc) => { - self.write_arc(&arc)?; + self.write_arc(arc)?; } EntityType::Circle(ref circle) => { - self.write_circle(&circle)?; + self.write_circle(circle)?; } EntityType::Face3D(ref face) => { - self.write_face(&face)?; + self.write_face(face)?; } EntityType::Line(ref line) => { - self.write_line(&line)?; + self.write_line(line)?; } EntityType::ModelPoint(ref point) => { - self.write_point(&point)?; + self.write_point(point)?; } EntityType::Polyline(ref poly) => { - self.write_polyline(&poly)?; + self.write_polyline(poly)?; } EntityType::Seqend(_) => { self.write_seqend()?; } EntityType::Solid(ref solid) => { - self.write_solid(&solid)?; + self.write_solid(solid)?; } EntityType::Trace(ref trace) => { - self.write_trace(&trace)?; + self.write_trace(trace)?; } EntityType::Vertex(ref vertex) => { - self.write_vertex(&vertex)?; + self.write_vertex(vertex)?; } _ => (), } @@ -161,7 +161,7 @@ impl DxbWriter { self.write_item_type(DxbItemType::Polyline)?; self.write_w(if poly.is_closed() { 1 } else { 0 })?; for vertex in poly.vertices() { - self.write_vertex(&vertex)?; + self.write_vertex(vertex)?; } self.write_seqend()?; Ok(()) diff --git a/src/entity.rs b/src/entity.rs index 1e08f76..ff24a59 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -669,8 +669,8 @@ impl Entity { } } fn apply_code_pair(&mut self, pair: &CodePair, iter: &mut CodePairPutBack) -> DxfResult<()> { - if !self.specific.try_apply_code_pair(&pair)? { - self.common.apply_individual_pair(&pair, iter)?; + if !self.specific.try_apply_code_pair(pair)? { + self.common.apply_individual_pair(pair, iter)?; } Ok(()) } @@ -1564,7 +1564,7 @@ impl Entity { }; a.add_code_pairs(pairs, version, write_handles); } - if ins.__attributes_and_handles.len() > 0 { + if !ins.__attributes_and_handles.is_empty() { Entity::add_code_pairs_seqend(pairs, &ins.__seqend_handle, write_handles); } } @@ -2649,8 +2649,10 @@ mod tests { fn write_lw_polyline() { let mut drawing = Drawing::new(); drawing.header.version = AcadVersion::R2013; - let mut poly = LwPolyline::default(); - poly.constant_width = 43.0; + let mut poly = LwPolyline { + constant_width: 43.0, + ..Default::default() + }; poly.vertices.push(LwPolylineVertex { x: 1.1, y: 2.1, @@ -2817,7 +2819,7 @@ mod tests { vec![ CodePair::new_str(0, "INSERT"), CodePair::new_i16(66, 1), // includes attributes - CodePair::new_str(0, "ATTRIB"), // these are embedded attributes tied to the `INSERT` enttiy + CodePair::new_str(0, "ATTRIB"), // these are embedded attributes tied to the `INSERT` entity CodePair::new_str(0, "ATTRIB"), CodePair::new_str(0, "SEQEND"), // this is an embedded `SEQEND` entity tied to the `INSERT` entity ], @@ -2826,15 +2828,17 @@ mod tests { assert_eq!(1, entities.len()); match entities[0].specific { EntityType::Insert(ref ins) => assert_eq!(2, ins.attributes().count()), - _ => panic!("exepcted an INSERT"), + _ => panic!("expected an INSERT"), } } #[test] fn write_insert_no_embedded_attributes() { let mut drawing = Drawing::new(); - let mut ins = Insert::default(); - ins.name = "insert-name".to_string(); + let ins = Insert { + name: "insert-name".to_string(), + ..Default::default() + }; let ent = Entity::new(EntityType::Insert(ins)); drawing.add_entity(ent); assert_not_contains_pairs( @@ -2871,8 +2875,10 @@ mod tests { fn write_insert_no_extrusion_on_r12() { let mut drawing = Drawing::new(); drawing.header.version = AcadVersion::R12; - let mut ins = Insert::default(); - ins.extrusion_direction = Vector::new(1.0, 2.0, 3.0); + let ins = Insert { + extrusion_direction: Vector::new(1.0, 2.0, 3.0), + ..Default::default() + }; let ent = Entity::new(EntityType::Insert(ins)); drawing.add_entity(ent); assert_not_contains_pairs( @@ -2889,8 +2895,10 @@ mod tests { fn write_insert_extrusion_on_r13() { let mut drawing = Drawing::new(); drawing.header.version = AcadVersion::R13; - let mut ins = Insert::default(); - ins.extrusion_direction = Vector::new(1.0, 2.0, 3.0); + let ins = Insert { + extrusion_direction: Vector::new(1.0, 2.0, 3.0), + ..Default::default() + }; let ent = Entity::new(EntityType::Insert(ins)); drawing.add_entity(ent); assert_contains_pairs( @@ -2935,7 +2943,7 @@ mod tests { assert_eq!(1, entities.len()); match entities[0].specific { EntityType::Attribute(ref att) => assert_eq!("m_text", att.m_text.text), - _ => panic!("exepcted an attribute"), + _ => panic!("expected an attribute"), } } @@ -3217,8 +3225,10 @@ mod tests { file.clear(); let objects = file.objects().collect::>(); assert_eq!(0, objects.len()); - let mut mline = MLine::default(); - mline.style_name = String::from("style name"); + let mline = MLine { + style_name: "style name".to_string(), + ..Default::default() + }; file.add_entity(Entity::new(EntityType::MLine(mline))); file.normalize(); let objects = file.objects().collect::>(); diff --git a/src/expected_type.rs b/src/expected_type.rs index d91d241..9053f27 100644 --- a/src/expected_type.rs +++ b/src/expected_type.rs @@ -12,7 +12,7 @@ pub enum ExpectedType { impl ExpectedType { /// Returns an option of the `ExpectedType` for the given code, or `None`. - pub fn expected_type(code: i32) -> ::std::option::Option { + pub fn new(code: i32) -> ::std::option::Option { match code { 0..=9 => Some(ExpectedType::Str), 10..=39 => Some(ExpectedType::Double), diff --git a/src/header.rs b/src/header.rs index 121f172..a40a345 100644 --- a/src/header.rs +++ b/src/header.rs @@ -221,14 +221,16 @@ mod tests { #[test] fn normalize_header() { - let mut header = Header::default(); - header.default_text_height = -1.0; // $TEXTSIZE; normalized to 0.2 - header.trace_width = 0.0; // $TRACEWID; normalized to 0.05 - header.text_style = String::new(); // $TEXTSTYLE; normalized to "STANDARD" - header.current_layer = String::new(); // $CLAYER; normalized to "0" - header.current_entity_line_type = String::new(); // $CELTYPE; normalized to "BYLAYER" - header.dimension_style_name = String::new(); // $DIMSTYLE; normalized to "STANDARD" - header.file_name = String::new(); // $MENU; normalized to "." + let mut header = Header { + default_text_height: -1.0, // $TEXTSIZE; normalized to 0.2, + trace_width: 0.0, // $TRACEWID; normalized to 0.05 + text_style: String::new(), // $TEXTSTYLE; normalized to "STANDARD" + current_layer: String::new(), // $CLAYER; normalized to "0" + current_entity_line_type: String::new(), // $CELTYPE; normalized to "BYLAYER" + dimension_style_name: String::new(), // $DIMSTYLE; normalized to "STANDARD" + file_name: String::new(), // $MENU; normalized to "." + ..Default::default() + }; header.normalize(); assert!(approx_eq!(f64, 0.2, header.default_text_height)); assert!(approx_eq!(f64, 0.05, header.trace_width)); @@ -383,7 +385,7 @@ mod tests { } #[test] - fn dont_write_suppressed_variables() { + fn do_not_write_suppressed_variables() { let mut drawing = Drawing::new(); drawing.header.version = AcadVersion::R2004; assert_contains_pairs( diff --git a/src/helper_functions.rs b/src/helper_functions.rs index 5151097..e2b6850 100644 --- a/src/helper_functions.rs +++ b/src/helper_functions.rs @@ -608,7 +608,7 @@ pub mod tests { } pub fn assert_contains(drawing: &Drawing, contents: String) { - let actual = to_test_string(&drawing); + let actual = to_test_string(drawing); assert!(actual.contains(&contents)); } @@ -638,7 +638,7 @@ pub mod tests { where T: PartialEq, { - let actual_index = try_find_index(&actual, &expected); + let actual_index = try_find_index(actual, expected); assert!(actual_index.is_some()); } @@ -653,7 +653,7 @@ pub mod tests { } pub fn assert_not_contains(drawing: &Drawing, contents: String) { - let actual = to_test_string(&drawing); + let actual = to_test_string(drawing); assert!(!actual.contains(&contents)); } diff --git a/src/misc_tests/integration.rs b/src/misc_tests/integration.rs index 5a9f707..216f26a 100644 --- a/src/misc_tests/integration.rs +++ b/src/misc_tests/integration.rs @@ -68,7 +68,7 @@ impl Oda { } assert!(exit_code.success()); - Drawing::load_file(&format!("{}/drawing.dxf", self.output_path)).unwrap() + Drawing::load_file(format!("{}/drawing.dxf", self.output_path)).unwrap() } fn version_string(version: AcadVersion) -> String { let s = match version { @@ -176,13 +176,13 @@ impl AutoCAD { script_path.push(&self.temp_path); script_path.push("script.scr"); let script_path = script_path.to_str().unwrap(); - write(&script_path, &script_contents).expect("failed to write script file"); + write(script_path, &script_contents).expect("failed to write script file"); let mut acad_convert = Command::new(&self.acad_path) .arg("/i") .arg(input_file) .arg("/s") - .arg(&script_path) + .arg(script_path) .spawn() .expect("Failed to spawn acad"); let exit_code = acad_convert.wait().expect("Failed to wait for acad"); @@ -206,7 +206,7 @@ impl AutoCAD { } assert!(exit_code.success()); - Drawing::load_file(&format!("{}/output.dxf", self.temp_path)).unwrap() + Drawing::load_file(format!("{}/output.dxf", self.temp_path)).unwrap() } fn version_string(version: AcadVersion) -> String { let s = match version { @@ -314,8 +314,10 @@ fn simple_line_can_be_read_by_acad_r12() { fn block_insert_can_be_read_by_acad_r12() { let acad = require_acad!(); let mut drawing = Drawing::new(); - let mut block = Block::default(); - block.name = "my-block-name".to_string(); + let mut block = Block { + name: "my-block-name".to_string(), + ..Default::default() + }; block.entities.push(Entity { common: Default::default(), specific: EntityType::Line(Line::new( @@ -324,8 +326,10 @@ fn block_insert_can_be_read_by_acad_r12() { )), }); drawing.add_block(block); - let mut insert = Insert::default(); - insert.name = "my-block-name".to_string(); + let mut insert = Insert { + name: "my-block-name".to_string(), + ..Default::default() + }; insert.location = Point::new(3.0, 3.0, 0.0); drawing.add_entity(Entity { common: Default::default(), diff --git a/src/object.rs b/src/object.rs index 57f8528..9ed6ac4 100644 --- a/src/object.rs +++ b/src/object.rs @@ -157,8 +157,8 @@ impl Object { } } fn apply_code_pair(&mut self, pair: &CodePair, iter: &mut CodePairPutBack) -> DxfResult<()> { - if !self.specific.try_apply_code_pair(&pair)? { - self.common.apply_individual_pair(&pair, iter)?; + if !self.specific.try_apply_code_pair(pair)? { + self.common.apply_individual_pair(pair, iter)?; } Ok(()) } @@ -306,7 +306,7 @@ impl Object { Object::apply_custom_reader_sunstudy(&mut self.common, ss, iter) } ObjectType::TableStyle(ref mut ts) => { - Object::apply_custom_reader_tabletyle(&mut self.common, ts, iter) + Object::apply_custom_reader_tablestyle(&mut self.common, ts, iter) } ObjectType::XRecordObject(ref mut xr) => { Object::apply_custom_reader_xrecordobject(&mut self.common, xr, iter) @@ -1130,7 +1130,7 @@ impl Object { let pair = next_pair!(iter); match pair.code { 1 => { - // value should be "SectionTypeSettings", but it doesn't realy matter + // value should be "SectionTypeSettings", but it doesn't really matter while let Some(ts) = SectionTypeSettings::read(iter)? { ss.geometry_settings.push(ts); } @@ -1384,7 +1384,7 @@ impl Object { } } } - fn apply_custom_reader_tabletyle( + fn apply_custom_reader_tablestyle( common: &mut ObjectCommon, ts: &mut TableStyle, iter: &mut CodePairPutBack, @@ -1583,7 +1583,7 @@ impl Object { for light in &ll.__lights_handle { pairs.push(CodePair::new_string(5, &light.as_string())); // TODO: write the light's real name - pairs.push(CodePair::new_string(1, &String::new())); + pairs.push(CodePair::new_string(1, "")); } } ObjectType::SectionSettings(ref ss) => { @@ -1655,7 +1655,7 @@ impl Object { true } - fn add_post_code_pairs(&self, _pairs: &mut Vec, _version: AcadVersion) { + fn add_post_code_pairs(&self, _pairs: &mut [CodePair], _version: AcadVersion) { // use the following pattern if this method is needed // match self.specific { // _ => (), @@ -2224,7 +2224,7 @@ mod tests { // validate specific match (&expected_type, &obj.specific) { - (&ObjectType::LayerIndex(ref a), &ObjectType::LayerIndex(ref b)) => { + (ObjectType::LayerIndex(a), ObjectType::LayerIndex(b)) => { // LayerIndex has a timestamp that will obviously differ; the remaining fields must be checked manually assert_eq!(a.layer_names, b.layer_names); assert_eq!(a.__id_buffers_handle, b.__id_buffers_handle); diff --git a/src/table.rs b/src/table.rs index 14acc2e..6b7c5b9 100644 --- a/src/table.rs +++ b/src/table.rs @@ -181,9 +181,12 @@ mod tests { #[test] fn write_layer() { let mut drawing = Drawing::new(); - let mut layer = Layer::default(); - layer.name = String::from("layer-name"); - layer.color = Color::from_index(3); + let layer = Layer { + name: String::from("layer-name"), + color: Color::from_index(3), + ..Default::default() + }; + drawing.add_layer(layer); assert_contains_pairs( &drawing, @@ -202,10 +205,12 @@ mod tests { #[test] fn normalize_layer() { - let mut layer = Layer::default(); - layer.name = String::from("layer-name"); - layer.color = Color::by_layer(); // value 256 not valid; normalized to 7 - layer.line_type_name = String::from(""); // empty string not valid; normalized to CONTINUOUS + let mut layer = Layer { + name: String::from("layer-name"), + color: Color::by_layer(), // value 256 not valid; normalized to 7 + line_type_name: String::from(""), // empty string not valid; normalized to CONTINUOUS + ..Default::default() + }; layer.normalize(); assert_eq!(Some(7), layer.color.index()); assert_eq!("CONTINUOUS", layer.line_type_name); @@ -213,10 +218,12 @@ mod tests { #[test] fn normalize_view() { - let mut view = View::default(); - view.view_height = 0.0; // invalid; normalized to 1.0 - view.view_width = -1.0; // invalid; normalized to 1.0 - view.lens_length = 42.0; // valid + let mut view = View { + view_height: 0.0, // invalid; normalized to 1.0 + view_width: -1.0, // invalid; normalized to 1.0 + lens_length: 42.0, // valid + ..Default::default() + }; view.normalize(); assert!(approx_eq!(f64, 1.0, view.view_height)); assert!(approx_eq!(f64, 1.0, view.view_width)); diff --git a/src/thumbnail.rs b/src/thumbnail.rs index 5ffd45d..e14f48c 100644 --- a/src/thumbnail.rs +++ b/src/thumbnail.rs @@ -75,12 +75,12 @@ fn read_thumbnail_bytes_from_code_pairs(iter: &mut CodePairPutBack) -> DxfResult fn update_thumbnail_data_offset_in_situ(data: &mut Vec) -> DxfResult { // calculate the image data offset - let dib_header_size = read_i32(&data, FILE_HEADER_LENGTH)? as usize; + let dib_header_size = read_i32(data, FILE_HEADER_LENGTH)? as usize; // calculate the palette size let palette_size = if dib_header_size >= BITMAP_HEADER_PALETTE_COUNT_OFFSET + 4 { let palette_color_count = read_u32( - &data, + data, FILE_HEADER_LENGTH + BITMAP_HEADER_PALETTE_COUNT_OFFSET, )? as usize; palette_color_count * 4 // always 4 bytes: BGRA @@ -196,7 +196,7 @@ fn set_thumbnail_offset_for_bitmapv4header_palette_256() { } fn read_thumbnail_from_bytes(data: &[u8]) -> DxfResult> { - let image = image::load_from_memory(&data)?; + let image = image::load_from_memory(data)?; Ok(Some(image)) }