Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update nom to the current version 7 #93

Merged
merged 1 commit into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async-trait = "0.1.41"

[dependencies.lber]
path = "lber"
version = "0.3.0"
version = "0.4.0"

[features]
default = ["sync", "tls"]
Expand Down
7 changes: 3 additions & 4 deletions lber/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
[package]
authors = ["Gregor Reitzenstein <dean4devil@paranoidlabs.org>", "Ivan Nejgebauer <inejge@gmail.com>"]
authors = ["Nadja Reitzenstein <me@dequbed.space>", "Ivan Nejgebauer <inejge@gmail.com>"]
categories = ["encoding", "parsing"]
description = "An ASN.1/BER parser/encoder based on nom"
keywords = ["ASN1", "BER", "nom"]
license = "MIT"
name = "lber"
repository = "https://github.com/inejge/ldap3"
documentation = "https://docs.rs/ldap3"
version = "0.3.0"
version = "0.4.0"

[dependencies]
byteorder = "1"
bytes = "1"
nom = "2"
nom = "7"
7 changes: 2 additions & 5 deletions lber/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
extern crate byteorder;
extern crate bytes;
#[macro_use]
extern crate nom;

pub mod common;
Expand All @@ -10,6 +8,5 @@ pub mod structures;
pub mod universal;
pub mod write;

pub use nom::IResult::*;
pub use nom::{Consumer, ConsumerState, IResult, Input, Move};
pub use parse::Parser;
pub use nom::IResult;
pub use parse::Parser;
157 changes: 50 additions & 107 deletions lber/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,148 +3,91 @@ use common::TagStructure;
use structure::{StructureTag, PL};

use nom;
use nom::Consumer;
use nom::ConsumerState;
use nom::ConsumerState::*;
use nom::IResult;
use nom::Input;
use nom::Input::*;
use nom::InputLength;
use nom::Move;

named!(class_bits<(&[u8], usize), TagClass>,
map_opt!(
take_bits!(u8, 2),
TagClass::from_u8
)
);
use nom::bits::streaming as bits;
use nom::number::streaming as number;
use nom::bytes::streaming::take;
use nom::combinator::map_opt;
use nom::{InputLength, IResult, Needed};
use nom::sequence::tuple;

fn class_bits(i: (&[u8], usize)) -> nom::IResult<(&[u8], usize), TagClass> {
map_opt(bits::take(2usize), TagClass::from_u8)(i)
}

named!(pc_bit<(&[u8], usize), TagStructure>,
map_opt!(
take_bits!(u8, 1),
TagStructure::from_u8
)
);
fn pc_bit(i: (&[u8], usize)) -> nom::IResult<(&[u8], usize), TagStructure> {
map_opt(bits::take(1usize), TagStructure::from_u8)(i)
}

named!(tagnr_bits<(&[u8], usize), u64>,
take_bits!(u64, 5)
);
fn tagnr_bits(i: (&[u8], usize)) -> nom::IResult<(&[u8], usize), u64> {
bits::take(5usize)(i)
}

named!(pub parse_type_header<(TagClass, TagStructure, u64)>, bits!(
do_parse!(
class: class_bits >>
pc: pc_bit >>
tagnr: tagnr_bits >>
((class, pc, tagnr))
)
));
fn parse_type_header(i: &[u8]) -> nom::IResult<&[u8], (TagClass, TagStructure, u64)> {
nom::bits(tuple((class_bits, pc_bit, tagnr_bits)))(i)
}

named!(pub parse_length<u64>,
alt!(
bits!(
do_parse!(
// Short length form
tag_bits!(u8, 1, 0u8) >>
len: take_bits!(u64, 7) >>
(len)
)
)
|
length_value!(
bits!(
do_parse!(
/* // TODO: Fix nom to be able to do this.
*return_error!(nom::ErrorKind::Custom(1),
* not!(tag_bits!(u8, 8, 255u8))
*) >>
*/
// Long length form
tag_bits!(u8, 1, 1u8) >>
len: take_bits!(u8, 7) >>
(len)
)
),
parse_uint
)
)
);
fn parse_length(i: &[u8]) -> nom::IResult<&[u8], u64> {
let (i, len) = number::be_u8(i)?;
if len < 128 {
Ok((i, len as u64))
} else {
let len = len - 128;
let (i, b) = take(len)(i)?;
let (_, len) = parse_uint(b)?;
Ok((i, len))
}
}

