rust-nex/rnex-rmc/src/string_set.rs

100 lines
2.7 KiB
Rust
Raw Normal View History

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
}
}