pub mod cyclonedx;
pub mod sbom;
use sha2::Digest;
use std::path::PathBuf;
pub use sbom::BillOfMaterials;
use crate::KonarrError;
use crate::models::{Component, ComponentVersion, Dependencies, Projects};
pub trait BomParser {
fn parse(data: &[u8]) -> Result<BillOfMaterials, crate::KonarrError>;
fn parse_with_name(
data: &[u8],
name: impl Into<String>,
) -> Result<BillOfMaterials, crate::KonarrError> {
let name = name.into();
match name.as_str() {
"cyclonedx-1.5" | "cdx-1.5" => crate::bom::cyclonedx::spec_v1_5::Bom::parse(data),
"cyclonedx-1.6" | "cdx-1.6" => crate::bom::cyclonedx::spec_v1_6::Bom::parse(data),
_ => Err(KonarrError::ParseSBOM(format!(
"SBOM Format unknow: {}",
name
))),
}
}
fn parse_path(path: PathBuf) -> Result<BillOfMaterials, crate::KonarrError> {
let data = std::fs::read(path.clone())?;
Self::parse(&data)
}
fn parse_path_with_name(
path: PathBuf,
name: impl Into<String>,
) -> Result<BillOfMaterials, crate::KonarrError> {
let name = name.into();
match name.as_str() {
"cyclonedx-1.5" => crate::bom::cyclonedx::spec_v1_5::Bom::parse_path(path),
"cyclonedx-1.6" | "cdx-1.6" => crate::bom::cyclonedx::spec_v1_6::Bom::parse_path(path),
_ => Err(KonarrError::ParseSBOM(format!(
"SBOM Format unknow: {}",
name
))),
}
}
}
pub trait BillOfMaterialsBuilder {
fn new() -> Self;
fn add_project(&mut self, project: &Projects) -> Result<(), crate::KonarrError>;
fn add_dependency(&mut self, dep: &Dependencies) -> Result<(), crate::KonarrError> {
self.add_component(&dep.component_id.data, &dep.component_version_id.data)
}
fn add_dependencies(
&mut self,
dependencies: &Vec<Dependencies>,
) -> Result<(), crate::KonarrError> {
for dep in dependencies.iter() {
self.add_dependency(dep)?;
}
Ok(())
}
#[allow(unused_variables)]
fn add_component(
&mut self,
component: &Component,
version: &ComponentVersion,
) -> Result<(), crate::KonarrError> {
Ok(())
}
fn add_components(&mut self, component: &Vec<Component>) -> Result<(), crate::KonarrError> {
for comp in component.iter() {
self.add_component(comp, &ComponentVersion::default())?;
}
Ok(())
}
fn output(&self) -> Result<Vec<u8>, crate::KonarrError>;
}
#[allow(non_camel_case_types)]
pub enum Parsers {
CycloneDX_v1_5,
CycloneDX_v1_6,
}
impl BomParser for Parsers {
fn parse(data: &[u8]) -> Result<BillOfMaterials, crate::KonarrError> {
let mut hasher = sha2::Sha256::new();
hasher.update(data);
let sha = hasher.finalize();
if let Ok(mut sbom) = cyclonedx::CycloneDx::parse(data) {
sbom.sha = hex::encode(sha);
Ok(sbom)
} else {
Err(KonarrError::ParseSBOM("Failed to parse SBOM".to_string()))
}
}
}
#[allow(non_camel_case_types)]
pub enum Builders {
CycloneDX_v1_6,
}