1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
//! Captured BER-encoded data.
//!
//! This is a private module. Its public items are re-exported by the parent.
use std::{fmt, io, mem, ops};
use bytes::{Bytes, BytesMut};
use crate::{decode, encode};
use crate::decode::{BytesSource, DecodeError, IntoSource, Pos};
use crate::mode::Mode;
//------------ Captured ------------------------------------------------------
/// A wrapper for BER encoded data.
///
/// This types keeps a sequence of BER-encoded data in a [`Bytes`] value. It
/// allows for delayed processing of this data and therefore zero-allocation
/// handling of sequences and similar types by implementing iterators and
/// helper types that work directly on the the still-encoded data.
///
/// You usually acquire a value of this type trough the [`capture`] family of
/// methods on constructed BER content. Alternatively, you can also construct
/// a new value via the [`CapturedBuilder`].
///
/// Once you have a captured value, you can use the [`decode`] method to
/// decode the entire captured value or [`decode_partial`] to decode some
/// values at the start of the captured value. The latter manipulates the
/// captured content by moving past the captured values and is therefore
/// perfect for an iterator.
///
/// The value also remembers what [`Mode`] the original data was decoded in
/// and will automatically use this encoding in those methods.
///
/// [`Bytes`]: ../../bytes/struct.Bytes.html
/// [`capture`]: ../decode/struct.Constructed.html
/// [`from_values`]: #method.from_values
/// [`empty`]: #method.empty
/// [`decode`]: #method.decode
/// [`decode_partial`]: #method.decode
/// [`Mode`]: ../enum.Mode.html
#[derive(Clone)]
pub struct Captured {
/// The captured data.
bytes: Bytes,
/// The encoding mode of the captured data.
mode: Mode,
/// The start position of the data in the original source.
start: Pos,
}
impl Captured {
/// Creates a new captured value from bytes and a mode.
///
/// Because we can’t guarantee that the bytes are properly encoded, we
/// keep this function crate public. The type, however, doesn’t rely on
/// content being properly encoded so this method isn’t unsafe.
pub(crate) fn new(bytes: Bytes, mode: Mode, start: Pos) -> Self {
Captured { bytes, mode, start }
}
/// Creates a captured value by encoding data.
///
/// The function takes a value encoder, encodes it into a bytes value
/// with the given mode, and returns the resulting data as a captured
/// value.
pub fn from_values<V: encode::Values>(mode: Mode, values: V) -> Self {
let mut builder = Self::builder(mode);
builder.extend(values);
builder.freeze()
}
/// Creates a new empty captured value in the given mode.
pub fn empty(mode: Mode) -> Self {
Captured {
bytes: Bytes::new(),
mode,
start: Pos::default(),
}
}
/// Creates a builder for a captured value in the given mode.
pub fn builder(mode: Mode) -> CapturedBuilder {
CapturedBuilder::new(mode)
}
/// Converts the captured values into a builder in order to add new values.
///
/// Because the captured values might be shared, this requires copying the
/// underlying data.
pub fn into_builder(self) -> CapturedBuilder {
self.into()
}
/// Decodes the full content using the provided function argument.
///
/// The method consumes the value. If you want to keep it around, simply
/// clone it first. Since bytes values are cheap to clone, this is
/// relatively cheap.
pub fn decode<F, T>(
self, op: F
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
where
F: FnOnce(
&mut decode::Constructed<BytesSource>
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
{
self.mode.decode(self.bytes, op)
}
/// Decodes the beginning of the content of the captured value.
///
/// The method calls `op` to parse a number of values from the beginning
/// of the value and then advances the content of the captured value until
/// after the end of these decoded values.
pub fn decode_partial<F, T>(
&mut self, op: F
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
where
F: FnOnce(
&mut decode::Constructed<&mut BytesSource>
) -> Result<T, DecodeError<<BytesSource as decode::Source>::Error>>
{
let mut source = mem::replace(
&mut self.bytes, Bytes::new()
).into_source();
let res = self.mode.decode(&mut source, op);
self.bytes = source.into_bytes();
res
}
/// Trades the value for a bytes value with the raw data.
pub fn into_bytes(self) -> Bytes {
self.bytes
}
/// Returns a bytes slice with the raw data of the captured value.
pub fn as_slice(&self) -> &[u8] {
self.bytes.as_ref()
}
}
//--- Deref and AsRef
impl ops::Deref for Captured {
type Target = Bytes;
fn deref(&self) -> &Bytes {
&self.bytes
}
}
impl AsRef<Bytes> for Captured {
fn as_ref(&self) -> &Bytes {
&self.bytes
}
}
impl AsRef<[u8]> for Captured {
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
//--- IntoSource
impl IntoSource for Captured {
type Source = BytesSource;
fn into_source(self) -> Self::Source {
BytesSource::with_offset(self.bytes, self.start)
}
}
//--- encode::Values
impl encode::Values for Captured {
fn encoded_len(&self, mode: Mode) -> usize {
assert!(
!(self.mode != mode && mode != Mode::Ber),
"Trying to encode a captured value with incompatible mode"
);
self.bytes.len()
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
assert!(
!(self.mode != mode && mode != Mode::Ber),
"Trying to encode a captured value with incompatible mode"
);
target.write_all(self.bytes.as_ref())
}
}
//--- Debug
impl fmt::Debug for Captured {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[ ")?;
for (i, &v) in self.bytes.iter().enumerate() {
write!(f, "{:02x} ", v)?;
if i % 4 == 3 {
write!(f, " ")?;
}
}
write!(f, "]")
}
}
//------------ CapturedBuilder -----------------------------------------------
pub struct CapturedBuilder {
bytes: BytesMut,
mode: Mode,
}
impl CapturedBuilder {
pub fn new(mode: Mode) -> Self {
CapturedBuilder {
bytes: BytesMut::new(),
mode
}
}
pub fn with_capacity(capacity: usize, mode: Mode) -> Self {
CapturedBuilder {
bytes: BytesMut::with_capacity(capacity),
mode
}
}
/// Extends the captured value by encoding the given values.
///
/// The function encodes the given values in the captured value’s own mode
/// and places the encoded content at the end of the captured value.
pub fn extend<V: encode::Values>(&mut self, values: V) {
values.write_encoded(
self.mode,
&mut CapturedWriter(&mut self.bytes)
).unwrap()
}
pub fn freeze(self) -> Captured {
Captured::new(self.bytes.freeze(), self.mode, Pos::default())
}
}
impl From<Captured> for CapturedBuilder {
fn from(src: Captured) -> Self {
CapturedBuilder {
bytes: src.bytes.as_ref().into(),
mode: src.mode
}
}
}
//------------ CapturedWriter ------------------------------------------------
struct CapturedWriter<'a>(&'a mut BytesMut);
impl<'a> io::Write for CapturedWriter<'a> {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
self.0.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), io::Error> {
Ok(())
}
}