Skip to content

Commit

Permalink
Move serialized types to their own crate
Browse files Browse the repository at this point in the history
  • Loading branch information
stephaneyfx committed Oct 5, 2020
1 parent 8c9ee4f commit 4479d0f
Show file tree
Hide file tree
Showing 14 changed files with 274 additions and 157 deletions.
9 changes: 8 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions cargo-geiger-serde/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "Apache-2.0/MIT"
name = "cargo-geiger-serde"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
semver = "0.10.0"
serde = { version = "1.0.116", features = ["derive"] }
url = { version = "2.1.1", features = ["serde"] }
26 changes: 19 additions & 7 deletions cargo-geiger-serde/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
//! cargo-geiger-serde ☢
//! ========
//!
//! This crate provides definitions to serialize the unsafety report.
#![forbid(unsafe_code)]
#![forbid(warnings)]

mod package_id;
mod report;
mod source;

pub use package_id::PackageId;
pub use report::{
Count, CounterBlock, DependencyKind, PackageInfo, QuickReportEntry, QuickSafetyReport,
ReportEntry, SafetyReport, UnsafeInfo,
};
pub use source::Source;

14 changes: 14 additions & 0 deletions cargo-geiger-serde/src/package_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::Source;
use semver::Version;
use serde::{Deserialize, Serialize};

/// Identifies a package in the dependency tree
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct PackageId {
/// Package name
pub name: String,
/// Package version
pub version: Version,
/// Package source (e.g. repository, crate registry)
pub source: Source,
}
166 changes: 166 additions & 0 deletions cargo-geiger-serde/src/report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use crate::PackageId;
use serde::{Deserialize, Serialize};
use std::{
ops::{Add, AddAssign},
path::PathBuf,
};

/// Package dependency information
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct PackageInfo {
pub id: PackageId,
pub dependencies: Vec<PackageId>,
pub dev_dependencies: Vec<PackageId>,
pub build_dependencies: Vec<PackageId>,
}

impl PackageInfo {
pub fn new(id: PackageId) -> Self {
PackageInfo {
id,
dependencies: Vec::new(),
dev_dependencies: Vec::new(),
build_dependencies: Vec::new(),
}
}

pub fn push_dependency(&mut self, dep: PackageId, kind: DependencyKind) {
match kind {
DependencyKind::Normal => self.dependencies.push(dep),
DependencyKind::Development => self.dev_dependencies.push(dep),
DependencyKind::Build => self.build_dependencies.push(dep),
}
}
}

/// Entry of the report generated from scanning for packages that forbid the use of `unsafe`
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct QuickReportEntry {
pub package: PackageInfo,
/// Whether this package forbids the use of `unsafe`
pub forbids_unsafe: bool,
}

/// Report generated from scanning for packages that forbid the use of `unsafe`
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct QuickSafetyReport {
/// Packages that were scanned successfully
pub packages: Vec<QuickReportEntry>,
/// Packages that were not scanned successfully
pub packages_without_metrics: Vec<PackageId>,
}

/// Entry of the report generated from scanning for the use of `unsafe`
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct ReportEntry {
pub package: PackageInfo,
/// Unsafety scan results
pub unsafety: UnsafeInfo,
}

/// Report generated from scanning for the use of `unsafe`
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct SafetyReport {
pub packages: Vec<ReportEntry>,
pub packages_without_metrics: Vec<PackageId>,
pub used_but_not_scanned_files: Vec<PathBuf>,
}

/// Unsafety usage in a package
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct UnsafeInfo {
/// Unsafe usage statistics for code used by the project
pub used: CounterBlock,
/// Unsafe usage statistics for code not used by the project
pub unused: CounterBlock,
/// Whether this package forbids the use of `unsafe`
pub forbids_unsafe: bool,
}

/// Kind of dependency for a package
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum DependencyKind {
/// Dependency in the `[dependencies]` section of `Cargo.toml`
Normal,
/// Dependency in the `[dev-dependencies]` section of `Cargo.toml`
Development,
/// Dependency in the `[build-dependencies]` section of `Cargo.toml`
Build,
}

/// Statistics about the use of `unsafe`
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct Count {
/// Number of safe items
pub safe: u64,
/// Number of unsafe items
pub unsafe_: u64,
}

impl Count {
/// Increments the safe or unsafe counter by 1
pub fn count(&mut self, is_unsafe: bool) {
if is_unsafe {
self.unsafe_ += 1;
} else {
self.safe += 1;
}
}
}

impl Add for Count {
type Output = Count;

fn add(self, other: Count) -> Count {
Count {
safe: self.safe + other.safe,
unsafe_: self.unsafe_ + other.unsafe_,
}
}
}

impl AddAssign for Count {
fn add_assign(&mut self, rhs: Count) {
*self = self.clone() + rhs;
}
}

/// Unsafe usage metrics collection.
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct CounterBlock {
pub functions: Count,
pub exprs: Count,
pub item_impls: Count,
pub item_traits: Count,
pub methods: Count,
}

