blob: 4fcd242e696b40651069d20a4a2e25da3612e299 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::node_path::NodePath,
serde::{
de::{self, Deserializer, Visitor},
Deserialize, Serialize, Serializer,
},
std::{error::Error, fmt},
};
/// Serialize `NodePath` into a path-like slash-separated a string
/// representation of the underlying child monikers.
//
/// Example: "/alpha:2/beta:0/gamma:1".
impl Serialize for NodePath {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let path = format!("/{}", self.as_vec().join("/"));
serializer.serialize_str(&path)
}
}
struct NodePathVisitor;
/// Deserialize `NodePath` from path-like slash-separated string of child
/// monikers.
impl<'de> Visitor<'de> for NodePathVisitor {
type Value = NodePath;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("A component tree node path")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(NodePath::new(
value
.split("/")
.filter_map(
|component| {
if component.is_empty() {
None
} else {
Some(component.into())
}
},
)
.collect(),
))
}
}
impl<'de> Deserialize<'de> for NodePath {
fn deserialize<D>(deserializer: D) -> Result<NodePath, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(NodePathVisitor)
}
}
/// Error for use with serialization: Stores both structured error and message,
/// and assesses equality using structured error.
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct ErrorWithMessage<E: Clone + Error + Serialize> {
pub error: E,
#[serde(default)]
pub message: String,
}
impl<E: Clone + Error + PartialEq + Serialize> PartialEq<ErrorWithMessage<E>>
for ErrorWithMessage<E>
{
fn eq(&self, other: &Self) -> bool {
// Ignore `message` when comparing.
self.error == other.error
}
}
impl<'de, E> From<E> for ErrorWithMessage<E>
where
E: Clone + Deserialize<'de> + Error + Serialize,
{
fn from(error: E) -> Self {
Self::from(&error)
}
}
impl<'de, E> From<&E> for ErrorWithMessage<E>
where
E: Clone + Deserialize<'de> + Error + Serialize,
{
fn from(error: &E) -> Self {
let message = error.to_string();
let error = error.clone();
Self { error, message }
}
}