ecitygml-io 0.0.2-alpha.5

IO operations for processing CityGML data.
Documentation
use crate::Error;

use egml::io::util::{Formatting, XmlElementSpans, XmlNodeContent, XmlNodeParts, serialize_inner};

use crate::gml::codec::appearance::abstract_surface_data::{
    deserialize_abstract_surface_data, serialize_abstract_surface_data,
};
use crate::gml::codec::appearance::basic_types::GmlColorPlusOpacity;
use crate::gml::codec::appearance::enums::{GmlTextureType, GmlWrapMode};
use crate::gml::util::CombinedCityGmlElement;
use ecitygml_core::model::appearance::{
    AbstractTexture, AsAbstractSurfaceData, AsAbstractTexture, AsAbstractTextureMut,
};
use quick_xml::de;
use serde::{Deserialize, Serialize};

pub fn deserialize_abstract_texture(
    xml_document: &[u8],
    spans: &XmlElementSpans<CombinedCityGmlElement>,
) -> Result<AbstractTexture, Error> {
    let (abstract_surface_data_result, gml_result) = rayon::join(
        || deserialize_abstract_surface_data(xml_document, spans),
        || de::from_reader::<_, GmlAbstractTexture>(xml_document).map_err(Error::from),
    );
    let abstract_feature = abstract_surface_data_result?;
    let parsed = gml_result?;

    let mut abstract_texture = AbstractTexture::from_abstract_surface_data(abstract_feature);
    abstract_texture.set_image_uri(parsed.image_uri);
    abstract_texture.set_texture_type(parsed.texture_type.map(Into::into));
    abstract_texture.set_wrap_mode(parsed.wrap_mode.map(Into::into));
    abstract_texture.set_border_color(parsed.border_color.map(TryInto::try_into).transpose()?);

    Ok(abstract_texture)
}

pub fn serialize_abstract_texture(
    abstract_texture: &AbstractTexture,
    formatting: Formatting,
) -> Result<XmlNodeParts, Error> {
    let mut xml_node_parts =
        serialize_abstract_surface_data(abstract_texture.abstract_surface_data(), formatting)?;

    if let Some(raw) = serialize_inner(GmlAbstractTexture::from(abstract_texture), formatting)? {
        xml_node_parts.content.push(XmlNodeContent::Raw(raw));
    }

    Ok(xml_node_parts)
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct GmlAbstractTexture {
    #[serde(
        rename(serialize = "app:imageURI", deserialize = "imageURI"),
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub image_uri: Option<String>,

    #[serde(
        rename(serialize = "app:textureType", deserialize = "textureType"),
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub texture_type: Option<GmlTextureType>,

    #[serde(
        rename(serialize = "app:wrapMode", deserialize = "wrapMode"),
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub wrap_mode: Option<GmlWrapMode>,

    #[serde(
        rename(serialize = "app:borderColor", deserialize = "borderColor"),
        default,
        skip_serializing_if = "Option::is_none"
    )]
    pub border_color: Option<GmlColorPlusOpacity>,
}

impl From<&AbstractTexture> for GmlAbstractTexture {
    fn from(item: &AbstractTexture) -> Self {
        Self {
            image_uri: item.image_uri().map(Into::into),
            texture_type: item.texture_type().map(Into::into),
            wrap_mode: item.wrap_mode().map(Into::into),
            border_color: item.border_color().map(Into::into),
        }
    }
}