1use arcstr::ArcStr;
4use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
5
6use crate::SignalId;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
11pub struct NamedSlice {
12 signal: ArcStr,
13 range: Option<SliceRange>,
14}
15
16#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
18pub struct NamedSliceOne {
19 signal: ArcStr,
20 index: Option<usize>,
21}
22
23#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
25pub struct Slice {
26 signal: SignalId,
27 range: Option<SliceRange>,
28}
29
30#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
32pub struct SliceOne {
33 signal: SignalId,
34 index: Option<usize>,
35}
36
37#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
39pub struct SliceRange {
40 pub(crate) start: usize,
41 pub(crate) end: usize,
42}
43
44impl From<Range<usize>> for SliceRange {
45 fn from(value: Range<usize>) -> Self {
46 Self {
47 start: value.start,
48 end: value.end,
49 }
50 }
51}
52
53impl SliceRange {
54 #[inline]
56 pub fn new(start: usize, end: usize) -> Self {
57 assert!(end > start);
58 Self { start, end }
59 }
60
61 pub(crate) fn from_index(start: usize) -> Self {
62 Self::new(start, start + 1)
63 }
64
65 #[inline]
66 pub(crate) fn with_width(end: usize) -> Self {
67 assert!(end > 0);
68 Self { start: 0, end }
69 }
70
71 #[inline]
73 pub const fn width(&self) -> usize {
74 self.end - self.start
75 }
76
77 #[inline]
79 pub const fn start(&self) -> usize {
80 self.start
81 }
82
83 #[inline]
85 pub const fn end(&self) -> usize {
86 self.end
87 }
88
89 #[inline]
91 pub fn indices(&self) -> impl Iterator<Item = usize> {
92 self.start..self.end
93 }
94
95 #[inline]
97 pub const fn contains(&self, idx: usize) -> bool {
98 idx >= self.start && idx < self.end
99 }
100}
101impl IntoIterator for SliceRange {
102 type Item = usize;
103 type IntoIter = std::ops::Range<usize>;
104 fn into_iter(self) -> Self::IntoIter {
105 self.start..self.end
106 }
107}
108
109impl NamedSlice {
110 #[inline]
112 pub fn new(signal: impl Into<ArcStr>) -> Self {
113 Self {
114 signal: signal.into(),
115 range: None,
116 }
117 }
118
119 #[inline]
121 pub fn with_range(signal: impl Into<ArcStr>, range: impl Into<SliceRange>) -> Self {
122 Self {
123 signal: signal.into(),
124 range: Some(range.into()),
125 }
126 }
127
128 #[inline]
132 pub fn range(&self) -> Option<SliceRange> {
133 self.range
134 }
135
136 #[inline]
140 pub fn width(&self) -> usize {
141 self.range.map(|x| x.width()).unwrap_or(1)
142 }
143
144 #[inline]
146 pub fn signal(&self) -> &ArcStr {
147 &self.signal
148 }
149
150 #[inline]
152 pub fn is_bus(&self) -> bool {
153 self.range.is_some()
154 }
155
156 #[inline]
157 fn assert_bus_index(&self) {
158 assert!(
159 self.is_bus(),
160 "attempted to index into a single-bit wire; only buses support indexing"
161 );
162 }
163
164 pub fn slice_one(self) -> Option<NamedSliceOne> {
168 NamedSliceOne::try_from(self).ok()
169 }
170}
171
172impl IndexOwned<usize> for NamedSlice {
173 type Output = NamedSliceOne;
174 fn index(&self, index: usize) -> Self::Output {
175 self.assert_bus_index();
176 NamedSliceOne::with_index(self.signal.clone(), self.range.unwrap().index(index))
177 }
178}
179
180impl IndexOwned<Range<usize>> for NamedSlice {
181 type Output = Self;
182 fn index(&self, index: Range<usize>) -> Self::Output {
183 self.assert_bus_index();
184 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
185 }
186}
187
188impl IndexOwned<RangeFrom<usize>> for NamedSlice {
189 type Output = Self;
190 fn index(&self, index: RangeFrom<usize>) -> Self::Output {
191 self.assert_bus_index();
192 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
193 }
194}
195
196impl IndexOwned<RangeFull> for NamedSlice {
197 type Output = Self;
198 fn index(&self, index: RangeFull) -> Self::Output {
199 self.assert_bus_index();
200 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
201 }
202}
203
204impl IndexOwned<RangeInclusive<usize>> for NamedSlice {
205 type Output = Self;
206 fn index(&self, index: RangeInclusive<usize>) -> Self::Output {
207 self.assert_bus_index();
208 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
209 }
210}
211
212impl IndexOwned<RangeTo<usize>> for NamedSlice {
213 type Output = Self;
214 fn index(&self, index: RangeTo<usize>) -> Self::Output {
215 self.assert_bus_index();
216 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
217 }
218}
219
220impl IndexOwned<RangeToInclusive<usize>> for NamedSlice {
221 type Output = Self;
222 fn index(&self, index: RangeToInclusive<usize>) -> Self::Output {
223 self.assert_bus_index();
224 Self::with_range(self.signal.clone(), self.range.unwrap().index(index))
225 }
226}
227
228impl TryFrom<NamedSlice> for NamedSliceOne {
229 type Error = SliceWidthNotOne;
230 fn try_from(value: NamedSlice) -> Result<Self, Self::Error> {
231 if value.width() == 1 {
232 Ok(Self {
233 signal: value.signal,
234 index: value.range.map(|s| s.start()),
235 })
236 } else {
237 Err(SliceWidthNotOne)
238 }
239 }
240}
241
242impl From<NamedSliceOne> for NamedSlice {
243 fn from(value: NamedSliceOne) -> Self {
244 let range = value.range();
245 Self {
246 signal: value.signal,
247 range,
248 }
249 }
250}
251
252impl NamedSliceOne {
253 #[inline]
255 pub fn new(signal: impl Into<ArcStr>) -> Self {
256 Self {
257 signal: signal.into(),
258 index: None,
259 }
260 }
261
262 pub fn with_index(signal: ArcStr, index: usize) -> Self {
264 Self {
265 signal,
266 index: Some(index),
267 }
268 }
269
270 #[inline]
274 pub fn range(&self) -> Option<SliceRange> {
275 self.index.map(SliceRange::from_index)
276 }
277
278 #[inline]
280 pub const fn width(&self) -> usize {
281 1
282 }
283
284 #[inline]
286 pub fn signal(&self) -> &ArcStr {
287 &self.signal
288 }
289
290 #[inline]
292 pub fn is_bus(&self) -> bool {
293 self.index.is_some()
294 }
295
296 #[inline]
298 pub fn index(&self) -> Option<usize> {
299 self.index
300 }
301}
302
303impl Slice {
304 #[inline]
305 pub(crate) fn new(signal: SignalId, range: Option<SliceRange>) -> Self {
306 Self { signal, range }
307 }
308
309 #[inline]
313 pub fn range(&self) -> Option<SliceRange> {
314 self.range
315 }
316
317 #[inline]
321 pub fn width(&self) -> usize {
322 self.range.map(|x| x.width()).unwrap_or(1)
323 }
324
325 #[inline]
327 pub fn signal(&self) -> SignalId {
328 self.signal
329 }
330
331 #[inline]
333 pub fn is_bus(&self) -> bool {
334 self.range.is_some()
335 }
336
337 #[inline]
338 fn assert_bus_index(&self) {
339 assert!(
340 self.is_bus(),
341 "attempted to index into a single-bit wire; only buses support indexing"
342 );
343 }
344
345 pub fn slice_one(&self) -> Option<SliceOne> {
349 SliceOne::try_from(self).ok()
350 }
351}
352
353impl IndexOwned<usize> for Slice {
354 type Output = SliceOne;
355 fn index(&self, index: usize) -> Self::Output {
356 self.assert_bus_index();
357 SliceOne::new(self.signal, Some(self.range.unwrap().index(index)))
358 }
359}
360
361impl IndexOwned<Range<usize>> for Slice {
362 type Output = Self;
363 fn index(&self, index: Range<usize>) -> Self::Output {
364 self.assert_bus_index();
365 Self::new(self.signal, Some(self.range.unwrap().index(index)))
366 }
367}
368
369impl IndexOwned<RangeFrom<usize>> for Slice {
370 type Output = Self;
371 fn index(&self, index: RangeFrom<usize>) -> Self::Output {
372 self.assert_bus_index();
373 Self::new(self.signal, Some(self.range.unwrap().index(index)))
374 }
375}
376
377impl IndexOwned<RangeFull> for Slice {
378 type Output = Self;
379 fn index(&self, index: RangeFull) -> Self::Output {
380 self.assert_bus_index();
381 Self::new(self.signal, Some(self.range.unwrap().index(index)))
382 }
383}
384
385impl IndexOwned<RangeInclusive<usize>> for Slice {
386 type Output = Self;
387 fn index(&self, index: RangeInclusive<usize>) -> Self::Output {
388 self.assert_bus_index();
389 Self::new(self.signal, Some(self.range.unwrap().index(index)))
390 }
391}
392
393impl IndexOwned<RangeTo<usize>> for Slice {
394 type Output = Self;
395 fn index(&self, index: RangeTo<usize>) -> Self::Output {
396 self.assert_bus_index();
397 Self::new(self.signal, Some(self.range.unwrap().index(index)))
398 }
399}
400
401impl IndexOwned<RangeToInclusive<usize>> for Slice {
402 type Output = Self;
403 fn index(&self, index: RangeToInclusive<usize>) -> Self::Output {
404 self.assert_bus_index();
405 Self::new(self.signal, Some(self.range.unwrap().index(index)))
406 }
407}
408
409impl IndexOwned<usize> for SliceRange {
410 type Output = usize;
411 fn index(&self, index: usize) -> Self::Output {
412 let idx = self.start + index;
413 assert!(idx < self.end, "index out of bounds");
414 idx
415 }
416}
417
418impl IndexOwned<Range<usize>> for SliceRange {
419 type Output = Self;
420 fn index(&self, index: Range<usize>) -> Self::Output {
421 assert!(self.start + index.end <= self.end, "index out of bounds");
422 Self::new(self.start + index.start, self.start + index.end)
423 }
424}
425
426impl IndexOwned<RangeFrom<usize>> for SliceRange {
427 type Output = Self;
428 fn index(&self, index: RangeFrom<usize>) -> Self::Output {
429 assert!(self.start + index.start <= self.end, "index out of bounds");
430 Self::new(self.start + index.start, self.end)
431 }
432}
433
434impl IndexOwned<RangeFull> for SliceRange {
435 type Output = Self;
436 fn index(&self, _index: RangeFull) -> Self::Output {
437 *self
438 }
439}
440
441impl IndexOwned<RangeInclusive<usize>> for SliceRange {
442 type Output = Self;
443 fn index(&self, index: RangeInclusive<usize>) -> Self::Output {
444 assert!(self.start + index.end() < self.end, "index out of bounds");
445 Self::new(self.start + index.start(), self.start + index.end() + 1)
446 }
447}
448
449impl IndexOwned<RangeTo<usize>> for SliceRange {
450 type Output = Self;
451 fn index(&self, index: RangeTo<usize>) -> Self::Output {
452 assert!(self.start + index.end <= self.end, "index out of bounds");
453 Self::new(self.start, self.start + index.end)
454 }
455}
456
457impl IndexOwned<RangeToInclusive<usize>> for SliceRange {
458 type Output = Self;
459 fn index(&self, index: RangeToInclusive<usize>) -> Self::Output {
460 assert!(self.start + index.end < self.end, "index out of bounds");
461 Self::new(self.start, self.start + index.end + 1)
462 }
463}
464
465#[derive(Debug, Clone, Serialize, Deserialize)]
467pub struct Concat {
468 parts: Vec<Slice>,
469}
470
471impl Concat {
472 #[inline]
474 pub fn new(parts: Vec<Slice>) -> Self {
475 Self { parts }
476 }
477
478 pub fn width(&self) -> usize {
482 self.parts.iter().map(Slice::width).sum()
483 }
484
485 #[inline]
487 pub fn parts(&self) -> impl Iterator<Item = &Slice> {
488 self.parts.iter()
489 }
490}
491
492impl FromIterator<Slice> for Concat {
493 fn from_iter<T: IntoIterator<Item = Slice>>(iter: T) -> Self {
494 let parts = iter.into_iter().collect();
495 Self { parts }
496 }
497}
498
499impl FromIterator<SliceOne> for Concat {
500 fn from_iter<T: IntoIterator<Item = SliceOne>>(iter: T) -> Self {
501 let parts = iter.into_iter().map(|s| s.into()).collect();
502 Self { parts }
503 }
504}
505
506impl From<Vec<Slice>> for Concat {
507 #[inline]
508 fn from(value: Vec<Slice>) -> Self {
509 Self::new(value)
510 }
511}
512
513impl From<Vec<SliceOne>> for Concat {
514 #[inline]
515 fn from(value: Vec<SliceOne>) -> Self {
516 Self::new(
517 value
518 .into_iter()
519 .map(|slice_one| slice_one.into())
520 .collect(),
521 )
522 }
523}
524
525impl From<Slice> for Concat {
526 #[inline]
527 fn from(value: Slice) -> Self {
528 Self { parts: vec![value] }
529 }
530}
531
532impl From<SliceOne> for Concat {
533 #[inline]
534 fn from(value: SliceOne) -> Self {
535 Self {
536 parts: vec![value.into()],
537 }
538 }
539}
540
541impl IndexOwned<usize> for Concat {
542 type Output = SliceOne;
543
544 fn index(&self, mut index: usize) -> Self::Output {
545 for part in self.parts.iter() {
546 let width = part.width();
547 if index < width {
548 return part.slice_one().unwrap_or_else(|| part.index(index));
549 }
550 index -= width;
551 }
552 panic!("index {index} out of bounds for signal");
553 }
554}
555
556pub trait IndexOwned<Idx>
562where
563 Idx: ?Sized,
564{
565 type Output;
567
568 fn index(&self, index: Idx) -> Self::Output;
570}
571
572#[derive(
575 Copy, Clone, Eq, PartialEq, Debug, Default, Hash, Serialize, Deserialize, thiserror::Error,
576)]
577#[error("slice width is not one")]
578pub struct SliceWidthNotOne;
579
580impl TryFrom<Slice> for SliceOne {
581 type Error = SliceWidthNotOne;
582 fn try_from(value: Slice) -> Result<Self, Self::Error> {
583 if value.width() == 1 {
584 Ok(Self {
585 signal: value.signal,
586 index: value.range.map(|s| s.start()),
587 })
588 } else {
589 Err(SliceWidthNotOne)
590 }
591 }
592}
593
594impl TryFrom<&Slice> for SliceOne {
595 type Error = SliceWidthNotOne;
596 fn try_from(value: &Slice) -> Result<Self, Self::Error> {
597 Self::try_from(*value)
598 }
599}
600
601impl From<SliceOne> for Slice {
602 fn from(value: SliceOne) -> Self {
603 Self {
604 signal: value.signal,
605 range: value.range(),
606 }
607 }
608}
609
610impl From<&SliceOne> for Slice {
611 fn from(value: &SliceOne) -> Self {
612 Self::from(*value)
613 }
614}
615
616impl SliceOne {
617 #[inline]
618 pub(crate) fn new(signal: SignalId, index: Option<usize>) -> Self {
619 Self { signal, index }
620 }
621
622 #[inline]
626 pub fn range(&self) -> Option<SliceRange> {
627 self.index.map(SliceRange::from_index)
628 }
629
630 #[inline]
632 pub const fn width(&self) -> usize {
633 1
634 }
635
636 #[inline]
638 pub fn signal(&self) -> SignalId {
639 self.signal
640 }
641
642 #[inline]
644 pub fn is_bus(&self) -> bool {
645 self.index.is_some()
646 }
647
648 #[inline]
650 pub fn index(&self) -> Option<usize> {
651 self.index
652 }
653}