this repo has no description
at main 153 lines 4.6 kB view raw
1use humansize::{format_size, DECIMAL}; 2use std::{cmp::Ordering, fmt::Display}; 3 4use super::{ 5 parser::DiffPackage, 6 versioning::{Version, VersionComponent, VersionList}, 7}; 8 9#[derive(Default, Debug, PartialEq, Eq)] 10pub enum DiffType { 11 Added, 12 Removed, 13 Changed, 14 15 #[default] 16 Unknown, 17} 18 19#[derive(Debug)] 20pub struct Package { 21 pub size_delta: SizeDelta, 22 pub diff_type: DiffType, 23 24 pub versions_before: VersionList, 25 pub versions_after: VersionList, 26} 27 28#[derive(Debug)] 29pub struct SizeDelta(pub i64); 30 31impl DiffType { 32 pub fn from_versions(before: &[String], after: &[String]) -> DiffType { 33 match (before.is_empty(), after.is_empty()) { 34 (true, false) => DiffType::Added, 35 (false, true) => DiffType::Removed, 36 (false, false) => DiffType::Changed, 37 (true, true) => DiffType::Unknown, // should be unreachable but I'm not sure 38 } 39 } 40} 41 42impl Display for Package { 43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 44 match self.diff_type { 45 DiffType::Added => { 46 write!(f, "{}", self.versions_after)?; 47 } 48 DiffType::Removed => { 49 write!(f, "{}", self.versions_before)?; 50 } 51 DiffType::Changed => { 52 write!(f, "{} -> {}", self.versions_before, self.versions_after)?; 53 } 54 DiffType::Unknown => unreachable!(), 55 } 56 57 Ok(()) 58 } 59} 60 61impl From<DiffPackage> for Package { 62 fn from(diff: DiffPackage) -> Self { 63 let diff_type = DiffType::from_versions(&diff.versions_before, &diff.versions_after); 64 65 let (parsed_before, parsed_after) = match diff_type { 66 DiffType::Added => handle_diff_added(&diff.versions_after), 67 DiffType::Removed => handle_diff_removed(&diff.versions_before), 68 DiffType::Changed => handle_diff_changed(&diff.versions_before, &diff.versions_after), 69 DiffType::Unknown => unreachable!(), 70 }; 71 72 Package { 73 size_delta: diff.size_delta.into(), 74 versions_before: parsed_before, 75 versions_after: parsed_after, 76 diff_type, 77 } 78 } 79} 80 81fn handle_diff_added(versions_after: &[String]) -> (VersionList, VersionList) { 82 let after = to_version_list(versions_after, Ordering::Greater); 83 (VersionList::new(), after) 84} 85 86fn handle_diff_removed(versions_before: &[String]) -> (VersionList, VersionList) { 87 let before = to_version_list(versions_before, Ordering::Less); 88 (before, VersionList::new()) 89} 90 91fn to_version_list(versions: &[String], order: Ordering) -> VersionList { 92 let mut version_list = VersionList::new(); 93 94 for before in versions { 95 let parts_before = before.split('.').map(String::from); 96 let mut version = Version::new(); 97 for part in parts_before { 98 version.push(VersionComponent::new(part, order)); 99 } 100 version_list.push(version); 101 } 102 103 version_list 104} 105 106fn handle_diff_changed( 107 versions_before: &[String], 108 versions_after: &[String], 109) -> (VersionList, VersionList) { 110 let mut parsed_before = VersionList::new(); 111 let mut parsed_after = VersionList::new(); 112 113 for (before, after) in versions_before.iter().zip(versions_after.iter()) { 114 let mut parts_before = before.split('.').map(String::from).collect::<Vec<_>>(); 115 let mut parts_after = after.split('.').map(String::from).collect::<Vec<_>>(); 116 117 let max_len = parts_before.len().max(parts_after.len()); 118 parts_before.resize(max_len, String::new()); 119 parts_after.resize(max_len, String::new()); 120 121 let mut ordering = Ordering::Equal; 122 123 let mut line_before = Version::new(); 124 let mut line_after = Version::new(); 125 126 for (b, a) in parts_before.into_iter().zip(parts_after.into_iter()) { 127 if ordering == Ordering::Equal { 128 ordering = b.cmp(&a); 129 } 130 line_before.push(VersionComponent::new(b, ordering)); 131 line_after.push(VersionComponent::new(a, ordering.reverse())); 132 } 133 134 parsed_before.push(line_before); 135 parsed_after.push(line_after); 136 } 137 138 (parsed_before, parsed_after) 139} 140 141impl std::fmt::Display for SizeDelta { 142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 143 let sign = if self.0 >= 0 { "+" } else { "-" }; 144 let size: u64 = self.0.abs().try_into().unwrap_or(0); 145 write!(f, "{sign}{}", format_size(size, DECIMAL)) 146 } 147} 148 149impl From<i64> for SizeDelta { 150 fn from(size: i64) -> Self { 151 SizeDelta(size) 152 } 153}