use std::collections::HashMap;
use std::slice;
use crate::{Algorithm, DigestValue};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HashResult {
digests: Vec<(Algorithm, DigestValue)>,
}
impl HashResult {
pub(crate) fn from_digest_map(
algorithms: &[Algorithm],
mut digests: HashMap<Algorithm, DigestValue>,
) -> Self {
let mut ordered = Vec::with_capacity(digests.len());
for algorithm in unique_algorithms(algorithms) {
if let Some(digest) = digests.remove(&algorithm) {
ordered.push((algorithm, digest));
}
}
Self { digests: ordered }
}
pub fn len(&self) -> usize {
self.digests.len()
}
pub fn is_empty(&self) -> bool {
self.digests.is_empty()
}
pub fn get(&self, algorithm: Algorithm) -> Option<&DigestValue> {
self.digests
.iter()
.find_map(|(candidate, digest)| (*candidate == algorithm).then_some(digest))
}
pub fn standard(&self, algorithm: Algorithm) -> Option<&str> {
self.get(algorithm).map(DigestValue::standard)
}
pub fn hex(&self, algorithm: Algorithm) -> Option<String> {
self.get(algorithm).map(DigestValue::hex)
}
pub fn raw(&self, algorithm: Algorithm) -> Option<&[u8]> {
self.get(algorithm).map(DigestValue::raw)
}
pub fn iter(&self) -> impl Iterator<Item = (Algorithm, &DigestValue)> {
self.digests
.iter()
.map(|(algorithm, digest)| (*algorithm, digest))
}
pub fn as_slice(&self) -> &[(Algorithm, DigestValue)] {
&self.digests
}
pub fn into_vec(self) -> Vec<(Algorithm, DigestValue)> {
self.digests
}
}
impl IntoIterator for HashResult {
type Item = (Algorithm, DigestValue);
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.digests.into_iter()
}
}
impl<'a> IntoIterator for &'a HashResult {
type Item = (Algorithm, &'a DigestValue);
type IntoIter = HashResultIter<'a>;
fn into_iter(self) -> Self::IntoIter {
HashResultIter {
inner: self.digests.iter(),
}
}
}
pub struct HashResultIter<'a> {
inner: slice::Iter<'a, (Algorithm, DigestValue)>,
}
impl<'a> Iterator for HashResultIter<'a> {
type Item = (Algorithm, &'a DigestValue);
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|(algorithm, digest)| (*algorithm, digest))
}
}
pub(crate) fn unique_algorithms(algorithms: &[Algorithm]) -> Vec<Algorithm> {
let mut unique = Vec::with_capacity(algorithms.len());
for algorithm in algorithms {
if !unique.contains(algorithm) {
unique.push(*algorithm);
}
}
unique
}