use std::{
collections::HashSet,
convert::TryFrom,
fmt,
io::{self, Read, Write},
};
use crate::{
io::{LenBm, ReadFrom, TooLongError, WriteTo},
var_type::{VarInt, VarIntList},
};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct StreamNumber(u32);
impl fmt::Display for StreamNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl StreamNumber {
pub fn new(value: u32) -> Self {
Self(value)
}
pub fn as_u32(self) -> u32 {
self.0
}
}
impl From<u32> for StreamNumber {
fn from(value: u32) -> Self {
Self(value)
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ConvertStreamNumberError {
TooLarge { max: u64, value: u64 },
}
impl fmt::Display for ConvertStreamNumberError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TooLarge { max, value } => {
write!(f, "stream number must be <={}, but {}", max, value)
}
}
}
}
impl std::error::Error for ConvertStreamNumberError {}
impl TryFrom<VarInt> for StreamNumber {
type Error = ConvertStreamNumberError;
fn try_from(vi: VarInt) -> Result<Self, <Self as TryFrom<VarInt>>::Error> {
if vi.as_u64() <= 0xffff_ffff {
Ok((vi.as_u64() as u32).into())
} else {
Err(Self::Error::TooLarge {
max: 0xffff_ffff,
value: vi.as_u64(),
})
}
}
}
impl From<StreamNumber> for VarInt {
fn from(sn: StreamNumber) -> Self {
(sn.as_u32() as u64).into()
}
}
impl WriteTo for StreamNumber {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
let v = VarInt::from(*self);
v.write_to(w)
}
}
impl ReadFrom for StreamNumber {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
let v = VarInt::read_from(r)?;
match Self::try_from(v) {
Ok(sn) => Ok(sn),
Err(err) => Err(io::Error::new(io::ErrorKind::Other, err)),
}
}
}
impl LenBm for StreamNumber {
fn len_bm(&self) -> usize {
let v = VarInt::from(*self);
v.len_bm()
}
}
#[test]
fn test_stream_number_write_to() {
let test: StreamNumber = 0xcd_u32.into();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [0xcd];
assert_eq!(bytes, expected);
let test: StreamNumber = 0xfe_u32.into();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [0xfd, 0x00, 0xfe];
assert_eq!(bytes, expected);
let test: StreamNumber = 0xcdef_u32.into();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [0xfd, 0xcd, 0xef];
assert_eq!(bytes, expected);
let test: StreamNumber = 0x89ab_cdef_u32.into();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [0xfe, 0x89, 0xab, 0xcd, 0xef];
assert_eq!(bytes, expected);
}
#[test]
fn test_stream_number_read_from() {
use std::io::Cursor;
let mut bytes = Cursor::new([0xcd]);
let test = StreamNumber::read_from(&mut bytes).unwrap();
let expected: StreamNumber = 0xcd_u32.into();
assert_eq!(test, expected);
let mut bytes = Cursor::new([0xfd, 0x00, 0xfe]);
let test = StreamNumber::read_from(&mut bytes).unwrap();
let expected: StreamNumber = 0xfe_u32.into();
assert_eq!(test, expected);
let mut bytes = Cursor::new([0xfe, 0x89, 0xab, 0xcd, 0xef]);
let test = StreamNumber::read_from(&mut bytes).unwrap();
let expected: StreamNumber = 0x89ab_cdef_u32.into();
assert_eq!(test, expected);
}
#[test]
#[should_panic]
fn test_stream_number_error_u16() {
use std::io::Cursor;
let mut bytes = Cursor::new([0xfd, 0x00, 0xab]);
let test = StreamNumber::read_from(&mut bytes).unwrap();
let expected: StreamNumber = 0x00ab_u32.into();
assert_eq!(test, expected);
}
#[test]
#[should_panic]
fn test_stream_number_error_u32() {
use std::io::Cursor;
let mut bytes = Cursor::new([0xfe, 0x00, 0x00, 0xcd, 0xef]);
let test = StreamNumber::read_from(&mut bytes).unwrap();
let expected: StreamNumber = 0x0000_cdef_u32.into();
assert_eq!(test, expected);
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct StreamNumbers(Vec<StreamNumber>);
impl AsRef<[StreamNumber]> for StreamNumbers {
fn as_ref(&self) -> &[StreamNumber] {
&self.0
}
}
impl StreamNumbers {
pub fn new(list: Vec<StreamNumber>) -> Self {
Self(list)
}
pub fn intersection(&self, other: &Self) -> Self {
let a: HashSet<StreamNumber> = self.0.iter().cloned().collect();
let b: HashSet<StreamNumber> = other.0.iter().cloned().collect();
let c = a.intersection(&b);
let mut v: Vec<StreamNumber> = c.cloned().collect();
v.sort_unstable();
v.into()
}
}
impl From<Vec<StreamNumber>> for StreamNumbers {
fn from(values: Vec<StreamNumber>) -> Self {
Self(values)
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ConvertStreamNumbersError {
InvalidStreamNumber(ConvertStreamNumberError),
}
impl fmt::Display for ConvertStreamNumbersError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidStreamNumber(err) => err.fmt(f),
}
}
}
impl std::error::Error for ConvertStreamNumbersError {}
impl TryFrom<VarIntList> for StreamNumbers {
type Error = ConvertStreamNumbersError;
fn try_from(vil: VarIntList) -> Result<Self, <Self as TryFrom<VarIntList>>::Error> {
let mut vec: Vec<StreamNumber> = Vec::with_capacity(vil.as_ref().len());
for vi in vil.as_ref() {
match StreamNumber::try_from(*vi) {
Ok(sn) => {
vec.push(sn);
}
Err(err) => return Err(Self::Error::InvalidStreamNumber(err)),
}
}
Ok(vec.into())
}
}
impl From<StreamNumbers> for VarIntList {
fn from(sns: StreamNumbers) -> Self {
let mut vec: Vec<VarInt> = Vec::with_capacity(sns.as_ref().len());
for sn in sns.as_ref() {
vec.push((sn.as_u32() as u64).into());
}
vec.into()
}
}
impl WriteTo for StreamNumbers {
fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
VarInt::from(self.0.len() as u64).write_to(w)?;
for value in &self.0 {
value.write_to(w)?
}
Ok(())
}
}
impl ReadFrom for StreamNumbers {
fn read_from(r: &mut dyn Read) -> io::Result<Self>
where
Self: Sized,
{
const MAX_COUNT: usize = 160_000;
let length = VarInt::read_from(r)?;
if length.as_u64() > MAX_COUNT as u64 {
return Err(io::Error::new(
io::ErrorKind::Other,
TooLongError::new(MAX_COUNT, length.as_u64() as usize),
));
}
let mut values = Vec::with_capacity(length.as_u64() as usize);
for _ in 0..length.as_u64() {
values.push(StreamNumber::read_from(r)?);
}
Ok(Self(values))
}
}
#[test]
fn test_stream_numbers_write_to() {
let test: StreamNumbers = vec![0xcd_u32.into(), 0xfe_u32.into(), 0xcdef_u32.into()].into();
let mut bytes = Vec::new();
test.write_to(&mut bytes).unwrap();
let expected = [0x03, 0xcd, 0xfd, 0x00, 0xfe, 0xfd, 0xcd, 0xef];
assert_eq!(bytes, expected);
}
#[test]
fn test_stream_numbers_read_from() {
use std::io::Cursor;
let mut bytes = Cursor::new([0x03, 0xcd, 0xfd, 0x00, 0xfe, 0xfd, 0xcd, 0xef]);
let test = StreamNumbers::read_from(&mut bytes).unwrap();
let expected: StreamNumbers = vec![0xcd_u32.into(), 0xfe_u32.into(), 0xcdef_u32.into()].into();
assert_eq!(test, expected);
}