1use crate::{reader, writer, XmlProfile};
4use ifc_model::{Codec, Model, ModelError};
5
6#[derive(Default)]
13pub struct XmlCodec {
14 profile: Option<XmlProfile>,
15 #[cfg(feature = "schema")]
16 schema: Option<std::sync::Arc<ifc_schema::Schema>>,
17}
18
19impl XmlCodec {
20 #[must_use]
22 pub const fn strict(profile: XmlProfile) -> Self {
23 Self {
24 profile: Some(profile),
25 #[cfg(feature = "schema")]
26 schema: None,
27 }
28 }
29
30 #[must_use]
32 pub const fn profile(&self) -> Option<XmlProfile> {
33 self.profile
34 }
35
36 #[cfg(feature = "schema")]
38 #[must_use]
39 pub fn with_schema(schema: std::sync::Arc<ifc_schema::Schema>) -> Self {
40 Self {
41 profile: None,
42 schema: Some(schema),
43 }
44 }
45
46 #[cfg(feature = "schema")]
48 #[must_use]
49 pub fn with_schema_and_profile(
50 schema: std::sync::Arc<ifc_schema::Schema>,
51 profile: XmlProfile,
52 ) -> Self {
53 Self {
54 profile: Some(profile),
55 schema: Some(schema),
56 }
57 }
58
59 #[cfg(feature = "schema")]
61 #[must_use]
62 pub fn schema(&self) -> Option<&ifc_schema::Schema> {
63 self.schema.as_deref()
64 }
65}
66
67impl Codec for XmlCodec {
68 fn name(&self) -> &'static str {
69 "ifcXML"
70 }
71
72 fn extensions(&self) -> &'static [&'static str] {
73 &["ifcxml", "xml"]
74 }
75
76 fn detect(&self, bytes: &[u8]) -> bool {
77 reader::looks_like_xml(bytes)
78 }
79
80 fn read_bytes(&self, bytes: &[u8]) -> Result<Model, ModelError> {
81 reader::read(self, bytes).map_err(|error| ModelError::Syntax {
82 offset: 0,
83 detail: error.to_string(),
84 })
85 }
86
87 fn write(&self, model: &Model, out: &mut dyn std::io::Write) -> Result<(), ModelError> {
88 let bytes =
89 writer::write(self, model).map_err(|error| ModelError::Write(error.to_string()))?;
90 out.write_all(&bytes)
91 .map_err(|error| ModelError::Io(error.to_string()))
92 }
93}