use std::io;
use bytes::Bytes;
use crate::{decode, encode};
use crate::decode::Source;
use crate::length::Length;
use crate::mode::Mode;
use crate::tag::Tag;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BitString {
unused: u8,
bits: Bytes,
}
impl BitString {
pub fn new(unused: u8, bits: Bytes) -> Self {
Self { unused, bits}
}
pub fn bit(&self, bit: usize) -> bool {
let idx = bit >> 3;
if self.bits.len() <= idx {
return false
}
let bit = 7 - (bit as u8 & 7);
if self.bits.len() + 1 == idx && self.unused > bit {
return false
}
self.bits[idx] & (1 << bit) != 0
}
pub fn bit_len(&self) -> usize {
(self.bits.len() << 3) - (self.unused as usize)
}
pub fn unused(&self) -> u8 {
self.unused
}
pub fn octet_len(&self) -> usize {
self.bits.len()
}
pub fn octets(&self) -> BitStringIter {
BitStringIter(self.bits.iter())
}
pub fn octet_slice(&self) -> Option<&[u8]> {
Some(self.bits.as_ref())
}
pub fn octet_bytes(&self) -> Bytes {
self.bits.clone()
}
}
impl BitString {
pub fn take_from<S: decode::Source>(
constructed: &mut decode::Constructed<S>
) -> Result<Self, S::Err> {
constructed.take_value_if(Tag::BIT_STRING, Self::from_content)
}
pub fn skip_in<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<(), S::Err> {
cons.take_value_if(Tag::BIT_STRING, Self::skip_content)
}
pub fn from_content<S: decode::Source>(
content: &mut decode::Content<S>
) -> Result<Self, S::Err> {
match *content {
decode::Content::Primitive(ref mut inner) => {
if inner.mode() == Mode::Cer && inner.remaining() > 1000 {
xerr!(return Err(decode::Error::Malformed.into()))
}
Ok(BitString {
unused: inner.take_u8()?,
bits: inner.take_all()?,
})
}
decode::Content::Constructed(ref inner) => {
if inner.mode() == Mode::Der {
xerr!(Err(decode::Error::Malformed.into()))
}
else {
xerr!(Err(decode::Error::Unimplemented.into()))
}
}
}
}
pub fn skip_content<S: decode::Source>(
content: &mut decode::Content<S>
) -> Result<(), S::Err> {
match *content {
decode::Content::Primitive(ref mut inner) => {
if inner.mode() == Mode::Cer && inner.remaining() > 1000 {
xerr!(return Err(decode::Error::Malformed.into()))
}
inner.skip_all()
}
decode::Content::Constructed(ref inner) => {
if inner.mode() == Mode::Der {
xerr!(Err(decode::Error::Malformed.into()))
}
else {
xerr!(Err(decode::Error::Unimplemented.into()))
}
}
}
}
pub fn encode_slice<T>(value: T, unused: u8) -> BitSliceEncoder<T> {
Self::encode_slice_as(value, unused, Tag::BIT_STRING)
}
pub fn encode_slice_as<T>(
value: T,
unused: u8,
tag: Tag
) -> BitSliceEncoder<T> {
BitSliceEncoder::new(value, unused, tag)
}
}
impl encode::PrimitiveContent for BitString {
const TAG: Tag = Tag::BIT_STRING;
fn encoded_len(&self, _: Mode) -> usize {
self.bits.len() + 1
}
fn write_encoded<W: io::Write>(
&self,
_: Mode,
target: &mut W
) -> Result<(), io::Error> {
target.write_all(&[self.unused])?;
target.write_all(self.bits.as_ref())
}
}
#[derive(Clone, Debug)]
pub struct BitStringIter<'a>(::std::slice::Iter<'a, u8>);
impl<'a> Iterator for BitStringIter<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
self.0.next().cloned()
}
}
#[derive(Clone, Debug)]
pub struct BitSliceEncoder<T> {
slice: T,
unused: u8,
tag: Tag,
}
impl<T> BitSliceEncoder<T> {
fn new(slice: T, unused: u8, tag: Tag) -> Self {
BitSliceEncoder { slice, unused, tag }
}
}
impl<T: AsRef<[u8]>> encode::Values for BitSliceEncoder<T> {
fn encoded_len(&self, mode: Mode) -> usize {
if mode == Mode::Cer {
unimplemented!()
}
let len = self.slice.as_ref().len() + 1;
self.tag.encoded_len() + Length::Definite(len).encoded_len() + len
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
if mode == Mode::Cer {
unimplemented!()
}
self.tag.write_encoded(false, target)?;
Length::Definite(self.slice.as_ref().len() + 1).write_encoded(target)?;
target.write_all(&[self.unused])?;
target.write_all(self.slice.as_ref())
}
}