use std::fmt;
use cxx::UniquePtr;
#[cfg(feature = "json")]
use crate::bridge::style_value;
use crate::bridge::{ffi, layers};
#[cfg(feature = "json")]
use crate::style::{value::build_style_value, StyleError};
use crate::style::{CircleLayer, FillLayer, LineLayer, SymbolLayer};
pub struct OpaqueLayer {
layer_id: String,
layer_type: String,
layer: UniquePtr<ffi::CxxLayer>,
}
impl OpaqueLayer {
#[must_use]
pub fn layer_id(&self) -> &str {
&self.layer_id
}
#[must_use]
pub fn type_str(&self) -> &str {
&self.layer_type
}
pub(crate) fn into_inner(self) -> UniquePtr<ffi::CxxLayer> {
self.layer
}
}
impl fmt::Debug for OpaqueLayer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OpaqueLayer")
.field("layer_id", &self.layer_id)
.field("type", &self.layer_type)
.finish_non_exhaustive()
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum AnyLayer {
Circle(CircleLayer),
Fill(FillLayer),
Line(LineLayer),
Symbol(SymbolLayer),
Opaque(OpaqueLayer),
}
impl AnyLayer {
pub(crate) fn from_layer_ptr(layer: UniquePtr<ffi::CxxLayer>) -> Option<Self> {
if layer.is_null() {
return None;
}
let layer_id = layers::layer_id(&layer);
let layer_type = layers::layer_type(&layer);
Some(match layer_type.as_str() {
"circle" => {
Self::Circle(CircleLayer::from_ffi_parts(layer_id, layers::try_into_circle(layer)))
}
"fill" => Self::Fill(FillLayer::from_ffi_parts(layer_id, layers::try_into_fill(layer))),
"line" => Self::Line(LineLayer::from_ffi_parts(layer_id, layers::try_into_line(layer))),
"symbol" => {
Self::Symbol(SymbolLayer::from_ffi_parts(layer_id, layers::try_into_symbol(layer)))
}
_ => Self::Opaque(OpaqueLayer { layer_id, layer_type, layer }),
})
}
#[cfg(feature = "json")]
pub fn from_json_str(json: &str) -> Result<Self, StyleError> {
let value: serde_json::Value = serde_json::from_str(json)?;
Self::from_json_value(&value)
}
#[cfg(feature = "json")]
pub fn from_json_value(value: &serde_json::Value) -> Result<Self, StyleError> {
let style_value = build_style_value(value)?;
let mut error_message = String::new();
let layer = style_value::layer_from_value(&style_value, &mut error_message);
if layer.is_null() {
return Err(StyleError::Native(error_message));
}
Self::from_layer_ptr(layer).ok_or(StyleError::Native(error_message))
}
#[must_use]
pub fn layer_id(&self) -> &str {
match self {
Self::Circle(l) => l.layer_id(),
Self::Fill(l) => l.layer_id(),
Self::Line(l) => l.layer_id(),
Self::Symbol(l) => l.layer_id(),
Self::Opaque(l) => l.layer_id(),
}
}
#[must_use]
pub fn type_str(&self) -> &str {
match self {
Self::Circle(_) => "circle",
Self::Fill(_) => "fill",
Self::Line(_) => "line",
Self::Symbol(_) => "symbol",
Self::Opaque(l) => l.type_str(),
}
}
pub(crate) fn into_layer_ptr(self) -> UniquePtr<ffi::CxxLayer> {
match self {
Self::Circle(l) => layers::circle_into_layer(l.into_inner()),
Self::Fill(l) => layers::fill_into_layer(l.into_inner()),
Self::Line(l) => layers::line_into_layer(l.into_inner()),
Self::Symbol(l) => layers::symbol_into_layer(l.into_inner()),
Self::Opaque(l) => l.into_inner(),
}
}
}