From d9b72ffa5485f3c253da22f09ff0a7090de7aa37 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 9 Apr 2022 11:27:14 +0300 Subject: refactor: rename Checksum to Label Label is a clearer and more accurate name for the type now that it is not just a checksum. Also, serialize a Label in tests, rather than using string literals. This is more correct, and we'll be changing serialization later. Sponsored-by: author --- src/checksummer.rs | 49 ------------------------------------------------- src/chunk.rs | 6 +++--- src/chunker.rs | 4 ++-- src/chunkid.rs | 6 +++--- src/chunkmeta.rs | 20 ++++++++++---------- src/cipher.rs | 6 +++--- src/client.rs | 4 ++-- src/index.rs | 18 +++++++++--------- src/label.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/server.rs | 4 ++-- 11 files changed, 84 insertions(+), 84 deletions(-) delete mode 100644 src/checksummer.rs create mode 100644 src/label.rs diff --git a/src/checksummer.rs b/src/checksummer.rs deleted file mode 100644 index 6d7303b..0000000 --- a/src/checksummer.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Compute checksums of data. -//! -//! De-duplication of backed up data in Obnam relies on cryptographic -//! checksums. They are implemented in this module. Note that Obnam -//! does not aim to make these algorithms configurable, so only a very -//! small number of carefully chosen algorithms are supported here. - -use sha2::{Digest, Sha256}; -use std::fmt; - -/// A checksum of some data. -#[derive(Debug, Clone)] -pub enum Checksum { - /// An arbitrary, literal string. - Literal(String), - - /// A SHA256 checksum. - Sha256(String), -} - -impl Checksum { - /// Construct a literal string. - pub fn literal(s: &str) -> Self { - Self::Literal(s.to_string()) - } - - /// Compute a SHA256 checksum for a block of data. - pub fn sha256(data: &[u8]) -> Self { - let mut hasher = Sha256::new(); - hasher.update(data); - let hash = hasher.finalize(); - Self::Sha256(format!("{:x}", hash)) - } - - /// Create a `Checksum` from a known, previously computed hash. - pub fn sha256_from_str_unchecked(hash: &str) -> Self { - Self::Sha256(hash.to_string()) - } -} - -impl fmt::Display for Checksum { - /// Format a checksum for display. - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Literal(s) => write!(f, "{}", s), - Self::Sha256(hash) => write!(f, "{}", hash), - } - } -} diff --git a/src/chunk.rs b/src/chunk.rs index df16a98..4f604b9 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -1,8 +1,8 @@ //! Chunks of data. -use crate::checksummer::Checksum; use crate::chunkid::ChunkId; use crate::chunkmeta::ChunkMeta; +use crate::label::Label; use serde::{Deserialize, Serialize}; use std::default::Default; @@ -97,7 +97,7 @@ impl GenerationChunk { let json: String = serde_json::to_string(self).map_err(GenerationChunkError::JsonGenerate)?; let bytes = json.as_bytes().to_vec(); - let checksum = Checksum::sha256(&bytes); + let checksum = Label::sha256(&bytes); let meta = ChunkMeta::new(&checksum); Ok(DataChunk::new(bytes, meta)) } @@ -185,7 +185,7 @@ impl ClientTrust { pub fn to_data_chunk(&self) -> Result { let json: String = serde_json::to_string(self).map_err(ClientTrustError::JsonGenerate)?; let bytes = json.as_bytes().to_vec(); - let checksum = Checksum::literal("client-trust"); + let checksum = Label::literal("client-trust"); let meta = ChunkMeta::new(&checksum); Ok(DataChunk::new(bytes, meta)) } diff --git a/src/chunker.rs b/src/chunker.rs index 7954621..2394230 100644 --- a/src/chunker.rs +++ b/src/chunker.rs @@ -1,8 +1,8 @@ //! Split file data into chunks. -use crate::checksummer::Checksum; use crate::chunk::DataChunk; use crate::chunkmeta::ChunkMeta; +use crate::label::Label; use std::io::prelude::*; use std::path::{Path, PathBuf}; @@ -54,7 +54,7 @@ impl FileChunks { } let buffer = &self.buf.as_slice()[..used]; - let hash = Checksum::sha256(buffer); + let hash = Label::sha256(buffer); let meta = ChunkMeta::new(&hash); let chunk = DataChunk::new(buffer.to_vec(), meta); Ok(Some(chunk)) diff --git a/src/chunkid.rs b/src/chunkid.rs index 3534627..50fc3d3 100644 --- a/src/chunkid.rs +++ b/src/chunkid.rs @@ -3,7 +3,7 @@ //! Chunk identifiers are chosen by the server. Each chunk has a //! unique identifier, which isn't based on the contents of the chunk. -use crate::checksummer::Checksum; +use crate::label::Label; use rusqlite::types::ToSqlOutput; use rusqlite::ToSql; use serde::{Deserialize, Serialize}; @@ -53,8 +53,8 @@ impl ChunkId { } /// Return the SHA256 checksum of the identifier. - pub fn sha256(&self) -> Checksum { - Checksum::sha256(self.id.as_bytes()) + pub fn sha256(&self) -> Label { + Label::sha256(self.id.as_bytes()) } } diff --git a/src/chunkmeta.rs b/src/chunkmeta.rs index 33c1070..1f591c6 100644 --- a/src/chunkmeta.rs +++ b/src/chunkmeta.rs @@ -1,6 +1,6 @@ //! Metadata about a chunk. -use crate::checksummer::Checksum; +use crate::label::Label; use serde::{Deserialize, Serialize}; use std::default::Default; use std::str::FromStr; @@ -37,9 +37,9 @@ impl ChunkMeta { /// Create a new data chunk. /// /// Data chunks are not for generations. - pub fn new(checksum: &Checksum) -> Self { + pub fn new(label: &Label) -> Self { ChunkMeta { - label: checksum.to_string(), + label: label.to_string(), } } @@ -79,20 +79,20 @@ impl FromStr for ChunkMeta { #[cfg(test)] mod test { - use super::{Checksum, ChunkMeta}; + use super::{ChunkMeta, Label}; #[test] fn new_creates_data_chunk() { - let sum = Checksum::sha256_from_str_unchecked("abcdef"); + let sum = Label::sha256(b"abcdef"); let meta = ChunkMeta::new(&sum); - assert_eq!(meta.label(), "abcdef"); + assert_eq!(meta.label(), &format!("{}", sum)); } #[test] fn new_generation_creates_generation_chunk() { - let sum = Checksum::sha256_from_str_unchecked("abcdef"); + let sum = Label::sha256(b"abcdef"); let meta = ChunkMeta::new(&sum); - assert_eq!(meta.label(), "abcdef"); + assert_eq!(meta.label(), &format!("{}", sum)); } #[test] @@ -113,7 +113,7 @@ mod test { #[test] fn generation_json_roundtrip() { - let sum = Checksum::sha256_from_str_unchecked("abcdef"); + let sum = Label::sha256(b"abcdef"); let meta = ChunkMeta::new(&sum); let json = serde_json::to_string(&meta).unwrap(); let meta2 = serde_json::from_str(&json).unwrap(); @@ -122,7 +122,7 @@ mod test { #[test] fn data_json_roundtrip() { - let sum = Checksum::sha256_from_str_unchecked("abcdef"); + let sum = Label::sha256(b"abcdef"); let meta = ChunkMeta::new(&sum); let json = meta.to_json_vec(); let meta2 = serde_json::from_slice(&json).unwrap(); diff --git a/src/cipher.rs b/src/cipher.rs index ee7fb8f..7bd2e84 100644 --- a/src/cipher.rs +++ b/src/cipher.rs @@ -191,15 +191,15 @@ impl Nonce { #[cfg(test)] mod test { - use crate::checksummer::Checksum; use crate::chunk::DataChunk; use crate::chunkmeta::ChunkMeta; use crate::cipher::{CipherEngine, CipherError, CHUNK_V1, NONCE_SIZE}; + use crate::label::Label; use crate::passwords::Passwords; #[test] fn metadata_as_aad() { - let sum = Checksum::sha256_from_str_unchecked("dummy-checksum"); + let sum = Label::sha256(b"dummy data"); let meta = ChunkMeta::new(&sum); let meta_as_aad = meta.to_json_vec(); let chunk = DataChunk::new("hello".as_bytes().to_vec(), meta); @@ -212,7 +212,7 @@ mod test { #[test] fn round_trip() { - let sum = Checksum::sha256_from_str_unchecked("dummy-checksum"); + let sum = Label::sha256(b"dummy data"); let meta = ChunkMeta::new(&sum); let chunk = DataChunk::new("hello".as_bytes().to_vec(), meta); let pass = Passwords::new("secret"); diff --git a/src/client.rs b/src/client.rs index 563921d..d8bf262 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,5 @@ //! Client to the Obnam server HTTP API. -use crate::checksummer::Checksum; use crate::chunk::{ ClientTrust, ClientTrustError, DataChunk, GenerationChunk, GenerationChunkError, }; @@ -10,6 +9,7 @@ use crate::cipher::{CipherEngine, CipherError}; use crate::config::{ClientConfig, ClientConfigError}; use crate::generation::{FinishedGeneration, GenId, LocalGeneration, LocalGenerationError}; use crate::genlist::GenerationList; +use crate::label::Label; use log::{debug, error, info}; use reqwest::header::HeaderMap; @@ -196,7 +196,7 @@ impl BackupClient { } async fn find_client_trusts(&self) -> Result, ClientError> { - let label = format!("{}", Checksum::literal("client-trust")); + let label = format!("{}", Label::literal("client-trust")); let body = match self.get("", &[("label", &label)]).await { Ok((_, body)) => body, Err(err) => return Err(err), diff --git a/src/index.rs b/src/index.rs index 11f3480..5310a44 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,8 +1,8 @@ //! An on-disk index of chunks for the server. -use crate::checksummer::Checksum; use crate::chunkid::ChunkId; use crate::chunkmeta::ChunkMeta; +use crate::label::Label; use rusqlite::Connection; use std::path::Path; @@ -74,7 +74,7 @@ impl Index { #[cfg(test)] mod test { - use crate::checksummer::Checksum; + use super::Label; use super::{ChunkId, ChunkMeta, Index}; use std::path::Path; @@ -87,20 +87,20 @@ mod test { #[test] fn remembers_inserted() { let id: ChunkId = "id001".parse().unwrap(); - let sum = Checksum::sha256_from_str_unchecked("abc"); + let sum = Label::sha256(b"abc"); let meta = ChunkMeta::new(&sum); let dir = tempdir().unwrap(); let mut idx = new_index(dir.path()); idx.insert_meta(id.clone(), meta.clone()).unwrap(); assert_eq!(idx.get_meta(&id).unwrap(), meta); - let ids = idx.find_by_label("abc").unwrap(); + let ids = idx.find_by_label(&format!("{}", sum)).unwrap(); assert_eq!(ids, vec![id]); } #[test] fn does_not_find_uninserted() { let id: ChunkId = "id001".parse().unwrap(); - let sum = Checksum::sha256_from_str_unchecked("abc"); + let sum = Label::sha256(b"abc"); let meta = ChunkMeta::new(&sum); let dir = tempdir().unwrap(); let mut idx = new_index(dir.path()); @@ -111,19 +111,19 @@ mod test { #[test] fn removes_inserted() { let id: ChunkId = "id001".parse().unwrap(); - let sum = Checksum::sha256_from_str_unchecked("abc"); + let sum = Label::sha256(b"abc"); let meta = ChunkMeta::new(&sum); let dir = tempdir().unwrap(); let mut idx = new_index(dir.path()); idx.insert_meta(id.clone(), meta).unwrap(); idx.remove_meta(&id).unwrap(); - let ids: Vec = idx.find_by_label("abc").unwrap(); + let ids: Vec = idx.find_by_label(&format!("{}", sum)).unwrap(); assert_eq!(ids, vec![]); } } mod sql { - use super::{Checksum, IndexError}; + use super::{IndexError, Label}; use crate::chunkid::ChunkId; use crate::chunkmeta::ChunkMeta; use log::error; @@ -216,7 +216,7 @@ mod sql { fn row_to_meta(row: &Row) -> rusqlite::Result { let hash: String = row.get("label")?; - let sha256 = Checksum::sha256_from_str_unchecked(&hash); + let sha256 = Label::sha256_from_str_unchecked(&hash); Ok(ChunkMeta::new(&sha256)) } diff --git a/src/label.rs b/src/label.rs new file mode 100644 index 0000000..7ee55d1 --- /dev/null +++ b/src/label.rs @@ -0,0 +1,49 @@ +//! A chunk label. +//! +//! De-duplication of backed up data in Obnam relies on cryptographic +//! checksums. They are implemented in this module. Note that Obnam +//! does not aim to make these algorithms configurable, so only a very +//! small number of carefully chosen algorithms are supported here. + +use sha2::{Digest, Sha256}; +use std::fmt; + +/// A checksum of some data. +#[derive(Debug, Clone)] +pub enum Label { + /// An arbitrary, literal string. + Literal(String), + + /// A SHA256 checksum. + Sha256(String), +} + +impl Label { + /// Construct a literal string. + pub fn literal(s: &str) -> Self { + Self::Literal(s.to_string()) + } + + /// Compute a SHA256 checksum for a block of data. + pub fn sha256(data: &[u8]) -> Self { + let mut hasher = Sha256::new(); + hasher.update(data); + let hash = hasher.finalize(); + Self::Sha256(format!("{:x}", hash)) + } + + /// Create a `Checksum` from a known, previously computed hash. + pub fn sha256_from_str_unchecked(hash: &str) -> Self { + Self::Sha256(hash.to_string()) + } +} + +impl fmt::Display for Label { + /// Format a checksum for display. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Literal(s) => write!(f, "{}", s), + Self::Sha256(hash) => write!(f, "{}", hash), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index a0a53c7..fbbea15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ pub mod accumulated_time; pub mod backup_progress; pub mod backup_reason; pub mod backup_run; -pub mod checksummer; pub mod chunk; pub mod chunker; pub mod chunkid; @@ -29,6 +28,7 @@ pub mod genlist; pub mod genmeta; pub mod index; pub mod indexedstore; +pub mod label; pub mod passwords; pub mod performance; pub mod policy; diff --git a/src/server.rs b/src/server.rs index 31a03fc..6b688d6 100644 --- a/src/server.rs +++ b/src/server.rs @@ -141,7 +141,7 @@ impl SearchHits { #[cfg(test)] mod test_search_hits { use super::{ChunkMeta, SearchHits}; - use crate::checksummer::Checksum; + use crate::label::Label; #[test] fn no_search_hits() { @@ -152,7 +152,7 @@ mod test_search_hits { #[test] fn one_search_hit() { let id = "abc".parse().unwrap(); - let sum = Checksum::sha256_from_str_unchecked("123"); + let sum = Label::sha256(b"123"); let meta = ChunkMeta::new(&sum); let mut hits = SearchHits::default(); hits.insert(id, meta); -- cgit v1.2.1