1use std::borrow::Cow;
2use std::fmt::{Debug, Display};
3use std::ops::{Index, IndexMut, Range};
4use std::slice::SliceIndex;
5
6#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
7pub struct IoNet {
8 pub index: u32,
9}
10
11impl IoNet {
12 pub const FLOATING: IoNet = IoNet { index: u32::MAX };
13
14 pub fn is_floating(self) -> bool {
15 self.index == u32::MAX
16 }
17}
18
19impl Debug for IoNet {
20 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
21 match self {
22 IoNet { index: u32::MAX } => write!(f, "IoNet::FLOATING"),
23 IoNet { index } => write!(f, "IoNet {{ index: {index} }}"),
24 }
25 }
26}
27
28impl Display for IoNet {
29 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
30 match self {
31 IoNet { index: u32::MAX } => write!(f, "#_"),
32 IoNet { index } => write!(f, "#{index}"),
33 }
34 }
35}
36
37#[derive(Clone, Debug, Eq, PartialEq, Hash)]
38pub struct IoValue {
39 nets: Vec<IoNet>,
40}
41
42impl IoValue {
43 pub const fn new() -> Self {
44 IoValue { nets: vec![] }
45 }
46
47 pub fn from_range(range: Range<u32>) -> Self {
48 Self { nets: range.map(|i| IoNet { index: i }).collect() }
49 }
50
51 pub fn floating(width: usize) -> Self {
52 Self { nets: vec![IoNet::FLOATING; width] }
53 }
54
55 pub fn len(&self) -> usize {
56 self.nets.len()
57 }
58
59 pub fn is_empty(&self) -> bool {
60 self.nets.is_empty()
61 }
62
63 pub fn iter(&self) -> impl DoubleEndedIterator<Item = IoNet> + ExactSizeIterator + '_ {
64 self.nets.iter().copied()
65 }
66
67 pub fn concat<'a>(&self, other: impl Into<Cow<'a, IoValue>>) -> Self {
68 Self::from_iter(self.iter().chain(other.into().iter()))
69 }
70
71 pub fn slice(&self, range: impl std::ops::RangeBounds<usize>) -> IoValue {
72 IoValue::from_iter(self[(range.start_bound().cloned(), range.end_bound().cloned())].iter().copied())
73 }
74}
75
76impl From<IoNet> for IoValue {
77 fn from(value: IoNet) -> Self {
78 Self { nets: vec![value] }
79 }
80}
81
82impl From<IoNet> for Cow<'_, IoValue> {
83 fn from(value: IoNet) -> Self {
84 Cow::Owned(IoValue::from(value))
85 }
86}
87
88impl FromIterator<IoNet> for IoValue {
89 fn from_iter<T: IntoIterator<Item = IoNet>>(iter: T) -> Self {
90 IoValue { nets: iter.into_iter().collect() }
91 }
92}
93
94impl<I: SliceIndex<[IoNet]>> Index<I> for IoValue {
95 type Output = I::Output;
96
97 fn index(&self, index: I) -> &Self::Output {
98 &self.nets[index]
99 }
100}
101
102impl<I: SliceIndex<[IoNet]>> IndexMut<I> for IoValue {
103 fn index_mut(&mut self, index: I) -> &mut Self::Output {
104 &mut self.nets[index]
105 }
106}
107
108impl IntoIterator for &IoValue {
109 type Item = IoNet;
110 type IntoIter = std::vec::IntoIter<IoNet>;
111
112 fn into_iter(self) -> Self::IntoIter {
113 self.nets.clone().into_iter()
114 }
115}
116
117impl IntoIterator for IoValue {
118 type Item = IoNet;
119 type IntoIter = std::vec::IntoIter<IoNet>;
120
121 fn into_iter(self) -> Self::IntoIter {
122 self.nets.into_iter()
123 }
124}
125
126impl Extend<IoNet> for IoValue {
127 fn extend<T: IntoIterator<Item = IoNet>>(&mut self, iter: T) {
128 self.nets.extend(iter);
129 }
130}