Add Facet trait and optimize functions. Begin to structure payload information. TODO Payload string parsing FromStr

This commit is contained in:
Till Wegmueller 2020-05-25 16:13:22 +02:00
parent 6d6cc575a4
commit 13f41862bb
4 changed files with 192 additions and 53 deletions

View file

@ -5,12 +5,38 @@
use regex::{RegexSet, Regex}; use regex::{RegexSet, Regex};
use std::collections::HashSet; use std::collections::HashSet;
use std::error;
use std::fmt;
use std::fs::File as OsFile; use std::fs::File as OsFile;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use failure::Error; use failure::Error;
use crate::payload::Payload;
use std::clone::Clone;
trait FacetedAction {
// Add a facet to the action if the facet is already present the function returns false.
fn add_facet(&mut self, facet: Facet) -> bool;
// Remove a facet from the action.
fn remove_facet(&mut self, facet: Facet) -> bool;
}
#[derive(Debug)]
pub struct Action {
kind: ActionKind,
payload_reference: String,
properties: Vec<Property>,
facets: HashSet<Facet>,
}
impl FacetedAction for Action {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Dir { pub struct Dir {
@ -23,9 +49,19 @@ pub struct Dir {
pub facets: HashSet<Facet>, pub facets: HashSet<Facet>,
} }
impl FacetedAction for Dir {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct File { pub struct File {
pub payload: String, pub payload: Payload,
pub path: String, pub path: String,
pub group: String, pub group: String,
pub owner: String, pub owner: String,
@ -39,6 +75,16 @@ pub struct File {
pub facets: HashSet<Facet>, pub facets: HashSet<Facet>,
} }
impl FacetedAction for File {
fn add_facet(&mut self, facet: Facet) -> bool {
return self.facets.insert(facet)
}
fn remove_facet(&mut self, facet: Facet) -> bool {
return self.facets.remove(&facet)
}
}
#[derive(Hash, Eq, PartialEq, Debug, Default)] #[derive(Hash, Eq, PartialEq, Debug, Default)]
pub struct Facet { pub struct Facet {
pub name: String, pub name: String,
@ -75,6 +121,7 @@ impl Manifest {
} }
} }
#[derive(Debug)]
enum ActionKind { enum ActionKind {
Attr, Attr,
Dir, Dir,
@ -165,6 +212,28 @@ fn handle_manifest_line(manifest: &mut Manifest, line: &str, line_nr: usize) ->
Ok(()) Ok(())
} }
fn add_facet_to_action<T: FacetedAction>(action: &mut T, facet_string: String, line: String, line_nr: usize) -> Result<(), ManifestError> {
let facet_key = match facet_string.find(".") {
Some(idx) => {
facet_string.clone().split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("separation dot not found but string contains facet.")})?
};
let value = match facet_string.find("=") {
Some(idx) => {
facet_string.clone().split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("no value present for facet")})?
};
if !action.add_facet(Facet{name: facet_key, value}) {
return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("double declaration of facet")})?
}
Ok(())
}
fn determine_action_kind(line: &str) -> ActionKind { fn determine_action_kind(line: &str) -> ActionKind {
let mut act = String::new(); let mut act = String::new();
for c in line.trim_start().chars() { for c in line.trim_start().chars() {
@ -245,35 +314,21 @@ fn parse_file_action(line: String, line_nr: usize) -> Result<File, Error> {
let key_val_string = clean_string_value(&cap[full_cap_idx]); let key_val_string = clean_string_value(&cap[full_cap_idx]);
if key_val_string.contains("facet.") { if key_val_string.contains("facet.") {
let facet_key = match key_val_string.find(".") { match add_facet_to_action(&mut act, key_val_string, line, line_nr) {
Some(idx) => { Ok(_) => continue,
key_val_string.clone().split_off(idx+1) Err(e) => return Err(e)?,
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("separation dot not found but string contains facet.")})?
};
let value = match key_val_string.find("=") {
Some(idx) => {
key_val_string.clone().split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("no value present for facet")})?
};
if !act.facets.insert(Facet{name: facet_key, value}) {
return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("double declaration of facet")})?
} }
} else {
let mut key = key_val_string.clone();
let value = match key.find("=") {
Some(idx) => {
key.split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("no value present for facet")})?
};
key = key.replace("=", "");
act.properties.push(Property{key, value});
} }
let mut key = key_val_string.clone();
let value = match key.find("=") {
Some(idx) => {
key.split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("no value present for facet")})?
};
key = key.replace("=", "");
act.properties.push(Property{key, value});
} }
} }
} }
@ -300,31 +355,18 @@ fn parse_dir_action(line: String, line_nr: usize) -> Result<Dir, Error> {
match &cap[key_cap_idx] { match &cap[key_cap_idx] {
"path" => act.path = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "path" => act.path = clean_string_value(&cap[val_cap_idx]),
"owner" => act.owner = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "owner" => act.owner = clean_string_value(&cap[val_cap_idx]),
"group" => act.group = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "group" => act.group = clean_string_value(&cap[val_cap_idx]),
"mode" => act.mode = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "mode" => act.mode = clean_string_value(&cap[val_cap_idx]),
"revert-tag" => act.revert_tag = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "revert-tag" => act.revert_tag = clean_string_value(&cap[val_cap_idx]),
"salvage-from" => act.salvage_from = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), "salvage-from" => act.salvage_from = clean_string_value(&cap[val_cap_idx]),
_ => { _ => {
let key_val_string = String::from(&cap[full_cap_idx]).trim_end().replace(&['"', '\\'][..], ""); let key_val_string = clean_string_value(&cap[full_cap_idx]);
if key_val_string.contains("facet.") { if key_val_string.contains("facet.") {
let key = match key_val_string.find(".") { match add_facet_to_action(&mut act, key_val_string, line, line_nr) {
Some(idx) => { Ok(_) => continue,
key_val_string.clone().split_off(idx+1) Err(e) => return Err(e)?,
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("separation dot not found but string contains facet.")})?
};
let value = match key_val_string.find("=") {
Some(idx) => {
key_val_string.clone().split_off(idx+1)
},
None => return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("no value present for facet")})?
};
if !act.facets.insert(Facet{name: key, value }) {
return Err(ManifestError::InvalidAction{action: line, line: line_nr, message: String::from("double declaration of facet")})?
} }
} }
} }

