mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 13:20:42 +00:00
Add Facet trait and optimize functions. Begin to structure payload information. TODO Payload string parsing FromStr
This commit is contained in:
parent
6d6cc575a4
commit
13f41862bb
4 changed files with 192 additions and 53 deletions
|
|
@ -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
46
src/digest/mod.rs
Normal 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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -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
49
src/payload/mod.rs
Normal 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,
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue