diff --git a/src/actions/mod.rs b/src/actions/mod.rs index 8042723..f753e79 100644 --- a/src/actions/mod.rs +++ b/src/actions/mod.rs @@ -5,12 +5,38 @@ use regex::{RegexSet, Regex}; use std::collections::HashSet; -use std::error; -use std::fmt; use std::fs::File as OsFile; use std::io::BufRead; use std::io::BufReader; 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, + facets: HashSet, +} + +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)] pub struct Dir { @@ -23,9 +49,19 @@ pub struct Dir { pub facets: HashSet, } +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)] pub struct File { - pub payload: String, + pub payload: Payload, pub path: String, pub group: String, pub owner: String, @@ -39,6 +75,16 @@ pub struct File { pub facets: HashSet, } +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)] pub struct Facet { pub name: String, @@ -75,6 +121,7 @@ impl Manifest { } } +#[derive(Debug)] enum ActionKind { Attr, Dir, @@ -165,6 +212,28 @@ fn handle_manifest_line(manifest: &mut Manifest, line: &str, line_nr: usize) -> Ok(()) } +fn add_facet_to_action(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 { let mut act = String::new(); for c in line.trim_start().chars() { @@ -245,35 +314,21 @@ fn parse_file_action(line: String, line_nr: usize) -> Result { let key_val_string = clean_string_value(&cap[full_cap_idx]); if key_val_string.contains("facet.") { - let facet_key = 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("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")})? + match add_facet_to_action(&mut act, key_val_string, line, line_nr) { + Ok(_) => continue, + Err(e) => return Err(e)?, } - - } 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 { match &cap[key_cap_idx] { - "path" => act.path = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), - "owner" => act.owner = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), - "group" => act.group = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), - "mode" => act.mode = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), - "revert-tag" => act.revert_tag = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), - "salvage-from" => act.salvage_from = String::from(&cap[val_cap_idx]).trim_end().replace(&['"', '\\'][..], ""), + "path" => act.path = clean_string_value(&cap[val_cap_idx]), + "owner" => act.owner = clean_string_value(&cap[val_cap_idx]), + "group" => act.group = clean_string_value(&cap[val_cap_idx]), + "mode" => act.mode = clean_string_value(&cap[val_cap_idx]), + "revert-tag" => act.revert_tag = clean_string_value(&cap[val_cap_idx]), + "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.") { - let key = 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("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")})? + match add_facet_to_action(&mut act, key_val_string, line, line_nr) { + Ok(_) => continue, + Err(e) => return Err(e)?, } } } diff --git a/src/digest/mod.rs b/src/digest/mod.rs new file mode 100644 index 0000000..dc02a7a --- /dev/null +++ b/src/digest/mod.rs @@ -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, + }, +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b979192..b527d29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,8 @@ // obtain one at https://mozilla.org/MPL/2.0/. mod actions; +mod digest; +mod payload; #[macro_use] extern crate failure; diff --git a/src/payload/mod.rs b/src/payload/mod.rs new file mode 100644 index 0000000..04350d5 --- /dev/null +++ b/src/payload/mod.rs @@ -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, + compression_algorithm: PayloadCompressionAlgorithm, + bitness: PayloadBits, + architecture: PayloadArchitecture, +} \ No newline at end of file