Skip to content

Commit

Permalink
feat(asn1-parser): add id to every asn1 entity
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBestTvarynka committed Dec 2, 2023
1 parent f9912ad commit d5c262c
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 72 deletions.
14 changes: 14 additions & 0 deletions crates/asn1-parser/src/asn1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ impl Asn1Entity for Asn1Type<'_> {
Asn1Type::Null(n) => n.tag(),
}
}

fn id(&self) -> u64 {
match self {
Asn1Type::OctetString(octet) => octet.id(),
Asn1Type::Utf8String(utf8) => utf8.id(),
Asn1Type::Sequence(sequence) => sequence.id(),
Asn1Type::BitString(bit) => bit.id(),
Asn1Type::BmpString(bmp) => bmp.id(),
Asn1Type::Bool(boolean) => boolean.id(),
Asn1Type::ExplicitTag(e) => e.id(),
Asn1Type::ApplicationTag(a) => a.id(),
Asn1Type::Null(n) => n.id(),
}
}
}

impl<'data> Asn1Decoder<'data> for Asn1Type<'data> {
Expand Down
31 changes: 22 additions & 9 deletions crates/asn1-parser/src/constructors/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{Asn1, Asn1Decoder, Asn1Encoder, Asn1Entity, Asn1Result, Asn1Type, Ta
/// In ASN.1, an ordered list of elements (or components) comprises a SEQUENCE.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Sequence<'data> {
id: u64,
fields: Vec<Asn1<'data>>,
}

Expand All @@ -21,8 +22,8 @@ pub type OwnedSequence = Sequence<'static>;
impl Sequence<'_> {
pub const TAG: Tag = Tag(0x30);

pub fn new(fields: Vec<Asn1>) -> Sequence {
Sequence { fields }
pub fn new(id: u64, fields: Vec<Asn1>) -> Sequence {
Sequence { id, fields }
}

/// Retuens [Sequence] fields
Expand All @@ -33,6 +34,7 @@ impl Sequence<'_> {
/// Returns owned version of the [Sequence]
pub fn to_owned(&self) -> OwnedSequence {
Sequence {
id: self.id,
fields: self.fields.iter().map(|f| f.to_owned()).collect(),
}
}
Expand All @@ -45,16 +47,20 @@ impl Sequence<'_> {
}
}

impl<'data> From<Vec<Asn1<'data>>> for Sequence<'data> {
fn from(fields: Vec<Asn1<'data>>) -> Self {
Self { fields }
}
}
// impl<'data> From<Vec<Asn1<'data>>> for Sequence<'data> {
// fn from(fields: Vec<Asn1<'data>>) -> Self {
// Self { id: 0, fields }
// }
// }

impl Asn1Entity for Sequence<'_> {
fn tag(&self) -> Tag {
Self::TAG
}

fn id(&self) -> u64 {
self.id
}
}

impl Asn1Encoder for Sequence<'_> {
Expand Down Expand Up @@ -91,7 +97,10 @@ impl<'data> Asn1Decoder<'data> for Sequence<'data> {
fields.push(Asn1Type::decode_asn1(reader)?);
}

Ok(Self { fields })
Ok(Self {
fields,
id: reader.next_id(),
})
}

