|
8 | 8 | use crate::dag::{Dag, DagLike, NoSharing};
|
9 | 9 | use crate::types::Final;
|
10 | 10 |
|
| 11 | +use crate::{types, EarlyEndOfStreamError}; |
11 | 12 | use std::collections::VecDeque;
|
12 | 13 | use std::fmt;
|
13 | 14 | use std::hash::Hash;
|
@@ -388,6 +389,138 @@ impl<'a> Iterator for PaddedBitsIter<'a> {
|
388 | 389 | }
|
389 | 390 | }
|
390 | 391 |
|
| 392 | +trait Padding { |
| 393 | + fn read_left_padding<I: Iterator<Item = bool>>( |
| 394 | + bits: &mut I, |
| 395 | + ty_l: &Final, |
| 396 | + ty_r: &Final, |
| 397 | + ) -> Result<(), EarlyEndOfStreamError>; |
| 398 | + |
| 399 | + fn read_right_padding<I: Iterator<Item = bool>>( |
| 400 | + bits: &mut I, |
| 401 | + ty_l: &Final, |
| 402 | + ty_r: &Final, |
| 403 | + ) -> Result<(), EarlyEndOfStreamError>; |
| 404 | +} |
| 405 | + |
| 406 | +struct CompactEncoding; |
| 407 | +struct PaddedEncoding; |
| 408 | + |
| 409 | +impl Padding for CompactEncoding { |
| 410 | + fn read_left_padding<I: Iterator<Item = bool>>( |
| 411 | + _: &mut I, |
| 412 | + _: &Final, |
| 413 | + _: &Final, |
| 414 | + ) -> Result<(), EarlyEndOfStreamError> { |
| 415 | + // no padding |
| 416 | + Ok(()) |
| 417 | + } |
| 418 | + |
| 419 | + fn read_right_padding<I: Iterator<Item = bool>>( |
| 420 | + _: &mut I, |
| 421 | + _: &Final, |
| 422 | + _: &Final, |
| 423 | + ) -> Result<(), EarlyEndOfStreamError> { |
| 424 | + // no padding |
| 425 | + Ok(()) |
| 426 | + } |
| 427 | +} |
| 428 | + |
| 429 | +impl Padding for PaddedEncoding { |
| 430 | + fn read_left_padding<I: Iterator<Item = bool>>( |
| 431 | + bits: &mut I, |
| 432 | + ty_l: &Final, |
| 433 | + ty_r: &Final, |
| 434 | + ) -> Result<(), EarlyEndOfStreamError> { |
| 435 | + for _ in 0..ty_l.pad_left(ty_r) { |
| 436 | + let _padding = bits.next().ok_or(EarlyEndOfStreamError)?; |
| 437 | + } |
| 438 | + Ok(()) |
| 439 | + } |
| 440 | + |
| 441 | + fn read_right_padding<I: Iterator<Item = bool>>( |
| 442 | + bits: &mut I, |
| 443 | + ty_l: &Final, |
| 444 | + ty_r: &Final, |
| 445 | + ) -> Result<(), EarlyEndOfStreamError> { |
| 446 | + for _ in 0..ty_l.pad_left(ty_r) { |
| 447 | + let _padding = bits.next().ok_or(EarlyEndOfStreamError)?; |
| 448 | + } |
| 449 | + Ok(()) |
| 450 | + } |
| 451 | +} |
| 452 | + |
| 453 | +impl Value { |
| 454 | + fn from_bits<I: Iterator<Item = bool>, P: Padding>( |
| 455 | + bits: &mut I, |
| 456 | + ty: &Final, |
| 457 | + ) -> Result<Self, EarlyEndOfStreamError> { |
| 458 | + enum State<'a> { |
| 459 | + ProcessType(&'a Final), |
| 460 | + DoSumL(Arc<Final>), |
| 461 | + DoSumR(Arc<Final>), |
| 462 | + DoProduct, |
| 463 | + } |
| 464 | + |
| 465 | + let mut stack = vec![State::ProcessType(ty)]; |
| 466 | + let mut result_stack = vec![]; |
| 467 | + while let Some(state) = stack.pop() { |
| 468 | + match state { |
| 469 | + State::ProcessType(ty) => match ty.bound() { |
| 470 | + types::CompleteBound::Unit => result_stack.push(Value::unit()), |
| 471 | + types::CompleteBound::Sum(ref l, ref r) => { |
| 472 | + if !bits.next().ok_or(EarlyEndOfStreamError)? { |
| 473 | + P::read_left_padding(bits, l, r)?; |
| 474 | + stack.push(State::DoSumL(Arc::clone(r))); |
| 475 | + stack.push(State::ProcessType(l)); |
| 476 | + } else { |
| 477 | + P::read_right_padding(bits, l, r)?; |
| 478 | + stack.push(State::DoSumR(Arc::clone(l))); |
| 479 | + stack.push(State::ProcessType(r)); |
| 480 | + } |
| 481 | + } |
| 482 | + types::CompleteBound::Product(ref l, ref r) => { |
| 483 | + stack.push(State::DoProduct); |
| 484 | + stack.push(State::ProcessType(r)); |
| 485 | + stack.push(State::ProcessType(l)); |
| 486 | + } |
| 487 | + }, |
| 488 | + State::DoSumL(r) => { |
| 489 | + let val = result_stack.pop().unwrap(); |
| 490 | + result_stack.push(Value::left(val, r)); |
| 491 | + } |
| 492 | + State::DoSumR(l) => { |
| 493 | + let val = result_stack.pop().unwrap(); |
| 494 | + result_stack.push(Value::right(l, val)); |
| 495 | + } |
| 496 | + State::DoProduct => { |
| 497 | + let val_r = result_stack.pop().unwrap(); |
| 498 | + let val_l = result_stack.pop().unwrap(); |
| 499 | + result_stack.push(Value::product(val_l, val_r)); |
| 500 | + } |
| 501 | + } |
| 502 | + } |
| 503 | + debug_assert_eq!(result_stack.len(), 1); |
| 504 | + Ok(result_stack.pop().unwrap()) |
| 505 | + } |
| 506 | + |
| 507 | + /// Decode a value of the given type from its compact bit encoding. |
| 508 | + pub fn from_compact_bits<I: Iterator<Item = bool>>( |
| 509 | + bits: &mut I, |
| 510 | + ty: &Final, |
| 511 | + ) -> Result<Self, EarlyEndOfStreamError> { |
| 512 | + Self::from_bits::<_, CompactEncoding>(bits, ty) |
| 513 | + } |
| 514 | + |
| 515 | + /// Decode a value of the given type from its padded bit encoding. |
| 516 | + pub fn from_padded_bits<I: Iterator<Item = bool>>( |
| 517 | + bits: &mut I, |
| 518 | + ty: &Final, |
| 519 | + ) -> Result<Self, EarlyEndOfStreamError> { |
| 520 | + Self::from_bits::<_, PaddedEncoding>(bits, ty) |
| 521 | + } |
| 522 | +} |
| 523 | + |
391 | 524 | #[cfg(test)]
|
392 | 525 | mod tests {
|
393 | 526 | use super::*;
|
|
0 commit comments