Skip to main content

oxihuman_export/
step_solid_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! STEP solid body export stub.
6
7/// STEP entity stub types used in AP214/AP203.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum StepEntityKind {
10    ManifoldSolidBrep,
11    ClosedShell,
12    AdvancedFaceSurface,
13}
14
15/// A STEP entity record stub.
16#[derive(Debug, Clone)]
17pub struct StepEntity {
18    pub id: u32,
19    pub kind: StepEntityKind,
20    pub attributes: Vec<String>,
21}
22
23/// STEP solid export container.
24#[derive(Debug, Clone, Default)]
25pub struct StepSolidExport {
26    pub entities: Vec<StepEntity>,
27    pub schema: String,
28    pub author: String,
29}
30
31/// Create a new STEP solid export.
32pub fn new_step_solid_export(schema: &str, author: &str) -> StepSolidExport {
33    StepSolidExport {
34        entities: Vec::new(),
35        schema: schema.to_string(),
36        author: author.to_string(),
37    }
38}
39
40/// Add a STEP entity and return its ID.
41pub fn add_step_entity(
42    export: &mut StepSolidExport,
43    kind: StepEntityKind,
44    attributes: Vec<String>,
45) -> u32 {
46    let id = export.entities.len() as u32 + 1;
47    export.entities.push(StepEntity {
48        id,
49        kind,
50        attributes,
51    });
52    id
53}
54
55/// Return the entity count.
56pub fn step_entity_count(export: &StepSolidExport) -> usize {
57    export.entities.len()
58}
59
60/// Render the STEP FILE_DESCRIPTION header (stub).
61pub fn step_file_header(export: &StepSolidExport) -> String {
62    format!(
63        "ISO-10303-21;\nHEADER;\nFILE_SCHEMA(('{}'));\nFILE_AUTHOR('{}');\nENDSEC;",
64        export.schema, export.author
65    )
66}
67
68/// Render a STEP data section entity line (stub).
69pub fn step_entity_line(entity: &StepEntity) -> String {
70    let kind_str = match entity.kind {
71        StepEntityKind::ManifoldSolidBrep => "MANIFOLD_SOLID_BREP",
72        StepEntityKind::ClosedShell => "CLOSED_SHELL",
73        StepEntityKind::AdvancedFaceSurface => "ADVANCED_FACE",
74    };
75    format!(
76        "#{} = {}({});",
77        entity.id,
78        kind_str,
79        entity.attributes.join(",")
80    )
81}
82
83/// Validate that the export has at least one entity.
84pub fn validate_step_export(export: &StepSolidExport) -> bool {
85    !export.entities.is_empty()
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_new_export_empty() {
94        let exp = new_step_solid_export("AP214", "Alice");
95        assert_eq!(step_entity_count(&exp), 0);
96    }
97
98    #[test]
99    fn test_add_entity_returns_id() {
100        let mut exp = new_step_solid_export("AP214", "Alice");
101        let id = add_step_entity(
102            &mut exp,
103            StepEntityKind::ManifoldSolidBrep,
104            vec!["''".into()],
105        );
106        assert_eq!(id, 1);
107    }
108
109    #[test]
110    fn test_entity_count_increments() {
111        let mut exp = new_step_solid_export("AP214", "Alice");
112        add_step_entity(&mut exp, StepEntityKind::ClosedShell, vec![]);
113        add_step_entity(&mut exp, StepEntityKind::AdvancedFaceSurface, vec![]);
114        assert_eq!(step_entity_count(&exp), 2);
115    }
116
117    #[test]
118    fn test_file_header_contains_schema() {
119        let exp = new_step_solid_export("AP214", "Bob");
120        assert!(step_file_header(&exp).contains("AP214"));
121    }
122
123    #[test]
124    fn test_file_header_contains_author() {
125        let exp = new_step_solid_export("AP203", "Charlie");
126        assert!(step_file_header(&exp).contains("Charlie"));
127    }
128
129    #[test]
130    fn test_entity_line_manifold() {
131        let e = StepEntity {
132            id: 1,
133            kind: StepEntityKind::ManifoldSolidBrep,
134            attributes: vec![],
135        };
136        assert!(step_entity_line(&e).contains("MANIFOLD_SOLID_BREP"));
137    }
138
139    #[test]
140    fn test_entity_line_closed_shell() {
141        let e = StepEntity {
142            id: 2,
143            kind: StepEntityKind::ClosedShell,
144            attributes: vec![],
145        };
146        assert!(step_entity_line(&e).contains("CLOSED_SHELL"));
147    }
148
149    #[test]
150    fn test_validate_non_empty() {
151        let mut exp = new_step_solid_export("AP214", "X");
152        add_step_entity(&mut exp, StepEntityKind::ManifoldSolidBrep, vec![]);
153        assert!(validate_step_export(&exp));
154    }
155
156    #[test]
157    fn test_validate_empty_fails() {
158        let exp = new_step_solid_export("AP214", "X");
159        assert!(!validate_step_export(&exp));
160    }
161
162    #[test]
163    fn test_schema_stored() {
164        let exp = new_step_solid_export("AP203", "Y");
165        assert_eq!(exp.schema, "AP203");
166    }
167}