fn decode_asn1(reader: &mut Reader<'data>) -> Asn1Result<Asn1<'data>> {
Expand All @@ -115,7 +124,10 @@ impl<'data> Asn1Decoder<'data> for Sequence<'data> {
length: len_range,
data: data_range,
},
asn1_type: Box::new(Asn1Type::Sequence(Sequence { fields })),
asn1_type: Box::new(Asn1Type::Sequence(Sequence {
fields,
id: reader.next_id(),
})),
})
}
}
Expand Down Expand Up @@ -148,6 +160,7 @@ mod tests {
data: 2..29,
},
asn1_type: Box::new(Asn1Type::Sequence(Sequence {
id: 0,
fields: vec![
Asn1 {
raw_data: RawAsn1EntityData {
Expand Down
55 changes: 38 additions & 17 deletions crates/asn1-parser/src/generic_types/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{Asn1, Asn1Decoder, Asn1Encoder, Asn1Entity, Asn1Result, Asn1Type, Er
/// The ASN.1 BOOLEAN type has two possible values: TRUE and FALSE.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Bool {
id: u64,
flag: bool,
}

Expand All @@ -21,30 +22,47 @@ impl Bool {
pub fn value(&self) -> bool {
self.flag
}
}

impl From<bool> for Bool {
fn from(flag: bool) -> Self {
Self { flag }
pub fn from_id_and_byte(id: u64, byte: u8) -> Asn1Result<Bool> {
Ok(Bool {
id,
flag: if byte == 0 {
false
} else if byte == 0xff {
true
} else {
return Err(Error::from("Invalid bool value"));
},
})
}
}

impl TryFrom<u8> for Bool {
type Error = Error;

fn try_from(flag: u8) -> Result<Self, Self::Error> {
match flag {
0 => Ok(Self { flag: false }),
0xff => Ok(Self { flag: true }),
_ => Err(Error::from("Invalid bool value")),
}
}
}
// impl From<bool> for Bool {
// fn from(flag: bool) -> Self {
// Self { flag }
// }
// }

// impl TryFrom<u8> for Bool {
// type Error = Error;
//
// fn try_from(flag: u8) -> Result<Self, Self::Error> {
// match flag {
// 0 => Ok(Self { flag: false }),
// 0xff => Ok(Self { flag: true }),
// _ => Err(Error::from("Invalid bool value")),
// }
// }
// }

impl Asn1Entity for Bool {
fn tag(&self) -> Tag {
Self::TAG
}

fn id(&self) -> u64 {
self.id
}
}

impl<'data> Asn1Decoder<'data> for Bool {
Expand All @@ -61,7 +79,7 @@ impl<'data> Asn1Decoder<'data> for Bool {
return Err(Error::from("Bool length must be equal to 1"));
}

reader.read_byte()?.try_into()
Self::from_id_and_byte(reader.next_id(), reader.read_byte()?)
}

fn decode_asn1(reader: &mut Reader<'data>) -> Asn1Result<Asn1<'data>> {
Expand All @@ -83,7 +101,10 @@ impl<'data> Asn1Decoder<'data> for Bool {
length: len_range,
data: data_range,
},
asn1_type: Box::new(Asn1Type::Bool(data[0].try_into()?)),
asn1_type: Box::new(Asn1Type::Bool(Self::from_id_and_byte(
reader.next_id(),
reader.read_byte()?,
)?)),
})
}
}
Expand Down
12 changes: 9 additions & 3 deletions crates/asn1-parser/src/generic_types/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use crate::{Asn1, Asn1Decoder, Asn1Encoder, Asn1Entity, Asn1Result, Asn1Type, Er
/// For example, it can be used to mark a currently empty space.
/// The NULL type has only one possible value, also called NULL.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Null;
pub struct Null {
id: u64,
}

impl Null {
pub const TAG: Tag = Tag(5);
Expand All @@ -22,6 +24,10 @@ impl Asn1Entity for Null {
fn tag(&self) -> Tag {
Self::TAG
}

fn id(&self) -> u64 {
self.id
}
}

impl<'data> Asn1Decoder<'data> for Null {
Expand All @@ -38,7 +44,7 @@ impl<'data> Asn1Decoder<'data> for Null {
return Err(Error::from("Bool length must be equal to 0"));
}

Ok(Self)
Ok(Self { id: reader.next_id() })
}

fn decode_asn1(reader: &mut Reader<'data>) -> Asn1Result<Asn1<'data>> {
Expand All @@ -60,7 +66,7 @@ impl<'data> Asn1Decoder<'data> for Null {
length: len_range,
data: data_range,
},
asn1_type: Box::new(Asn1Type::Null(Self)),
asn1_type: Box::new(Asn1Type::Null(Self { id: reader.next_id() })),
})
}
}
Expand Down
5 changes: 4 additions & 1 deletion crates/asn1-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub trait Asn1Decoder<'data>: Sized {
/// Decodes the asn1 entity using provided Reader.
fn decode_asn1(reader: &mut Reader<'data>) -> Asn1Result<Asn1<'data>>;

/// Decodes the asn1 entity using provided Reader.
/// Decodes the asn1 entity using provided buffer.
fn decode_asn1_buff(buff: &'data [u8]) -> Asn1Result<Asn1<'data>> {
Self::decode_asn1(&mut Reader::new(buff))
}
Expand All @@ -68,4 +68,7 @@ pub trait Asn1Encoder {
pub trait Asn1Entity {
/// Returns asn1 tag of the entity
fn tag(&self) -> Tag;

/// Returns a unique asn1 node id
fn id(&self) -> u64;
}
7 changes: 7 additions & 0 deletions crates/asn1-parser/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@ use crate::{Asn1Result, Error};

#[derive(Debug)]
pub struct Reader<'data> {
next_node_id: u64,
position: usize,
inner: &'data [u8],
}

impl<'data> Reader<'data> {
pub fn new(data: &'data [u8]) -> Self {
Self {
next_node_id: 0,
position: 0,
inner: data,
}
}

pub fn next_id(&mut self) -> u64 {
self.next_node_id += 1;
self.next_node_id
}

pub fn position(&self) -> usize {
self.position
}
Expand Down
25 changes: 18 additions & 7 deletions crates/asn1-parser/src/string/bit_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{Asn1, Asn1Decoder, Asn1Encoder, Asn1Entity, Asn1Result, Asn1Type, Er
/// A BIT STRING value doesn't need to be an even multiple of eight bits.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BitString<'data> {
id: u64,
bits: Cow<'data, [u8]>,
}

Expand All @@ -32,7 +33,7 @@ impl BitString<'_> {
}

/// Creates a new [BitString] from amount of bits and actual bits buffer
pub fn from_raw_vec(bits_amount: usize, mut bits: Vec<u8>) -> Asn1Result<Self> {
pub fn from_raw_vec(id: u64, bits_amount: usize, mut bits: Vec<u8>) -> Asn1Result<Self> {
let all_bits_amount = bits.len() * 8;

if bits_amount > all_bits_amount {
Expand All @@ -46,28 +47,36 @@ impl BitString<'_> {
let unused_bits: u8 = (all_bits_amount - bits_amount).try_into()?;
bits.insert(0, unused_bits);

Ok(Self { bits: Cow::Owned(bits) })
Ok(Self {
id,
bits: Cow::Owned(bits),
})
}

/// Returns owned version of the [BitString]
pub fn to_owned(&self) -> OwnedBitString {
OwnedBitString {
id: self.id,
bits: self.bits.to_vec().into(),
}
}
}

// we assume here that firs vector byte contains amount of unused bytes
impl From<Vec<u8>> for BitString<'_> {
fn from(bits: Vec<u8>) -> Self {
Self { bits: Cow::Owned(bits) }
}
}
// impl From<Vec<u8>> for BitString<'_> {
// fn from(bits: Vec<u8>) -> Self {
// Self { bits: Cow::Owned(bits) }
// }
// }

impl Asn1Entity for BitString<'_> {
fn tag(&self) -> Tag {
Self::TAG
}

fn id(&self) -> u64 {
self.id
}
}

impl<'data> Asn1Decoder<'data> for BitString<'data> {
Expand All @@ -83,6 +92,7 @@ impl<'data> Asn1Decoder<'data> for BitString<'data> {
let data = reader.read(len)?;

Ok(Self {
id: reader.next_id(),
bits: Cow::Borrowed(data),
})
}
Expand All @@ -103,6 +113,7 @@ impl<'data> Asn1Decoder<'data> for BitString<'data> {
data: data_range,
},
asn1_type: Box::new(Asn1Type::BitString(Self {
id: reader.next_id(),
bits: Cow::Borrowed(data),
})),
})
Expand Down
Loading

0 comments on commit d5c262c

Please sign in to comment.