Skip to content
This repository was archived by the owner on Apr 9, 2023. It is now read-only.

Upgrade to nom 6 #20

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ publish = false

[dependencies]
petgraph = "^0.5"
nom = "^3"
nom = "6.0"
lazy_static = "^1.4"
fnv = "^1"

Expand Down
183 changes: 58 additions & 125 deletions src/fdo_magic/ruleset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,130 +2,69 @@ use std::str;
use petgraph::prelude::*;
use fnv::FnvHashMap;
use crate::MIME;
use nom::{
IResult,
bytes::complete::{is_not, tag, take, take_while},
character::is_digit,
combinator::{map, map_res, opt},
multi::many0,
number::complete::be_u16,
sequence::{delimited, preceded, terminated, tuple},
};

// Below functions from https://github.com/badboy/iso8601/blob/master/src/helper.rs
// but modified to be safe and provide defaults
pub fn to_string(s: &[u8]) -> std::result::Result<&str, std::str::Utf8Error> {
str::from_utf8(s)
}
pub fn to_u32(s: std::result::Result<&str, std::str::Utf8Error>, def: u32) -> u32 {

match s {
Ok (t) => {str::FromStr::from_str(t).unwrap_or(def)},
Err (_) => def
}
}

pub fn buf_to_u32(s: &[u8], def: u32) -> u32 {
to_u32(to_string(s), def)
}

// Initial mime string
// Format: [priority: mime]
named!(mime<&str>,
map_res!(
delimited!(
delimited!(
char!('['),
is_not!(":"),
char!(':')
),
is_not!("]"), // the mime
tag!("]\n")
),
str::from_utf8
)
);
// Singular magic ruleset
fn magic_rules(input: &[u8]) -> IResult<&[u8], super::MagicRule> {
let int_or = |default| map(
take_while(is_digit),
move |digits| str::from_utf8(digits).unwrap().parse().unwrap_or(default)
);

// Indent levels sub-parser for magic_rules
// Default value 0
named!(magic_rules_indent_level<u32>,
do_parse!(
ret: take_until!(">") >>
(buf_to_u32(ret, 0))
)
);
let (input, (indent_level, start_off, val_len)) = tuple((
terminated(int_or(0), tag(">")),
terminated(int_or(0), tag("=")),
be_u16,
))(input)?;

// Start offset sub-parser for magic_rules
named!(magic_rules_start_off<u32>,
do_parse!(
ret: take_until!("=") >>
(buf_to_u32(ret, 0))
)
);
let (input, (val, mask, word_len, region_len)) = terminated(
tuple((
take(val_len),
opt(preceded(tag("&"), take(val_len))),
opt(preceded(tag("~"), int_or(1))),
opt(preceded(tag("+"), int_or(0))),
)),
tag("\n")
)(input)?;

// Singular magic ruleset
named!(magic_rules<super::MagicRule>,
do_parse!(
peek!(is_a!("012345689>")) >>
_indent_level: magic_rules_indent_level >>
tag!(">") >>
_start_off: magic_rules_start_off >>
tag!("=") >>
_val_len: u16!(nom::Endianness::Big) >> // length of value
_val: do_parse!(
ret: take!(_val_len) >>
(ret.iter().map(|&x| x).collect())
) >> // value

_mask: opt!(
do_parse!(
char!('&') >>
ret: take!(_val_len) >> // mask (default 0xFF)
(ret.iter().map(|&x| x).collect())
)
) >>

// word size (default 1)
_word_len: opt!(
do_parse!(
tag!("~") >>
ret: take_until!("+") >>
(buf_to_u32(ret, 1))
)
) >>

// length of region in file to check (default 1)
_region_len: opt!(
do_parse!(
tag!("+") >>
ret: take_until!("\n") >>
(buf_to_u32(ret, 0))
)
) >>

take_until_and_consume!("\n") >>

(super::MagicRule{
indent_level: _indent_level,
start_off: _start_off,
val: _val,
val_len: _val_len,
mask: _mask,
word_len: _word_len.unwrap_or(1),
region_len: _region_len.unwrap_or(0)
})
)

);

/// Singular magic entry
named!(magic_entry<(MIME, Vec<super::MagicRule>)>,
do_parse!(
_mime: do_parse!(ret: mime >> (ret.to_string())) >>
_rules: many0!(magic_rules) >> (_mime, _rules)
)
);
Ok((input, super::MagicRule {
indent_level,
start_off,
val: val.to_vec(),
val_len,
mask: mask.map(Vec::from),
word_len: word_len.unwrap_or(1),
region_len: region_len.unwrap_or(0),
}))
}

/// Converts a magic file given as a &[u8] array
/// to a vector of MagicEntry structs
named!(from_u8_to_tuple_vec<Vec<(MIME, Vec<super::MagicRule>)>>,
do_parse!(
tag!("MIME-Magic\0\n") >>
ret: many0!(magic_entry) >>
(ret)
)
);
fn ruleset(input: &[u8]) -> IResult<&[u8], Vec<(MIME, Vec<super::MagicRule>)>> {
// Parse the MIME type from "[priority: mime]"
let mime = map(map_res(
terminated(
delimited(
delimited(tag("["), is_not(":"), tag(":")), // priority
is_not("]"), // mime
tag("]")
),
tag("\n"),
),
str::from_utf8),
str::to_string);

let magic_entry = tuple((mime, many0(magic_rules)));
preceded(tag("MIME-Magic\0\n"), many0(magic_entry))(input)
}

fn gen_graph(magic_rules: Vec<super::MagicRule>) -> DiGraph<super::MagicRule, u32>
{
Expand Down Expand Up @@ -159,15 +98,9 @@ fn gen_graph(magic_rules: Vec<super::MagicRule>) -> DiGraph<super::MagicRule, u3
}

pub fn from_u8(b: &[u8]) -> Result<FnvHashMap<MIME, DiGraph<super::MagicRule, u32>>, String> {
let tuplevec = from_u8_to_tuple_vec(b).to_result().map_err(|e| e.to_string())?;
let mut res = FnvHashMap::<MIME, DiGraph<super::MagicRule, u32>>::default();

for x in tuplevec {
res.insert(x.0, gen_graph(x.1));
}

let tuplevec = ruleset(b).map_err(|e| e.to_string())?.1;
let res = tuplevec.into_iter().map(|x| (x.0, gen_graph(x.1))).collect();
Ok(res)

}

/// Loads the given magic file and outputs a vector of MagicEntry structs
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

#![allow(unused_doc_comments)]
#![allow(dead_code)]
#[macro_use] extern crate nom;
#[macro_use] extern crate lazy_static;

use petgraph::prelude::*;
Expand Down