71 lines
1.7 KiB
Rust
71 lines
1.7 KiB
Rust
|
//@ known-bug: #102310
|
||
|
//@ compile-flags: -Copt-level=0
|
||
|
//@ edition:2021
|
||
|
// ignore-tidy-linelength
|
||
|
|
||
|
use std::vec::Vec;
|
||
|
use std::iter::Peekable;
|
||
|
|
||
|
pub fn main() {
|
||
|
let packet = decode(vec![1,0,1,0]);
|
||
|
}
|
||
|
|
||
|
pub fn decode(bitstream: Vec<u64>) -> Packet {
|
||
|
let mut bitstream_itr = bitstream.into_iter().peekable();
|
||
|
return match decode_packet(&mut bitstream_itr) {
|
||
|
Some(p) => p,
|
||
|
None => panic!("expected outer packet"),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn decode_packets<I: Iterator<Item = u64>>(itr: &mut Peekable<I>) -> Vec<Packet> {
|
||
|
let mut res = Vec::new();
|
||
|
loop {
|
||
|
match decode_packet(itr) {
|
||
|
Some(p) => { res.push(p); },
|
||
|
None => break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
pub fn decode_packet<I: Iterator<Item = u64>>(itr: &mut Peekable<I>) -> Option<Packet> {
|
||
|
// get version digits
|
||
|
let version = extend_number(0, itr, 3)?;
|
||
|
let type_id = extend_number(0, itr, 3)?;
|
||
|
return operator_packet(version, type_id, itr);
|
||
|
}
|
||
|
|
||
|
pub fn operator_packet<I: Iterator<Item = u64>>(version: u64, type_id: u64, itr: &mut Peekable<I>) -> Option<Packet> {
|
||
|
let p = OperatorPacket {
|
||
|
version: version,
|
||
|
type_id: type_id,
|
||
|
packets: decode_packets(&mut itr.take(0).peekable()),
|
||
|
};
|
||
|
|
||
|
return Some(Packet::Operator(p));
|
||
|
}
|
||
|
|
||
|
pub fn extend_number<I: Iterator<Item = u64>>(num: u64, itr: &mut Peekable<I>, take: u64) -> Option<u64> {
|
||
|
let mut value = num;
|
||
|
for _ in 0..take {
|
||
|
value *= 2;
|
||
|
value += itr.next()?;
|
||
|
}
|
||
|
|
||
|
return Some(value);
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum Packet {
|
||
|
Operator(OperatorPacket),
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct OperatorPacket {
|
||
|
version: u64,
|
||
|
type_id: u64,
|
||
|
packets: Vec<Packet>
|
||
|
}
|