/// Extract an unsigned integer value from BER data.
pub fn parse_uint(i: &[u8]) -> nom::IResult<&[u8], u64> {
nom::IResult::Done(i, i.iter().fold(0, |res, &byte| (res << 8) | byte as u64))
Ok((i, i.iter().fold(0, |res, &byte| (res << 8) | byte as u64)))
}

/// Parse raw BER data into a serializable structure.
pub fn parse_tag(i: &[u8]) -> nom::IResult<&[u8], StructureTag> {
let (mut i, ((class, structure, id), len)) = try_parse!(
i,
do_parse!(hdr: parse_type_header >> len: parse_length >> ((hdr, len)))
);
let (mut i, ((class, structure, id), len)) = tuple((parse_type_header, parse_length))(i)?;

let pl: PL = match structure {
TagStructure::Primitive => {
let (j, content) = try_parse!(i, length_data!(value!(len)));
let (j, content) = take(len)(i)?;
i = j;

PL::P(content.to_vec())
}
TagStructure::Constructed => {
let (j, mut content) = try_parse!(i, length_bytes!(value!(len)));
let (j, mut content) = take(len)(i)?;
i = j;

let mut tv: Vec<StructureTag> = Vec::new();
while content.input_len() > 0 {
let pres = try_parse!(content, call!(parse_tag));
content = pres.0;
let res: StructureTag = pres.1;
tv.push(res);
let (j, sub) = parse_tag(content)?;
content = j;
tv.push(sub);
}

PL::C(tv)
}
};

nom::IResult::Done(
Ok((
i,
StructureTag {
class: class,
id: id,
class,
id,
payload: pl,
},
)
))
}

pub struct Parser {
state: ConsumerState<StructureTag, (), Move>,
}
pub struct Parser;

impl Parser {
pub fn new() -> Parser {
Parser {
state: Continue(Move::Consume(0)),
}
}
}

impl<'a> Consumer<&'a [u8], StructureTag, (), Move> for Parser {
fn handle(&mut self, input: Input<&[u8]>) -> &ConsumerState<StructureTag, (), Move> {
use nom::Offset;
match input {
Empty | Eof(None) => self.state(),
Element(data) | Eof(Some(data)) => {
self.state = match parse_tag(data) {
IResult::Incomplete(n) => Continue(Move::Await(n)),
IResult::Error(_) => Error(()),
IResult::Done(i, o) => Done(Move::Consume(data.offset(i)), o),
};

&self.state
}
}
pub fn new() -> Self {
Self
}

fn state(&self) -> &ConsumerState<StructureTag, (), Move> {
&self.state
pub fn parse<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], StructureTag, nom::error::Error<&'a [u8]>> {
if input.is_empty() { return Err(nom::Err::Incomplete(Needed::Unknown)) };
parse_tag(input)
}
}

Expand All @@ -167,7 +110,7 @@ mod test {

let tag = parse_tag(&bytes[..]);

assert_eq!(tag, IResult::Done(&rest_tag[..], result_tag));
assert_eq!(tag, Ok((&rest_tag[..], result_tag)));
}

#[test]
Expand All @@ -188,7 +131,7 @@ mod test {

let tag = parse_tag(&bytes[..]);

assert_eq!(tag, IResult::Done(&rest_tag[..], result_tag));
assert_eq!(tag, Ok((&rest_tag[..], result_tag)));
}

#[test]
Expand Down Expand Up @@ -251,6 +194,6 @@ mod test {
let rest_tag = Vec::new();

let tag = parse_tag(&bytes[..]);
assert_eq!(tag, IResult::Done(&rest_tag[..], result_tag));
assert_eq!(tag, Ok((&rest_tag[..], result_tag)));
}
}
9 changes: 5 additions & 4 deletions lber/src/structures/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use universal;