impl CounterBlock {
pub fn has_unsafe(&self) -> bool {
self.functions.unsafe_ > 0
|| self.exprs.unsafe_ > 0
|| self.item_impls.unsafe_ > 0
|| self.item_traits.unsafe_ > 0
|| self.methods.unsafe_ > 0
}
}

impl Add for CounterBlock {
type Output = CounterBlock;

fn add(self, other: CounterBlock) -> CounterBlock {
CounterBlock {
functions: self.functions + other.functions,
exprs: self.exprs + other.exprs,
item_impls: self.item_impls + other.item_impls,
item_traits: self.item_traits + other.item_traits,
methods: self.methods + other.methods,
}
}
}

impl AddAssign for CounterBlock {
fn add_assign(&mut self, rhs: Self) {
*self = self.clone() + rhs;
}
}
18 changes: 18 additions & 0 deletions cargo-geiger-serde/src/source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
use url::Url;

/// Source of a package (where it is fetched from)
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub enum Source {
Git {
url: Url,
rev: String,
},
Registry {
name: String,
url: Url,
},
Path(Url),
LocalRegistry(Url),
Directory(Url),
}
1 change: 1 addition & 0 deletions cargo-geiger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ maintenance = { status = "experimental" }

[dependencies]
cargo = "0.47.0"
cargo-geiger-serde = { path = "../cargo-geiger-serde", version = "0.1.0" }
cargo-platform = "0.1.1"
colored = "2.0.0"
console = "0.11.3"
Expand Down
2 changes: 1 addition & 1 deletion cargo-geiger/src/format/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::scan::{unsafe_stats, GeigerContext};
use crate::tree::TextTreeLine;

use cargo::core::package::PackageSet;
use geiger::{Count, CounterBlock};
use cargo_geiger_serde::{Count, CounterBlock};
use std::collections::HashSet;
use std::path::PathBuf;

Expand Down
48 changes: 40 additions & 8 deletions cargo-geiger/src/scan.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod default;
mod find;
mod forbid;
mod report;

use crate::args::Args;
use crate::format::print::PrintConfig;
Expand All @@ -10,11 +9,11 @@ use crate::rs_file::RsFileMetricsWrapper;

use default::scan_unsafe;
use forbid::scan_forbid_unsafe;
use report::{PackageInfo, UnsafeInfo};

use cargo::core::{PackageId, PackageSet, Workspace};
use cargo::core::dependency::DepKind;
use cargo::{CliResult, Config};
use geiger::CounterBlock;
use cargo_geiger_serde::{CounterBlock, DependencyKind, PackageInfo, UnsafeInfo};
use petgraph::visit::EdgeRef;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
Expand Down Expand Up @@ -165,14 +164,14 @@ fn package_metrics<'a>(
std::iter::from_fn(move || {
let i = indices.pop()?;
let id = graph.graph[i].id;
let mut package = PackageInfo::new(id);
let mut package = PackageInfo::new(from_cargo_package_id(id));
for edge in graph.graph.edges(i) {
let dep_index = edge.target();
if visited.insert(dep_index) {
indices.push(dep_index);
}
let dep = graph.graph[dep_index].id;
package.push_dependency(dep, *edge.weight());
let dep = from_cargo_package_id(graph.graph[dep_index].id);
package.push_dependency(dep, from_cargo_dependency_kind(*edge.weight()));
}
match geiger_context.pack_id_to_metrics.get(&id) {
Some(m) => Some((package, Some(m))),
Expand All @@ -184,16 +183,49 @@ fn package_metrics<'a>(
})
}

fn from_cargo_package_id(id: PackageId) -> cargo_geiger_serde::PackageId {
let source = id.source_id();
let source_url = source.url().clone();
let source = if source.is_git() {
cargo_geiger_serde::Source::Git {
url: source_url,
rev: source.precise().expect("Git revision should be known").to_string(),
}
} else if source.is_path() {
cargo_geiger_serde::Source::Path(source_url)
} else if source.is_registry() {
cargo_geiger_serde::Source::Registry {
name: source.display_registry_name(),
url: source_url,
}
} else {
panic!("Unsupported source type: {:?}", source)
};
cargo_geiger_serde::PackageId {
name: id.name().to_string(),
version: id.version().clone(),
source,
}
}

fn from_cargo_dependency_kind(kind: DepKind) -> DependencyKind {
match kind {
DepKind::Normal => DependencyKind::Normal,
DepKind::Development => DependencyKind::Development,
DepKind::Build => DependencyKind::Build,
}
}

#[cfg(test)]
mod scan_tests {
use super::*;

use crate::{
rs_file::RsFileMetricsWrapper,
scan::{report::UnsafeInfo, PackageMetrics},
scan::PackageMetrics,
};

use geiger::Count;
use cargo_geiger_serde::{Count, UnsafeInfo};
use std::{collections::HashSet, path::PathBuf};

#[test]
Expand Down
Loading

0 comments on commit 4479d0f

Please sign in to comment.