mirror of
https://github.com/trussed-dev/flexiber.git
synced 2026-06-20 04:16:10 -07:00
Simplification
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
der = "0.2.3"
|
||||
# der = "0.2.3"
|
||||
|
||||
[dependencies.heapless]
|
||||
version = "0.6.0"
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
use core::convert::TryInto;
|
||||
use crate::{Encodable, ErrorKind, Header, Length, nested, Result, Tag};
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
use crate::{Encodable, ErrorKind, header::Header, Length, Result, Tag};
|
||||
|
||||
/// SIMPLE-TLV encoder.
|
||||
#[derive(Debug)]
|
||||
@@ -59,7 +59,7 @@ impl<'a> Encoder<'a> {
|
||||
|
||||
/// Encode a collection of values which impl the [`Encodable`] trait under a given tag.
|
||||
pub fn nested(&mut self, tag: Tag, encodables: &[&dyn Encodable]) -> Result<()> {
|
||||
let expected_len = nested::encoded_len_inner(encodables)?;
|
||||
let expected_len = Length::try_from(encodables)?;
|
||||
Header::new(tag, expected_len).and_then(|header| header.encode(self))?;
|
||||
|
||||
let mut nested_encoder = Encoder::new(self.reserve(expected_len)?);
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ pub enum ErrorKind {
|
||||
Truncated,
|
||||
|
||||
/// Encoded message is shorter than the expected length
|
||||
/// (i.e. an `Encodable` impl on a particular type has a buggy `encoded_len`)
|
||||
/// (i.e. an `Encodable` impl on a particular type has a buggy `encoded_length`)
|
||||
Underlength {
|
||||
/// Expected length
|
||||
expected: Length,
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ impl Decodable<'_> for Header {
|
||||
}
|
||||
|
||||
impl Encodable for Header {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
self.tag.encoded_len()? + self.length.encoded_len()?
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
self.tag.encoded_length()? + self.length.encoded_length()?
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
|
||||
+13
-1
@@ -32,6 +32,18 @@ impl Length {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the sum of the encoded lengths of the encodables.
|
||||
impl<'a> TryFrom<&'a [&'a dyn Encodable]> for Length {
|
||||
type Error = Error;
|
||||
fn try_from(encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
encodables
|
||||
.iter()
|
||||
.fold(Ok(Length::zero()), |sum, encodable| {
|
||||
sum + encodable.encoded_length()?
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Length {
|
||||
type Output = Result<Self>;
|
||||
|
||||
@@ -122,7 +134,7 @@ impl Decodable<'_> for Length {
|
||||
}
|
||||
|
||||
impl Encodable for Length {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
match self.0 {
|
||||
0..=0xFE => Ok(Length(1)),
|
||||
_ => Ok(Length(3)),
|
||||
|
||||
+6
-6
@@ -35,18 +35,18 @@ mod encoder;
|
||||
mod error;
|
||||
mod header;
|
||||
mod length;
|
||||
mod nested;
|
||||
mod slice;
|
||||
mod tag;
|
||||
mod tagged_slice;
|
||||
mod tagged;
|
||||
mod traits;
|
||||
|
||||
pub use tagged_slice::TaggedSlice;
|
||||
pub use decoder::Decoder;
|
||||
pub use encoder::Encoder;
|
||||
pub use error::{Error, ErrorKind, Result};
|
||||
pub(crate) use header::Header;
|
||||
// pub(crate) use header::Header;
|
||||
pub use length::Length;
|
||||
pub use nested::Nested;
|
||||
pub use slice::Slice;
|
||||
pub use tag::Tag;
|
||||
pub use traits::{Decodable, Encodable, Tagged};
|
||||
pub use tagged::{TaggedSlice, TaggedValue};
|
||||
pub use traits::{Decodable, Encodable, Taggable};
|
||||
|
||||
|
||||
+13
-13
@@ -1,20 +1,20 @@
|
||||
use crate::{Decoder, Encodable, Encoder, ErrorKind, Header, Length, Result, Tag, tagged_slice::ByteSlice, TaggedSlice};
|
||||
use crate::{Decoder, Encodable, Encoder, ErrorKind, Header, Length, Result, Slice, Tag, TaggedSlice};
|
||||
|
||||
/// Obtain the length of an ASN.1 `SEQUENCE` of [`Encodable`] values when
|
||||
/// serialized as ASN.1 DER, including the `SEQUENCE` tag and length prefix.
|
||||
pub fn encoded_len(/*tag: Tag,*/ encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
let inner_len = encoded_len_inner(encodables)?;
|
||||
// Header::new(tag, inner_len)?.encoded_len() + inner_len
|
||||
Header::new(crate::tag::MEANINGLESS_TAG, inner_len)?.encoded_len() + inner_len
|
||||
pub fn encoded_length(/*tag: Tag,*/ encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
let inner_len = encoded_length_inner(encodables)?;
|
||||
// Header::new(tag, inner_len)?.encoded_length() + inner_len
|
||||
Header::new(crate::tag::MEANINGLESS_TAG, inner_len)?.encoded_length() + inner_len
|
||||
}
|
||||
|
||||
/// Obtain the inner length of a container of [`Encodable`] values
|
||||
/// excluding the tag and length.
|
||||
pub(crate) fn encoded_len_inner(encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
pub(crate) fn encoded_length_inner(encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
encodables
|
||||
.iter()
|
||||
.fold(Ok(Length::zero()), |sum, encodable| {
|
||||
sum + encodable.encoded_len()?
|
||||
sum + encodable.encoded_length()?
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ pub struct Nested<'a> {
|
||||
/// Tag
|
||||
pub(crate) tag: Tag,
|
||||
/// Inner value
|
||||
pub(crate) slice: ByteSlice<'a>,
|
||||
pub(crate) slice: Slice<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Nested<'a> {
|
||||
/// Create a new [`Nested`] from a slice
|
||||
pub fn new(tag: Tag, slice: &'a [u8]) -> Result<Self> {
|
||||
ByteSlice::new(slice)
|
||||
Slice::new(slice)
|
||||
.map(|slice| Self { tag, slice })
|
||||
.map_err(|_| ErrorKind::Length { tag }.into())
|
||||
}
|
||||
@@ -67,19 +67,19 @@ impl AsRef<[u8]> for Nested<'_> {
|
||||
|
||||
impl<'a> From<TaggedSlice<'a>> for Nested<'a> {
|
||||
fn from(tagged_slice: TaggedSlice<'a>) -> Nested<'a> {
|
||||
Self { tag: tagged_slice.tag(), slice: tagged_slice.slice }
|
||||
Self { tag: tagged_slice.tag(), slice: tagged_slice.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Nested<'a>> for TaggedSlice<'a> {
|
||||
fn from(nested: Nested<'a>) -> TaggedSlice<'a> {
|
||||
TaggedSlice { tag: nested.tag(), slice: nested.slice }
|
||||
TaggedSlice { tag: nested.tag(), value: nested.slice }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encodable for Nested<'a> {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
TaggedSlice::from(*self).encoded_len()
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
TaggedSlice::from(*self).encoded_length()
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
use core::convert::TryFrom;
|
||||
use crate::{Length, Result};
|
||||
|
||||
/// Slice of at most `Length::max()` bytes.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Slice<'a> {
|
||||
/// Inner value
|
||||
inner: &'a [u8],
|
||||
|
||||
/// Precomputed `Length` (avoids possible panicking conversions)
|
||||
length: Length,
|
||||
}
|
||||
|
||||
impl<'a> Slice<'a> {
|
||||
/// Create a new [`Slice`], ensuring that the provided `slice` value
|
||||
/// is shorter than `Length::max()`.
|
||||
pub fn new(slice: &'a [u8]) -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: slice,
|
||||
length: Length::try_from(slice.len())?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Borrow the inner byte slice
|
||||
pub fn as_bytes(&self) -> &'a [u8] {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Get the [`Length`] of this [`Slice`]
|
||||
pub fn length(self) -> Length {
|
||||
self.length
|
||||
}
|
||||
|
||||
/// Is this [`Slice`] empty?
|
||||
pub fn is_empty(self) -> bool {
|
||||
self.length() == Length::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Slice<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -5,8 +5,6 @@ use crate::{Decodable, Decoder, Encodable, Encoder, Error, ErrorKind, Length, Re
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub struct Tag(u8);
|
||||
|
||||
pub(crate) const MEANINGLESS_TAG: Tag = Tag(42);
|
||||
|
||||
impl TryFrom<u8> for Tag {
|
||||
type Error = Error;
|
||||
fn try_from(tag_number: u8) -> Result<Self> {
|
||||
@@ -41,7 +39,7 @@ impl Decodable<'_> for Tag {
|
||||
}
|
||||
|
||||
impl Encodable for Tag {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
Ok(1u8.into())
|
||||
}
|
||||
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
// //! Common handling for types backed by byte slices with enforcement of the
|
||||
// //! format-level length limitation of 65_535 bytes.
|
||||
|
||||
use crate::{Decodable, Decoder, Encodable, Encoder, ErrorKind, header::Header, Length, Result, Slice, Tag};
|
||||
|
||||
/// SIMPLE-TLV data object
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct TaggedValue<V> {
|
||||
tag: Tag,
|
||||
value: V,
|
||||
}
|
||||
|
||||
/// Raw SIMPLE-TLV data object: TaggedValue with Slice as value.
|
||||
pub type TaggedSlice<'a> = TaggedValue<Slice<'a>>;
|
||||
|
||||
impl<V> TaggedValue<V>
|
||||
{
|
||||
pub fn new(tag: Tag, value: V) -> Self {
|
||||
Self { tag, value }
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> Tag {
|
||||
self.tag
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, E> TaggedValue<&'a E>
|
||||
where
|
||||
E: Encodable
|
||||
{
|
||||
fn header(&self) -> Result<Header> {
|
||||
Ok(Header {
|
||||
tag: self.tag(),
|
||||
length: self.value.encoded_length()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> Encodable for TaggedValue<&'a E>
|
||||
where
|
||||
E: Encodable
|
||||
{
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
self.header()?.encoded_length()? + self.value.encoded_length()?
|
||||
}
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
self.header()?.encode(encoder)?;
|
||||
encoder.encode(self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TaggedSlice<'a> {
|
||||
|
||||
/// Create a new tagged slice, checking lengths.
|
||||
pub fn from(tag: Tag, slice: &'a [u8]) -> Result<Self> {
|
||||
Slice::new(slice)
|
||||
.map(|slice| Self { tag, value: slice })
|
||||
.map_err(|_| (ErrorKind::InvalidLength).into())
|
||||
}
|
||||
|
||||
/// Borrow the inner byte slice.
|
||||
pub fn as_bytes(&self) -> &'a [u8] {
|
||||
self.value.as_bytes()
|
||||
}
|
||||
|
||||
/// Get the length of the inner byte slice.
|
||||
pub fn length(&self) -> Length {
|
||||
self.value.length()
|
||||
}
|
||||
|
||||
/// Is the inner byte slice empty?
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.value.is_empty()
|
||||
}
|
||||
|
||||
/// Get the SIMPLE-TLV [`Header`] for this [`TaggedSlice`] value
|
||||
fn header(&self) -> Result<Header> {
|
||||
Ok(Header {
|
||||
tag: self.tag(),
|
||||
length: self.length(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Decode nested values, creating a new [`Decoder`] for
|
||||
/// the data contained in the sequence's body and passing it to the provided
|
||||
/// [`FnOnce`].
|
||||
pub fn decode_nested<F, T>(&self, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut Decoder<'a>) -> Result<T>,
|
||||
{
|
||||
let mut nested_decoder = Decoder::new(self.as_bytes());
|
||||
let result = f(&mut nested_decoder)?;
|
||||
nested_decoder.finish(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decodable<'a> for TaggedSlice<'a> {
|
||||
fn decode(decoder: &mut Decoder<'a>) -> Result<TaggedSlice<'a>> {
|
||||
let header = Header::decode(decoder)?;
|
||||
let tag = header.tag;
|
||||
let len = header.length.to_usize();
|
||||
let value = decoder.bytes(len).map_err(|_| ErrorKind::Length { tag })?;
|
||||
Self::from(tag, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encodable for TaggedSlice<'a> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
self.header()?.encoded_length()? + self.length()
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
self.header()?.encode(encoder)?;
|
||||
encoder.bytes(self.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// /// Obtain the length of an ASN.1 `SEQUENCE` of [`Encodable`] values when
|
||||
// /// serialized as ASN.1 DER, including the `SEQUENCE` tag and length prefix.
|
||||
// pub fn encoded_length2(/*tag: Tag,*/ encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
// let inner_len = Length::try_from(encodables)?;
|
||||
// Header::new(crate::tag::MEANINGLESS_TAG, inner_len)?.encoded_length() + inner_len
|
||||
// }
|
||||
|
||||
// /// Obtain the inner length of a container of [`Encodable`] values
|
||||
// /// excluding the tag and length.
|
||||
// pub(crate) fn sum_encoded_lengths(encodables: &[&dyn Encodable]) -> Result<Length> {
|
||||
// encodables
|
||||
// .iter()
|
||||
// .fold(Ok(Length::zero()), |sum, encodable| {
|
||||
// sum + encodable.encoded_length()?
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::convert::TryFrom;
|
||||
use crate::{Encodable, Tag, TaggedSlice};
|
||||
|
||||
#[test]
|
||||
fn encode() {
|
||||
let mut buf = [0u8; 1024];
|
||||
|
||||
let short = TaggedSlice::from(Tag::try_from(0x66).unwrap(), &[1, 2, 3]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
short.encode_to_slice(&mut buf).unwrap(),
|
||||
&[0x66, 0x3, 1, 2, 3]
|
||||
);
|
||||
|
||||
let slice = &[43u8; 256];
|
||||
let long = TaggedSlice::from(Tag::try_from(0x66).unwrap(), slice).unwrap();
|
||||
let encoded = long.encode_to_slice(&mut buf).unwrap();
|
||||
assert_eq!(&encoded[..4], &[0x66, 0xFF, 0x01, 0x00]);
|
||||
assert_eq!(&encoded[4..], slice);
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
// //! Common handling for types backed by byte slices with enforcement of the
|
||||
// //! format-level length limitation of 65_535 bytes.
|
||||
|
||||
use crate::{Decodable, Decoder, Encodable, Encoder, ErrorKind, Header, Length, Nested, Result, Tag};
|
||||
use core::convert::TryFrom;
|
||||
|
||||
/// Byte slice newtype which respects the `Length::max()` limit.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct ByteSlice<'a> {
|
||||
/// Inner value
|
||||
inner: &'a [u8],
|
||||
|
||||
/// Precomputed `Length` (avoids possible panicking conversions)
|
||||
length: Length,
|
||||
}
|
||||
|
||||
impl<'a> ByteSlice<'a> {
|
||||
/// Create a new [`ByteSlice`], ensuring that the provided `slice` value
|
||||
/// is shorter than `Length::max()`.
|
||||
pub fn new(slice: &'a [u8]) -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: slice,
|
||||
length: Length::try_from(slice.len())?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Borrow the inner byte slice
|
||||
pub fn as_bytes(&self) -> &'a [u8] {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Get the [`Length`] of this [`ByteSlice`]
|
||||
pub fn len(self) -> Length {
|
||||
self.length
|
||||
}
|
||||
|
||||
/// Is this [`ByteSlice`] empty?
|
||||
pub fn is_empty(self) -> bool {
|
||||
self.len() == Length::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for ByteSlice<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn TaggedAs(tag: Tag, data: &[u8]) -> impl Tagged<'_> {
|
||||
// struct
|
||||
|
||||
// todo!();
|
||||
// }
|
||||
|
||||
/// SIMPLE-TLV data object
|
||||
///
|
||||
/// TODO(nickray): rename to DataObject or similar (also module)
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct TaggedSlice<'a> {
|
||||
pub(crate) tag: Tag,
|
||||
pub(crate) slice: ByteSlice<'a>,
|
||||
}
|
||||
|
||||
// impl<'a, V: Decodable<'a> + Encodable> TaggedValue<'a, V> {
|
||||
// pub fn new(tag: Tag, value: &'a V) -> Self {
|
||||
// Self { tag, value }
|
||||
// }
|
||||
|
||||
// pub fn tag(&self) -> Tag {
|
||||
// self.tag
|
||||
// }
|
||||
|
||||
// // pub fn value(&self) -> &'a V {
|
||||
// // }
|
||||
|
||||
// }
|
||||
|
||||
impl<'a> TaggedSlice<'a> {
|
||||
/// Create a new tagged slice, checking lengths.
|
||||
pub fn new(tag: Tag, slice: &'a [u8]) -> Result<Self> {
|
||||
ByteSlice::new(slice)
|
||||
.map(|slice| Self { tag, slice })
|
||||
.map_err(|_| (ErrorKind::InvalidLength).into())
|
||||
}
|
||||
|
||||
/// Borrow the inner byte slice.
|
||||
pub fn as_bytes(&self) -> &'a [u8] {
|
||||
self.slice.as_bytes()
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> Tag {
|
||||
self.tag
|
||||
}
|
||||
|
||||
/// Get the length of the inner byte slice.
|
||||
pub fn len(&self) -> Length {
|
||||
self.slice.len()
|
||||
}
|
||||
|
||||
/// Is the inner byte slice empty?
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.slice.is_empty()
|
||||
}
|
||||
|
||||
/// Get the SIMPLE-TLV [`Header`] for this [`TaggedSlice`] value
|
||||
fn header(self) -> Result<Header> {
|
||||
Ok(Header {
|
||||
tag: self.tag,
|
||||
length: self.len(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Attempt to decode this value as nested TaggedSlices, creating a new
|
||||
/// nested [`Decoder`] and calling the provided argument with it.
|
||||
pub fn nested<F, T>(self, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut Decoder<'a>) -> Result<T>,
|
||||
{
|
||||
Nested::from(self).decode_nested(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decodable<'a> for TaggedSlice<'a> {
|
||||
fn decode(decoder: &mut Decoder<'a>) -> Result<TaggedSlice<'a>> {
|
||||
let header = Header::decode(decoder)?;
|
||||
let tag = header.tag;
|
||||
let len = header.length.to_usize();
|
||||
let value = decoder.bytes(len).map_err(|_| ErrorKind::Length { tag })?;
|
||||
Self::new(tag, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encodable for TaggedSlice<'a> {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
self.header()?.encoded_len()? + self.len()
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
self.header()?.encode(encoder)?;
|
||||
encoder.bytes(self.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
// pub struct TaggedValue<V> {
|
||||
// pub(crate) tag: Tag,
|
||||
// pub(crate) value: PhantomData<V>,
|
||||
// }
|
||||
|
||||
// impl<'a, V> Decodable<'a> for TaggedValue<'a, V>
|
||||
// where
|
||||
// V: Decodable<'a> + Encodable,
|
||||
// {
|
||||
// fn decode(decoder: &mut Decoder<'a>) -> Result<Self> {
|
||||
// let tagged_slice: TaggedSlice = decoder.decode()?;
|
||||
// // tagged_slice.tag().assert_eq(self.tag())?;
|
||||
// let value: &'a V = Decoder::new(tagged_slice.as_bytes()).decode()?;
|
||||
// Ok(Self { tag: tagged_slice.tag(), value })
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<'a, V> Encodable for TaggedValue<'a, V>
|
||||
// where
|
||||
// V: Decodable<'a> + Encodable,
|
||||
// {
|
||||
// fn encoded_len(&self) -> Result<Length> {
|
||||
// self.header()?.encoded_len()? + self.len()
|
||||
// }
|
||||
|
||||
// fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
// self.header()?.encode(encoder)?;
|
||||
// encoder.bytes(self.value.as_bytes())
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::convert::TryFrom;
|
||||
use crate::{Encodable, Tag, TaggedSlice};
|
||||
|
||||
#[test]
|
||||
fn encode() {
|
||||
let mut buf = [0u8; 1024];
|
||||
|
||||
let short = TaggedSlice::new(Tag::try_from(0x66).unwrap(), &[1, 2, 3]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
short.encode_to_slice(&mut buf).unwrap(),
|
||||
&[0x66, 0x3, 1, 2, 3]
|
||||
);
|
||||
|
||||
let slice = &[43u8; 256];
|
||||
let long = TaggedSlice::new(Tag::try_from(0x66).unwrap(), slice).unwrap();
|
||||
let encoded = long.encode_to_slice(&mut buf).unwrap();
|
||||
assert_eq!(&encoded[..4], &[0x66, 0xFF, 0x01, 0x00]);
|
||||
assert_eq!(&encoded[4..], slice);
|
||||
}
|
||||
}
|
||||
+28
-63
@@ -2,7 +2,7 @@
|
||||
//! Trait definitions
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use crate::{Decoder, Encoder, Error, Header, Length, nested, Result, Tag, TaggedSlice};
|
||||
use crate::{Decoder, Encoder, Error, header::Header, Length, Result, Tag, TaggedSlice, TaggedValue};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use {
|
||||
@@ -17,7 +17,9 @@ use {
|
||||
crate::{Error, ErrorKind},
|
||||
};
|
||||
|
||||
/// Decoding trait.
|
||||
/// Decoding trait:
|
||||
///
|
||||
/// Decode out of decoder, which essentially is a slice of bytes.
|
||||
pub trait Decodable<'a>: Sized {
|
||||
/// Attempt to decode this message using the provided decoder.
|
||||
fn decode(decoder: &mut Decoder<'a>) -> Result<Self>;
|
||||
@@ -41,10 +43,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Encoding trait.
|
||||
/// Encoding trait
|
||||
///
|
||||
/// Encode into encoder, which essentially is a mutable slice of bytes.
|
||||
///
|
||||
/// Additionally, the encoded length needs to be known without actually encoding.
|
||||
pub trait Encodable {
|
||||
/// Compute the length of this value in bytes when encoded as SIMPLE-TLV
|
||||
fn encoded_len(&self) -> Result<Length>;
|
||||
fn encoded_length(&self) -> Result<Length>;
|
||||
|
||||
/// Encode this value as SIMPLE-TLV using the provided [`Encoder`].
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()>;
|
||||
@@ -62,7 +68,7 @@ pub trait Encodable {
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
|
||||
fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> {
|
||||
let expected_len = self.encoded_len()?.to_usize();
|
||||
let expected_len = self.encoded_length()?.to_usize();
|
||||
let current_len = buf.len();
|
||||
buf.reserve(expected_len);
|
||||
buf.extend(iter::repeat(0).take(expected_len));
|
||||
@@ -98,7 +104,7 @@ pub trait Encodable {
|
||||
#[cfg(feature = "heapless")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
|
||||
fn encode_to_heapless_vec<N: heapless::ArrayLength<u8>>(&self, buf: &mut heapless::Vec<u8, N>) -> Result<Length> {
|
||||
let expected_len = self.encoded_len()?.to_usize();
|
||||
let expected_len = self.encoded_length()?.to_usize();
|
||||
let current_len = buf.len();
|
||||
// TODO(nickray): add a specific error for "Overcapacity" conditional on heapless feature?
|
||||
buf.resize_default(current_len + expected_len).map_err(|_| Error::from(ErrorKind::Overlength))?;
|
||||
@@ -128,49 +134,14 @@ pub trait Encodable {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Taggable: Sized + Encodable {
|
||||
fn tagged(&self, tag: Tag) -> Tagged<'_, Self> {
|
||||
Tagged { tag, encodable: self }
|
||||
/// Types that have can be tagged.
|
||||
pub trait Taggable: Sized {
|
||||
fn tagged(&self, tag: Tag) -> TaggedValue<&Self> {
|
||||
TaggedValue::new(tag, self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<X> Taggable for X where X: Sized + Encodable {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
// pub struct Tagged<'a, E: Encodable> {
|
||||
pub struct Tagged<'a, E> {
|
||||
tag: Tag,
|
||||
encodable: &'a E,
|
||||
}
|
||||
|
||||
impl<'a, E> Tagged<'a, E>
|
||||
where
|
||||
E: Encodable
|
||||
{
|
||||
pub fn from(encodable: &'a E, tag: Tag) -> Self {
|
||||
Tagged { tag, encodable }
|
||||
}
|
||||
|
||||
fn header(&self) -> Result<Header> {
|
||||
Ok(Header {
|
||||
tag: self.tag,
|
||||
length: self.encodable.encoded_len()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> Encodable for Tagged<'a, E>
|
||||
where
|
||||
E: Encodable
|
||||
{
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
self.header()?.encoded_len()? + self.encodable.encoded_len()?
|
||||
}
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
self.header()?.encode(encoder)?;
|
||||
encoder.encode(self.encodable)
|
||||
}
|
||||
}
|
||||
impl<X> Taggable for X where X: Sized {}
|
||||
|
||||
// /// Types with an associated SIMPLE-TLV [`Tag`].
|
||||
// pub trait Tagged {
|
||||
@@ -204,8 +175,9 @@ impl<'a, M> Encodable for M
|
||||
where
|
||||
M: Message<'a>,
|
||||
{
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
self.fields(nested::encoded_len)
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
let value_length = self.fields(|encodables| Length::try_from(encodables))?;
|
||||
Header::new(Self::tag(), value_length)?.encoded_length() + value_length
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
|
||||
@@ -213,22 +185,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
//impl<'a, M> Tagged for M
|
||||
//where
|
||||
// M: Message<'a>,
|
||||
//{
|
||||
// const TAG: Tag = Tag::Sequence;
|
||||
//}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
use crate::{Decodable, Decoder, Encodable, Encoder, Error, Length, Result, Tag, TaggedSlice};
|
||||
use super::{Message, Taggable};
|
||||
use crate::{Decodable, Decoder, Encodable, Encoder, Error, Length, Result, Tag, Taggable, TaggedSlice};
|
||||
use super::Message;
|
||||
|
||||
impl Encodable for [u8; 2] {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
Ok(2u8.into())
|
||||
}
|
||||
|
||||
@@ -239,7 +204,7 @@ mod tests {
|
||||
}
|
||||
|
||||
impl Encodable for [u8; 3] {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
Ok(3u8.into())
|
||||
}
|
||||
|
||||
@@ -250,7 +215,7 @@ mod tests {
|
||||
}
|
||||
|
||||
impl Encodable for [u8; 4] {
|
||||
fn encoded_len(&self) -> Result<Length> {
|
||||
fn encoded_length(&self) -> Result<Length> {
|
||||
Ok(4u8.into())
|
||||
}
|
||||
|
||||
@@ -305,7 +270,7 @@ mod tests {
|
||||
|
||||
fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<S> {
|
||||
tagged_slice.tag().assert_eq(Tag::try_from(0xAA).unwrap())?;
|
||||
tagged_slice.nested(|decoder| {
|
||||
tagged_slice.decode_nested(|decoder| {
|
||||
let x = decoder.decode_tag(Tag::try_from(0x11).unwrap())?;
|
||||
let y = decoder.decode_tag(Tag::try_from(0x22).unwrap())?;
|
||||
let z = decoder.decode_tag(Tag::try_from(0x33).unwrap())?;
|
||||
@@ -368,7 +333,7 @@ mod tests {
|
||||
|
||||
fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<Self> {
|
||||
tagged_slice.tag().assert_eq(Tag::try_from(0xBB).unwrap())?;
|
||||
tagged_slice.nested(|decoder| {
|
||||
tagged_slice.decode_nested(|decoder| {
|
||||
let s = decoder.decode_tag(Tag::try_from(0x01).unwrap())?;
|
||||
let t = decoder.decode_tag(Tag::try_from(0x02).unwrap())?;
|
||||
|
||||
@@ -434,7 +399,7 @@ mod tests {
|
||||
|
||||
fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<Self> {
|
||||
tagged_slice.tag().assert_eq(Tag::try_from(0xCC).unwrap())?;
|
||||
tagged_slice.nested(|decoder| {
|
||||
tagged_slice.decode_nested(|decoder| {
|
||||
let s = decoder.decode()?;
|
||||
let t = decoder.decode_tag(Tag::try_from(0x02).unwrap())?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user