use alloc::format;
use iceoryx2_bb_container::{semantic_string::SemanticStringError, string::*};
use iceoryx2_bb_derive_macros::{PlacementDefault, ZeroCopySend};
use iceoryx2_bb_elementary_traits::placement_default::PlacementDefault;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use iceoryx2_log::fail;
use crate::constants::MAX_PORT_NAME_LENGTH;
use serde::{Deserialize, Serialize, de::Visitor};
type PortNameString = StaticString<MAX_PORT_NAME_LENGTH>;
#[derive(
PlacementDefault, ZeroCopySend, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
#[repr(C)]
pub struct PortName {
value: PortNameString,
}
impl PortName {
pub fn new(name: &str) -> Result<Self, SemanticStringError> {
Ok(Self {
value: fail!(from "PortName::new()",
when PortNameString::try_from(name),
"The string \"{}\" is not a valid port name.",
name),
})
}
pub fn new_empty() -> Self {
Self {
value: PortNameString::default(),
}
}
pub fn as_str(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.value.as_bytes()) }
}
pub fn max_len() -> usize {
PortNameString::capacity()
}
}
impl core::fmt::Display for PortName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.value)
}
}
impl TryInto<PortName> for &str {
type Error = SemanticStringError;
fn try_into(self) -> Result<PortName, Self::Error> {
PortName::new(self)
}
}
impl PartialEq<&str> for PortName {
fn eq(&self, other: &&str) -> bool {
*self.as_str() == **other
}
}
impl PartialEq<&str> for &PortName {
fn eq(&self, other: &&str) -> bool {
*self.as_str() == **other
}
}
impl core::ops::Deref for PortName {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
struct PortNameVisitor;
impl Visitor<'_> for PortNameVisitor {
type Value = PortName;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a string containing the service name")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match PortName::new(v) {
Ok(v) => Ok(v),
Err(v) => Err(E::custom(format!("invalid port name provided {v:?}."))),
}
}
}
impl<'de> Deserialize<'de> for PortName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(PortNameVisitor)
}
}
impl Serialize for PortName {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(core::str::from_utf8(self.as_bytes()).unwrap())
}
}