#[cfg(feature = "bits")]
use bitvec::prelude::*;
use no_std_io::io::{ErrorKind, Read, Seek, SeekFrom};
use crate::{ctx::Order, prelude::NeedSize, DekuError};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "bits")]
use core::cmp::Ordering;
#[cfg(feature = "logging")]
use log;
pub enum ReaderRet {
Bytes,
#[cfg(all(feature = "bits", feature = "alloc"))]
Bits(Option<BitVec<u8, Msb0>>),
}
#[derive(Debug, Clone)]
pub enum Leftover {
Byte(u8),
#[cfg(feature = "bits")]
Bits(crate::BoundedBitVec<[u8; 1], Msb0>),
}
pub struct Reader<R: Read + Seek> {
inner: R,
pub leftover: Option<Leftover>,
pub bits_read: usize,
}
impl<R: Read + Seek> Seek for Reader<R> {
#[inline]
fn seek(&mut self, pos: SeekFrom) -> no_std_io::io::Result<u64> {
#[cfg(feature = "logging")]
log::trace!("seek: {pos:?}");
self.leftover = None;
match pos {
SeekFrom::Start(n) => {
if n > 0 {
self.bits_read = (n * 8) as usize;
}
}
SeekFrom::End(_) => (),
SeekFrom::Current(n) => {
if n > 0 {
self.bits_read += (n * 8) as usize;
}
}
}
self.inner.seek(pos)
}
}
impl<R: Read + Seek> AsMut<R> for Reader<R> {
#[inline]
fn as_mut(&mut self) -> &mut R {
&mut self.inner
}
}
impl<R: Read + Seek> Reader<R> {
#[inline]
pub fn new(inner: R) -> Self {
Self {
inner,
leftover: None,
bits_read: 0,
}
}
#[inline]
pub fn into_inner(self) -> R {
self.inner
}
#[inline]
#[cfg(feature = "alloc")]
pub fn rest(&mut self) -> Vec<bool> {
#[cfg(feature = "bits")]
match &self.leftover {
Some(Leftover::Bits(bits)) => {
debug_assert!(bits.len() <= 8);
bits.as_bitslice().iter().by_vals().collect()
}
Some(Leftover::Byte(byte)) => {
let bytes: &[u8] = &[*byte];
let bits: BitVec<u8, Msb0> = BitVec::try_from_slice(bytes).unwrap();
bits.iter().by_vals().collect()
}
None => alloc::vec![],
}
#[cfg(not(feature = "bits"))]
alloc::vec![]
}
#[inline]
pub fn end(&mut self) -> bool {
if self.leftover.is_some() {
#[cfg(feature = "logging")]
log::trace!("not end");
false
} else {
let mut buf = [0; 1];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
#[cfg(feature = "logging")]
log::trace!("end");
return true;
}
}
#[cfg(feature = "logging")]
log::trace!("not end: read {:02x?}", &buf);
self.leftover = Some(Leftover::Byte(buf[0]));
false
}
}
#[inline]
#[allow(unused_mut)]
pub fn skip_bits(&mut self, mut amt: usize, _order: Order) -> Result<(), DekuError> {
#[cfg(feature = "bits")]
{
#[cfg(feature = "logging")]
log::trace!("skip_bits: {amt}");
if let Some(Leftover::Bits(bits)) = &self.leftover {
let mut buf = bitarr!(u8, Msb0; 0; 8);
let needed = core::cmp::min(amt, bits.len());
amt -= needed;
self.read_bits_into(&mut buf[..needed], _order)?;
}
let bytes_amt = amt / 8;
let bits_amt = amt % 8;
if bytes_amt != 0 {
debug_assert_eq!(self.bits_read % 8, 0);
self.seek(SeekFrom::Current(
i64::try_from(bytes_amt).expect("could not convert seek usize into i64"),
))
.map_err(|e| DekuError::Io(e.kind()))?;
}
let mut buf = bitarr!(u8, Msb0; 0; 8);
self.read_bits_into(&mut buf[..bits_amt], _order)?;
}
#[cfg(not(feature = "bits"))]
{
if amt > 0 {
panic!("requires deku feature: bits");
}
}
Ok(())
}
#[inline(never)]
#[cfg(feature = "bits")]
pub fn read_bits_into(
&mut self,
dst: &mut BitSlice<u8, Msb0>,
order: Order,
) -> Result<(), DekuError> {
#[cfg(feature = "logging")]
log::trace!("read_bits_into: {order:?}, {:?}", dst.len());
if dst.is_empty() {
return Ok(());
}
let mut leftover = None;
core::mem::swap(&mut leftover, &mut self.leftover);
if let Some(Leftover::Byte(byte)) = leftover {
leftover = Some(Leftover::Bits(BitArray::from([byte]).into()));
}
let previous_len = if let Some(Leftover::Bits(bits)) = &leftover {
bits.len()
} else {
0
};
match dst.len().cmp(&previous_len) {
Ordering::Less => {
let Some(Leftover::Bits(mut bits)) = leftover else {
unreachable!();
};
debug_assert!(bits.len() <= 8);
match order {
Order::Lsb0 => {
let used = bits.split_off(bits.len() - dst.len());
dst.copy_from_bitslice(used.as_bitslice());
self.leftover = Some(Leftover::Bits(bits));
}
Order::Msb0 => {
let used = bits.split_off(dst.len());
dst.copy_from_bitslice(bits.as_bitslice());
self.leftover = Some(Leftover::Bits(used));
}
}
}
Ordering::Equal => {
let Some(Leftover::Bits(bits)) = &mut leftover else {
unreachable!();
};
debug_assert!(bits.len() <= 8);
let mut bbv: crate::BoundedBitVec<[u8; 1], Msb0> = crate::BoundedBitVec::new();
core::mem::swap(&mut bbv, bits);
let (consumed, _dst) = dst.split_at_mut(bbv.len());
let end = bbv.len();
consumed.copy_from_bitslice(bbv.as_mut_bitslice().split_at_mut(end).0);
}
Ordering::Greater => {
let (start, end) = if order == Order::Lsb0 {
let need = dst.len() - previous_len;
let start = 8 - ((need.div_ceil(8) * 8) - need);
(start, need)
} else if let Some(Leftover::Bits(bits)) = &leftover {
debug_assert_eq!(order, Order::Msb0);
let end = bits.len();
dst[..end].copy_from_bitslice(bits.as_bitslice().split_at(end).0);
(end, dst.len())
} else {
(0, dst.len())
};
let remainder = if order == Order::Lsb0 {
if dst.len() % 8 != 0 {
let mut iter = dst[..end].rchunks_exact_mut(8);
for slot in iter.by_ref() {
let mut buf: [u8; 1] = [0u8];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(dst.len())));
}
}
slot.store_be(buf[0]);
}
iter.into_remainder()
} else {
let mut iter = dst[..end].chunks_exact_mut(8);
for slot in iter.by_ref() {
let mut buf: [u8; 1] = [0u8];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(dst.len())));
}
}
slot.store_be(buf[0]);
}
iter.into_remainder()
}
} else {
debug_assert_eq!(order, Order::Msb0);
let mut iter = dst[start..end].chunks_exact_mut(8);
for slot in iter.by_ref() {
let mut buf: [u8; 1] = [0u8];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(dst.len())));
}
}
slot.store_be(buf[0]);
}
iter.into_remainder()
};
if order == Order::Lsb0 {
if !remainder.is_empty() {
let mut buf: [u8; 1] = [0u8];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(dst.len())));
}
return Err(DekuError::Io(e.kind()));
}
let slice: &mut BitSlice<u8, Msb0> =
BitSlice::try_from_slice_mut(buf.as_mut_slice()).unwrap();
let (rest, used) = slice.split_at_mut(8 - remainder.len());
let len = used.len();
remainder.copy_from_bitslice(used.split_at_mut(len).0);
self.leftover = Some(Leftover::Bits(rest.into()));
}
if let Some(Leftover::Bits(bits)) = leftover {
dst[end..].copy_from_bitslice(bits.as_bitslice());
}
} else if !remainder.is_empty() {
debug_assert_eq!(Order::Msb0, order);
let mut buf: [u8; 1] = [0u8];
if let Err(e) = self.inner.read_exact(&mut buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(dst.len())));
}
return Err(DekuError::Io(e.kind()));
}
let slice: &mut BitSlice<u8, Msb0> =
BitSlice::try_from_slice_mut(buf.as_mut_slice()).unwrap();
let (used, rest) = slice.split_at_mut(remainder.len());
let end = used.len();
remainder.copy_from_bitslice(used.split_at_mut(end).0);
self.leftover = Some(Leftover::Bits(rest.into()));
}
}
}
self.bits_read += dst.len();
Ok(())
}
#[inline(never)]
#[cfg(all(feature = "bits", feature = "alloc"))]
pub fn read_bits(
&mut self,
amt: usize,
order: Order,
) -> Result<Option<BitVec<u8, Msb0>>, DekuError> {
let mut vec = BitVec::repeat(false, amt);
self.read_bits_into(vec.as_mut_bitslice(), order)?;
Ok(Some(vec))
}
#[inline(always)]
pub fn read_bytes(
&mut self,
amt: usize,
buf: &mut [u8],
order: Order,
) -> Result<ReaderRet, DekuError> {
#[cfg(feature = "logging")]
log::trace!("read_bytes: requesting {amt} bytes");
if self.leftover.is_none() {
if let Err(e) = self.inner.read_exact(&mut buf[..amt]) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(amt * 8)));
}
return Err(DekuError::Io(e.kind()));
}
let bits_read = amt * 8;
self.bits_read += bits_read;
#[cfg(feature = "logging")]
log::trace!("read_bytes: returning {:02x?}", &buf[..amt]);
return Ok(ReaderRet::Bytes);
}
self.read_bytes_other(amt, buf, order)
}
fn read_bytes_other(
&mut self,
amt: usize,
buf: &mut [u8],
_order: Order,
) -> Result<ReaderRet, DekuError> {
match self.leftover {
Some(Leftover::Byte(byte)) => self.read_bytes_leftover(buf, byte, amt),
#[cfg(feature = "bits")]
Some(Leftover::Bits(_)) => {
let slice = BitSlice::from_slice_mut(&mut buf[..amt]);
self.read_bits_into(slice, _order)?;
Ok(ReaderRet::Bytes)
}
_ => unreachable!(),
}
}
fn read_bytes_leftover(
&mut self,
buf: &mut [u8],
byte: u8,
amt: usize,
) -> Result<ReaderRet, DekuError> {
buf[0] = byte;
#[cfg(feature = "logging")]
log::trace!("read_bytes_leftover: using previous read {:02x?}", &buf[0]);
self.leftover = None;
let remaining = amt - 1;
if remaining == 0 {
#[cfg(feature = "logging")]
log::trace!("read_bytes_const_leftover: returning {:02x?}", &buf);
self.bits_read += amt * 8;
return Ok(ReaderRet::Bytes);
}
let buf_len = buf.len();
if buf_len < remaining {
return Err(DekuError::Incomplete(NeedSize::new(remaining * 8)));
}
if let Err(e) = self
.inner
.read_exact(&mut buf[amt - remaining..][..remaining])
{
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(remaining * 8)));
}
return Err(DekuError::Io(e.kind()));
}
self.bits_read += amt * 8;
#[cfg(feature = "logging")]
log::trace!("read_bytes_leftover: returning {:02x?}", &buf);
Ok(ReaderRet::Bytes)
}
#[inline(always)]
pub fn read_bytes_const<const N: usize>(
&mut self,
buf: &mut [u8; N],
order: Order,
) -> Result<ReaderRet, DekuError> {
#[cfg(feature = "logging")]
log::trace!("read_bytes_const: requesting {N} bytes");
if self.leftover.is_none() {
if let Err(e) = self.inner.read_exact(buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(N * 8)));
}
return Err(DekuError::Io(e.kind()));
}
self.bits_read += N * 8;
#[cfg(feature = "logging")]
log::trace!("read_bytes_const: returning {:02x?}", &buf);
return Ok(ReaderRet::Bytes);
}
self.read_bytes_const_other::<N>(buf, order)
}
fn read_bytes_const_other<const N: usize>(
&mut self,
buf: &mut [u8; N],
_order: Order,
) -> Result<ReaderRet, DekuError> {
match self.leftover {
Some(Leftover::Byte(byte)) => {
self.read_bytes_const_leftover(buf, byte)?;
Ok(ReaderRet::Bytes)
}
#[cfg(feature = "bits")]
Some(Leftover::Bits(_)) => {
let slice = BitSlice::from_slice_mut(buf);
self.read_bits_into(slice, _order)?;
Ok(ReaderRet::Bytes)
}
_ => unreachable!(),
}
}
pub fn read_bytes_const_into<const N: usize>(
&mut self,
buf: &mut [u8; N],
_order: Order,
) -> Result<(), DekuError> {
if self.leftover.is_none() {
if let Err(e) = self.inner.read_exact(buf) {
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(N * 8)));
}
return Err(DekuError::Io(e.kind()));
}
self.bits_read += N * 8;
return Ok(());
}
match self.leftover {
Some(Leftover::Byte(byte)) => self.read_bytes_const_leftover(buf, byte),
#[cfg(feature = "bits")]
Some(Leftover::Bits(_)) => {
let slice = BitSlice::from_slice_mut(buf);
self.read_bits_into(slice, _order)?;
Ok(())
}
None => unreachable!(),
}
}
fn read_bytes_const_leftover<const N: usize>(
&mut self,
buf: &mut [u8; N],
byte: u8,
) -> Result<(), DekuError> {
buf[0] = byte;
#[cfg(feature = "logging")]
log::trace!(
"read_bytes_const_leftover: using previous read {:02x?}",
&buf[0]
);
self.leftover = None;
let remaining = N - 1;
if remaining == 0 {
#[cfg(feature = "logging")]
log::trace!("read_bytes_const_leftover: returning {:02x?}", &buf);
self.bits_read += N * 8;
return Ok(());
}
let buf_len = buf.len();
if buf_len < remaining {
return Err(DekuError::Incomplete(NeedSize::new(remaining * 8)));
}
if let Err(e) = self
.inner
.read_exact(&mut buf[N - remaining..][..remaining])
{
if e.kind() == ErrorKind::UnexpectedEof {
return Err(DekuError::Incomplete(NeedSize::new(remaining * 8)));
}
return Err(DekuError::Io(e.kind()));
}
self.bits_read += N * 8;
#[cfg(feature = "logging")]
log::trace!("read_bytes_const_leftover: returning {:02x?}", &buf);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use hexlit::hex;
use no_std_io::io::Cursor;
#[test]
#[cfg(all(feature = "alloc", feature = "bits"))]
fn test_end() {
let input = hex!("aabb");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
assert!(!reader.end());
let mut buf = [0; 2];
let _ = reader.read_bytes_const::<2>(&mut buf, Order::Lsb0).unwrap();
assert!(reader.end());
assert_eq!(reader.bits_read, 8 * 2);
let input = hex!("aa");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
assert!(!reader.end());
let _ = reader.read_bits(4, Order::Lsb0).unwrap();
assert!(!reader.end());
let _ = reader.read_bits(4, Order::Lsb0).unwrap();
assert!(reader.end());
assert_eq!(reader.bits_read, 8);
let input = hex!("aa");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
assert!(!reader.end());
let mut buf = [0; 1];
let _ = reader.read_bytes(1, &mut buf, Order::Lsb0).unwrap();
assert!(reader.end());
assert_eq!(reader.bits_read, 8);
}
#[test]
#[cfg(all(feature = "alloc", feature = "bits"))]
fn test_bits_less() {
let input = hex!("aa");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let _ = reader.read_bits(1, Order::Lsb0);
let _ = reader.read_bits(4, Order::Lsb0);
let _ = reader.read_bits(3, Order::Lsb0);
}
#[test]
fn test_inner() {
let input = hex!("aabbcc");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let mut buf = [0; 1];
let _ = reader.read_bytes(1, &mut buf, Order::Lsb0).unwrap();
assert_eq!([0xaa], buf);
assert_eq!(reader.bits_read, 8);
}
#[cfg(all(feature = "alloc", feature = "bits"))]
#[test]
fn test_bit_order() {
let input = hex!("ab");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let input = hex!("ab");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let input = hex!("abcd");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 0]));
let input = hex!("abcd");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 1]));
let input = hex!("abcd");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 1]));
let input = hex!("abcd");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 1]));
let bits = reader.read_bits(4, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 1, 0, 0]));
let input = hex!("ab");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(1, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1]));
let bits = reader.read_bits(3, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 0, 1, 0]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1, 1]));
let input = hex!("ab");
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(1, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1]));
let bits = reader.read_bits(3, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1, 0, 1]));
let bits = reader.read_bits(4, Order::Msb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 0, 1, 0, 1]));
}
#[cfg(all(feature = "alloc", feature = "bits"))]
#[test]
fn test_long_unaligned_bytes_read() {
use alloc::vec;
let input = vec![0xff; 0xff * 2];
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
let bits = reader.read_bits(1, Order::Lsb0).unwrap();
assert_eq!(bits, Some(bitvec![u8, Msb0; 1]));
let mut out = vec![0x00; 0xff * 2];
let _ = reader.read_bytes(0xfe * 2, &mut out, Order::Lsb0).unwrap();
}
#[cfg(all(feature = "alloc", feature = "bits"))]
#[test]
fn test_regression_msb0() {
let input = [0x64, 0x20];
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
reader.leftover = Some(Leftover::Bits([true, false].as_slice().into()));
let bits = reader.read_bits(17, Order::Msb0).unwrap();
assert_eq!(
bits,
Some(bitvec![u8, Msb0; 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0])
);
}
#[cfg(all(feature = "alloc", feature = "bits"))]
#[test]
fn test_regression_lsb0() {
let input = [0x64, 0x20];
let mut cursor = Cursor::new(input);
let mut reader = Reader::new(&mut cursor);
reader.leftover = Some(Leftover::Bits([true, false].as_slice().into()));
let bits = reader.read_bits(17, Order::Lsb0).unwrap();
assert_eq!(
bits,
Some(bitvec![u8, Msb0; 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0])
);
}
}