use std::default;

use byteorder::{BigEndian, WriteBytesExt};

/// Integer value.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Integer {
Expand Down Expand Up @@ -40,8 +38,11 @@ fn i_e_into_structure(id: u64, class: TagClass, inner: i64) -> structure::Struct
}

let mut out: Vec<u8> = Vec::with_capacity(count as usize);

out.write_int::<BigEndian>(inner, count as usize).unwrap();
let repr = inner.to_be_bytes();
if (count as usize) > repr.len() {
out.push(0);
}
out.extend_from_slice(&repr);

structure::StructureTag {
id: id,
Expand Down
16 changes: 9 additions & 7 deletions lber/src/write.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! BER encoding support.
use byteorder::{BigEndian, WriteBytesExt};
use bytes::BytesMut;
use common::{TagClass, TagStructure};
use structure::{StructureTag, PL};
Expand Down Expand Up @@ -75,7 +74,7 @@ fn write_type(w: &mut dyn Write, class: TagClass, structure: TagStructure, id: u
}
}; // let type_byte

let _ = w.write_u8(type_byte);
let _ = w.write(&[type_byte]);

if let Some(mut ext_bytes) = extended_tag {
for _ in 0..ext_bytes.len() - 1 {
Expand All @@ -84,19 +83,19 @@ fn write_type(w: &mut dyn Write, class: TagClass, structure: TagStructure, id: u
// Set the first bit
byte |= 0x80;

let _ = w.write_u8(byte);
let _ = w.write(&[byte]);
}

let byte = ext_bytes.pop().unwrap();
let _ = w.write_u8(byte);
let _ = w.write(&[byte]);
}
}

// Yes I know you could overflow the length in theory. But, do you have 2^64 bytes of memory?
fn write_length(w: &mut dyn Write, length: usize) {
// Short form
if length < 128 {
let _ = w.write_u8(length as u8);
let _ = w.write(&[length as u8]);
}
// Long form
else {
Expand All @@ -108,8 +107,11 @@ fn write_length(w: &mut dyn Write, length: usize) {
len > 0
} {}

let _ = w.write_u8(count | 0x80);
let _ = w.write_uint::<BigEndian>(length as u64, count as usize);
let _ = w.write(&[count | 0x80]);
let repr = &length.to_be_bytes();
let len = repr.len();
let bytes = &repr[(len-(count as usize))..];
let _ = w.write_all(bytes);
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/controls_impl/content_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub enum EntryState {
impl ControlParser for SyncState {
fn parse(val: &[u8]) -> Self {
let mut tags = match parse_tag(val) {
IResult::Done(_, tag) => tag,
IResult::Ok((_, tag)) => tag,
_ => panic!("syncstate: failed to parse tag"),
}
.expect_constructed()
Expand All @@ -122,7 +122,7 @@ impl ControlParser for SyncState {
.expect("syncstate: state")
.as_slice(),
) {
IResult::Done(_, state) => state,
Ok((_, state)) => state,
_ => panic!("syncstate: failed to parse state"),
} {
0 => EntryState::Present,
Expand Down Expand Up @@ -157,7 +157,7 @@ pub struct SyncDone {
impl ControlParser for SyncDone {
fn parse(val: &[u8]) -> Self {
let tags = match parse_tag(val) {
IResult::Done(_, tag) => tag,
Ok((_, tag)) => tag,
_ => panic!("syncdone: failed to parse tag"),
}
.expect_constructed()
Expand Down Expand Up @@ -229,7 +229,7 @@ pub fn parse_syncinfo(entry: ResultEntry) -> SyncInfo {
Some(tag) if tag.id == 1 => {
let syncinfo_val =
match parse_tag(tag.expect_primitive().expect("octet string").as_ref()) {
IResult::Done(_, tag) => tag,
Ok((_, tag)) => tag,
_ => panic!("syncinfo: error parsing value"),
};
return match syncinfo_val {
Expand Down