use core::ops::Deref;
use iceoryx2_bb_container::vector::*;
use iceoryx2_bb_derive_macros::ZeroCopySend;
use iceoryx2_bb_elementary::CallbackProgression;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use iceoryx2_log::fail;
use serde::{Deserialize, Serialize};
use crate::constants::MAX_ATTRIBUTES;
mod key {
use core::hash::Hash;
use core::hash::Hasher;
use alloc::string::String;
use iceoryx2_bb_container::semantic_string;
use iceoryx2_bb_container::semantic_string::SemanticString;
use iceoryx2_bb_derive_macros::ZeroCopySend;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use crate::constants::MAX_ATTRIBUTE_KEY_LENGTH;
semantic_string! {
name: FixedString,
capacity: MAX_ATTRIBUTE_KEY_LENGTH,
invalid_content: |string: &[u8]| {
string.is_empty()
},
invalid_characters: |_string: &[u8]| {
false
},
normalize: |this: &FixedString| {
*this
}
}
}
pub type AttributeKey = key::FixedString;
mod value {
use core::hash::Hash;
use core::hash::Hasher;
use alloc::string::String;
use iceoryx2_bb_container::semantic_string;
use iceoryx2_bb_container::semantic_string::SemanticString;
use iceoryx2_bb_derive_macros::ZeroCopySend;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use crate::constants::MAX_ATTRIBUTE_VALUE_LENGTH;
semantic_string! {
name: FixedString,
capacity: MAX_ATTRIBUTE_VALUE_LENGTH,
invalid_content: |string: &[u8]| {
string.is_empty()
},
invalid_characters: |_string: &[u8]| {
false
},
normalize: |this: &FixedString| {
*this
}
}
}
pub type AttributeValue = value::FixedString;
type KeyStorage = StaticVec<AttributeKey, MAX_ATTRIBUTES>;
type AttributeStorage = StaticVec<Attribute, MAX_ATTRIBUTES>;
#[allow(clippy::large_enum_variant)] #[derive(Debug, Eq, PartialEq, Clone)]
pub enum AttributeVerificationError {
NonExistingKey(AttributeKey),
IncompatibleAttribute((AttributeKey, AttributeValue)),
}
impl core::fmt::Display for AttributeVerificationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
AttributeVerificationError::NonExistingKey(key) => {
write!(f, "AttributeVerificationError::NonExistingKey({:?})", key)
}
AttributeVerificationError::IncompatibleAttribute((key, value)) => {
write!(
f,
"AttributeVerificationError::IncompatibleAttribute(({:?}, {:?}))",
key, value
)
}
}
}
}
impl core::error::Error for AttributeVerificationError {}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum AttributeDefinitionError {
ExceedsMaxSupportedAttributes,
}
impl core::fmt::Display for AttributeDefinitionError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "AttributeDefinitionError::{self:?}")
}
}
impl core::error::Error for AttributeDefinitionError {}
#[derive(Debug, Eq, PartialEq, Clone, PartialOrd, Ord, ZeroCopySend, Serialize, Deserialize)]
#[repr(C)]
pub struct Attribute {
key: AttributeKey,
value: AttributeValue,
}
impl Attribute {
pub fn new(key: &AttributeKey, value: &AttributeValue) -> Self {
Self {
key: *key,
value: *value,
}
}
pub fn key(&self) -> &AttributeKey {
&self.key
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
}
#[derive(Debug, Clone)]
pub struct AttributeSpecifier(pub(crate) AttributeSet);
impl Default for AttributeSpecifier {
fn default() -> Self {
Self(AttributeSet::new())
}
}
impl AttributeSpecifier {
pub fn new() -> Self {
Self::default()
}
pub fn define(
mut self,
key: &AttributeKey,
value: &AttributeValue,
) -> Result<Self, AttributeDefinitionError> {
self.0.add(key, value)?;
Ok(self)
}
pub fn attributes(&self) -> &AttributeSet {
&self.0
}
}
#[derive(Debug, Clone)]
pub struct AttributeVerifier {
required_attributes: AttributeSet,
required_keys: KeyStorage,
}
impl Default for AttributeVerifier {
fn default() -> Self {
Self {
required_attributes: AttributeSet::new(),
required_keys: KeyStorage::new(),
}
}
}
impl AttributeVerifier {
pub fn new() -> Self {
Self::default()
}
pub fn require(
mut self,
key: &AttributeKey,
value: &AttributeValue,
) -> Result<Self, AttributeDefinitionError> {
if AttributeSet::capacity() <= self.required_attributes.len() + self.required_keys.len()
|| self.required_attributes.add(key, value).is_err()
{
fail!(from self, with AttributeDefinitionError::ExceedsMaxSupportedAttributes,
"Unable to require the attribute {}={} since it would exceed the maximum number of supported attributes of {}.",
key, value, MAX_ATTRIBUTES);
}
Ok(self)
}
pub fn require_key(mut self, key: &AttributeKey) -> Result<Self, AttributeDefinitionError> {
if AttributeSet::capacity() <= self.required_attributes.len() + self.required_keys.len()
|| self.required_keys.push(*key).is_err()
{
fail!(from self, with AttributeDefinitionError::ExceedsMaxSupportedAttributes,
"Unable to require the key {} since it would exceed the maximum number of supported attributes of {}.",
key, MAX_ATTRIBUTES);
}
Ok(self)
}
pub fn required_attributes(&self) -> &AttributeSet {
&self.required_attributes
}
pub fn required_keys(&self) -> &[AttributeKey] {
self.required_keys.as_slice()
}
#[allow(clippy::result_large_err)] pub fn verify_requirements(
&self,
rhs: &AttributeSet,
) -> Result<(), AttributeVerificationError> {
let msg = "The verification of attribute requirements failed";
for attribute in self.required_attributes().iter() {
let key = attribute.key();
let value = attribute.value();
let attribute_present = rhs
.iter()
.any(|attr| attr.key() == key && attr.value() == value);
if !attribute_present {
fail!(from self,
with AttributeVerificationError::IncompatibleAttribute((*key, *value)),
"{msg} due to the incompatible attribute {} = {}.",
key, value);
}
}
for key in self.required_keys() {
let key_exists = rhs.iter().any(|attr| attr.key == *key);
if !key_exists {
fail!(from self,
with AttributeVerificationError::NonExistingKey(*key),
"{msg} due to a missing key {}.", key);
}
}
Ok(())
}
}
#[derive(Debug, Eq, PartialEq, Clone, ZeroCopySend, Serialize, Deserialize)]
#[repr(C)]
pub struct AttributeSet(AttributeStorage);
impl Deref for AttributeSet {
type Target = [Attribute];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl AttributeSet {
pub(crate) fn new() -> Self {
Self(AttributeStorage::new())
}
pub(crate) fn add(
&mut self,
key: &AttributeKey,
value: &AttributeValue,
) -> Result<(), AttributeDefinitionError> {
fail!(from self,
when self.0.push(Attribute::new(key, value)),
with AttributeDefinitionError::ExceedsMaxSupportedAttributes,
"Failed to add attribute {}={} since this would exceed the max number of supported attributes {}.",
key, value, self.0.capacity());
self.0.sort();
Ok(())
}
pub fn number_of_attributes(&self) -> usize {
self.iter().len()
}
pub const fn capacity() -> usize {
AttributeStorage::capacity()
}
pub fn number_of_key_values(&self, key: &AttributeKey) -> usize {
self.iter().filter(|element| element.key() == key).count()
}
pub fn key_value(&self, key: &AttributeKey, idx: usize) -> Option<&AttributeValue> {
self.0
.iter()
.filter(|attr| attr.key() == key)
.map(|attr| attr.value())
.nth(idx)
}
pub fn iter_key_values<F: FnMut(&AttributeValue) -> CallbackProgression>(
&self,
key: &AttributeKey,
mut callback: F,
) {
for element in self.iter() {
if element.key() != key {
continue;
}
if callback(element.value()) == CallbackProgression::Stop {
break;
}
}
}
}