46
src/digest/mod.rs Normal file
View file

@ -0,0 +1,46 @@
// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of the
// MPL was not distributed with this file, You can
// obtain one at https://mozilla.org/MPL/2.0/.
#[derive(Debug)]
pub enum DigestAlgorithm {
SHA1, //Default, sadly
SHA256, //sha256t
SHA512, //sha512t
SHA512Half, //sha512t_256
SHA3256, // Sha3 version of sha256t
SHA3512Half, // Sha3 version of sha512t_256
SHA3512, // Sha3 version of sha512t
}
impl Default for DigestAlgorithm {
fn default() -> Self { DigestAlgorithm::SHA1 }
}
#[derive(Debug)]
pub enum DigestSource {
GzipCompressed,
GNUElf,
GNUElfUnsigned,
UncompressedFile
}
impl Default for DigestSource {
fn default() -> Self { DigestSource::UncompressedFile }
}
#[derive(Debug, Default)]
pub struct Digest {
hash: String,
algorithm: DigestAlgorithm,
source: DigestSource,
}
#[derive(Debug, Fail)]
pub enum DigestError {
#[fail(display = "hashing algorithm {} is not known by this library", algorithm)]
UnknownAlgorithm {
algorithm: String,
},
}

View file

@ -4,6 +4,8 @@
// obtain one at https://mozilla.org/MPL/2.0/. // obtain one at https://mozilla.org/MPL/2.0/.
mod actions; mod actions;
mod digest;
mod payload;
#[macro_use] extern crate failure; #[macro_use] extern crate failure;

49
src/payload/mod.rs Normal file
View file

@ -0,0 +1,49 @@
// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of the
// MPL was not distributed with this file, You can
// obtain one at https://mozilla.org/MPL/2.0/.
use crate::digest::Digest;
#[derive(Debug)]
pub enum PayloadCompressionAlgorithm {
Gzip,
LZ4
}
impl Default for PayloadCompressionAlgorithm {
fn default() -> Self { PayloadCompressionAlgorithm::Gzip }
}
#[derive(Debug)]
pub enum PayloadBits {
Independent,
Bits32,
Bits64
}
impl Default for PayloadBits {
fn default() -> Self { PayloadBits::Independent }
}
#[derive(Debug)]
pub enum PayloadArchitecture {
NOARCH,
I386,
SPARC,
ARM,
RISCV
}
impl Default for PayloadArchitecture {
fn default() -> Self { PayloadArchitecture::NOARCH }
}
#[derive(Debug, Default)]
pub struct Payload {
primary_identifier: Digest,
additional_identifiers: Vec<Digest>,
compression_algorithm: PayloadCompressionAlgorithm,
bitness: PayloadBits,
architecture: PayloadArchitecture,
}