summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chunkmeta.rs6
-rw-r--r--src/client.rs2
-rw-r--r--src/index.rs6
-rw-r--r--src/label.rs59
4 files changed, 55 insertions, 18 deletions
diff --git a/src/chunkmeta.rs b/src/chunkmeta.rs
index 1f591c6..fe7ef4c 100644
--- a/src/chunkmeta.rs
+++ b/src/chunkmeta.rs
@@ -39,7 +39,7 @@ impl ChunkMeta {
/// Data chunks are not for generations.
pub fn new(label: &Label) -> Self {
ChunkMeta {
- label: label.to_string(),
+ label: label.serialize(),
}
}
@@ -85,14 +85,14 @@ mod test {
fn new_creates_data_chunk() {
let sum = Label::sha256(b"abcdef");
let meta = ChunkMeta::new(&sum);
- assert_eq!(meta.label(), &format!("{}", sum));
+ assert_eq!(meta.label(), sum.serialize());
}
#[test]
fn new_generation_creates_generation_chunk() {
let sum = Label::sha256(b"abcdef");
let meta = ChunkMeta::new(&sum);
- assert_eq!(meta.label(), &format!("{}", sum));
+ assert_eq!(meta.label(), sum.serialize());
}
#[test]
diff --git a/src/client.rs b/src/client.rs
index d8bf262..bed5f1e 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -196,7 +196,7 @@ impl BackupClient {
}
async fn find_client_trusts(&self) -> Result<Vec<ChunkId>, ClientError> {
- let label = format!("{}", Label::literal("client-trust"));
+ let label = Label::literal("client-trust").serialize();
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 5310a44..52da2f2 100644
--- a/src/index.rs
+++ b/src/index.rs
@@ -93,7 +93,7 @@ mod test {
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(&format!("{}", sum)).unwrap();
+ let ids = idx.find_by_label(&sum.serialize()).unwrap();
assert_eq!(ids, vec![id]);
}
@@ -117,7 +117,7 @@ mod test {
let mut idx = new_index(dir.path());
idx.insert_meta(id.clone(), meta).unwrap();
idx.remove_meta(&id).unwrap();
- let ids: Vec<ChunkId> = idx.find_by_label(&format!("{}", sum)).unwrap();
+ let ids: Vec<ChunkId> = idx.find_by_label(&sum.serialize()).unwrap();
assert_eq!(ids, vec![]);
}
}
@@ -216,7 +216,7 @@ mod sql {
fn row_to_meta(row: &Row) -> rusqlite::Result<ChunkMeta> {
let hash: String = row.get("label")?;
- let sha256 = Label::sha256_from_str_unchecked(&hash);
+ let sha256 = Label::deserialize(&hash).expect("deserialize checksum from database");
Ok(ChunkMeta::new(&sha256))
}
diff --git a/src/label.rs b/src/label.rs
index 7ee55d1..64be341 100644
--- a/src/label.rs
+++ b/src/label.rs
@@ -6,7 +6,9 @@
//! small number of carefully chosen algorithms are supported here.
use sha2::{Digest, Sha256};
-use std::fmt;
+
+const LITERAL: char = '0';
+const SHA256: char = '1';
/// A checksum of some data.
#[derive(Debug, Clone)]
@@ -32,18 +34,53 @@ impl Label {
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())
+ /// Serialize a label into a string representation.
+ pub fn serialize(&self) -> String {
+ match self {
+ Self::Literal(s) => format!("{}{}", LITERAL, s),
+ Self::Sha256(hash) => format!("{}{}", SHA256, hash),
+ }
}
-}
-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),
+ /// De-serialize a label from its string representation.
+ pub fn deserialize(s: &str) -> Result<Self, LabelError> {
+ if s.starts_with(LITERAL) {
+ Ok(Self::Literal(s[1..].to_string()))
+ } else if s.starts_with(SHA256) {
+ Ok(Self::Sha256(s[1..].to_string()))
+ } else {
+ Err(LabelError::UnknownType(s.to_string()))
}
}
}
+
+/// Possible errors from dealing with chunk labels.
+#[derive(Debug, thiserror::Error)]
+pub enum LabelError {
+ /// Serialized label didn't start with a known type prefix.
+ #[error("Unknown label: {0:?}")]
+ UnknownType(String),
+}
+
+#[cfg(test)]
+mod test {
+ use super::Label;
+
+ #[test]
+ fn roundtrip_literal() {
+ let label = Label::literal("dummy data");
+ let serialized = label.serialize();
+ let de = Label::deserialize(&serialized).unwrap();
+ let seri2 = de.serialize();
+ assert_eq!(serialized, seri2);
+ }
+
+ #[test]
+ fn roundtrip_sha256() {
+ let label = Label::sha256(b"dummy data");
+ let serialized = label.serialize();
+ let de = Label::deserialize(&serialized).unwrap();
+ let seri2 = de.serialize();
+ assert_eq!(serialized, seri2);
+ }
+}