2026-06-19 14:33:22 +02:00
|
|
|
use std::{
|
|
|
|
|
collections::HashSet,
|
|
|
|
|
hash::Hash,
|
|
|
|
|
io::{Read, Write},
|
|
|
|
|
str::FromStr,
|
|
|
|
|
string::ToString,
|
|
|
|
|
};
|
2026-05-04 16:06:25 +02:00
|
|
|
|
2026-07-12 18:21:18 +02:00
|
|
|
use crate::serialization::{Error, Result, RmcSerialize};
|
2026-05-04 16:06:25 +02:00
|
|
|
|
2026-05-05 14:48:25 +02:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct StringSet<T: FromStr + ToString + Eq>(pub HashSet<T>)
|
2026-05-04 16:06:25 +02:00
|
|
|
where
|
|
|
|
|
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static;
|
|
|
|
|
|
|
|
|
|
impl<T: FromStr + ToString + Eq + Hash> PartialEq for StringSet<T>
|
|
|
|
|
where
|
|
|
|
|
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
|
|
|
|
|
{
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
self.0.iter().eq(&other.0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: FromStr + ToString + Eq + Hash> ToString for StringSet<T>
|
|
|
|
|
where
|
|
|
|
|
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
|
|
|
|
|
{
|
|
|
|
|
fn to_string(&self) -> String {
|
|
|
|
|
self.0
|
|
|
|
|
.iter()
|
|
|
|
|
.map(ToString::to_string)
|
|
|
|
|
.reduce(|a, b| format!("{}|{}", a, b))
|
|
|
|
|
.unwrap_or(String::new())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: FromStr + ToString + Eq + Hash> FromStr for StringSet<T>
|
|
|
|
|
where
|
|
|
|
|
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
|
|
|
|
|
{
|
|
|
|
|
type Err = Box<dyn std::error::Error + Send + Sync>;
|
|
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2026-05-05 18:03:00 +02:00
|
|
|
Ok(Self(
|
|
|
|
|
s.split("|")
|
|
|
|
|
.filter(|v| !v.is_empty())
|
|
|
|
|
.map(T::from_str)
|
|
|
|
|
.try_fold(
|
|
|
|
|
HashSet::new(),
|
|
|
|
|
|mut a, b| -> Result<HashSet<T>, Self::Err> {
|
|
|
|
|
a.insert(b.map_err(Box::new)?);
|
|
|
|
|
Ok(a)
|
|
|
|
|
},
|
|
|
|
|
)?,
|
|
|
|
|
))
|
2026-05-04 16:06:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: FromStr + ToString + Eq + Hash> RmcSerialize for StringSet<T>
|
|
|
|
|
where
|
|
|
|
|
<T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
|
|
|
|
|
{
|
2026-07-12 18:21:18 +02:00
|
|
|
fn deserialize(reader: &mut (impl Read + ?Sized)) -> Result<Self>
|
2026-05-04 16:06:25 +02:00
|
|
|
where
|
|
|
|
|
Self: Sized,
|
|
|
|
|
{
|
2026-07-12 18:21:18 +02:00
|
|
|
Self::from_str(&String::deserialize(reader)?).map_err(Error::Other)
|
2026-05-04 16:06:25 +02:00
|
|
|
}
|
2026-07-12 18:21:18 +02:00
|
|
|
fn serialize(&self, writer: &mut (impl Write + ?Sized)) -> Result<()> {
|
2026-05-04 16:06:25 +02:00
|
|
|
self.to_string().serialize(writer)
|
|
|
|
|
}
|
2026-07-12 18:21:18 +02:00
|
|
|
fn serialize_write_size(&self) -> Result<u32> {
|
2026-05-04 16:06:25 +02:00
|
|
|
self.to_string().serialize_write_size()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
2026-07-12 18:21:18 +02:00
|
|
|
use crate::string_set::StringSet;
|
2026-05-04 16:06:25 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test() {
|
|
|
|
|
let str_val = "0|100|200|10|110|210|20|120|220|30|130|230";
|
|
|
|
|
let set: StringSet<u32> = StringSet::from_str(str_val).unwrap();
|
|
|
|
|
let string_2 = set.to_string();
|
|
|
|
|
let reset: StringSet<u32> = StringSet::from_str(&string_2).unwrap();
|
|
|
|
|
|
|
|
|
|
for val in &set.0 {
|
|
|
|
|
if !reset.0.contains(&val) {
|
|
|
|
|
panic!("sets arent equivalent");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-05 18:03:00 +02:00
|
|
|
|
|
|
|
|
let _: StringSet<u32> = StringSet::from_str("").unwrap();
|
|
|
|
|
|
|
|
|
|
let _: StringSet<u32> = StringSet::from_str("10").unwrap();
|
2026-05-04 16:06:25 +02:00
|
|
|
}
|
|
|
|
|
}
|