1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::sync::Arc;

use fast_rsync::{diff, Signature, SignatureOptions};
use object_lib::ObjectId;
use object_tracker::ObjectTracker;

use crate::config::RSyncConfig;
use crate::util;

pub enum SignatureCalculationConfig<'a> {
    SignatureCalculationOptions(SignatureOptions),
    SignatureCalculationConfig(&'a RSyncConfig),
}

impl Into<SignatureOptions> for SignatureCalculationConfig<'_> {
    fn into(self) -> SignatureOptions {
        match self {
            SignatureCalculationConfig::SignatureCalculationOptions(so) => so,
            SignatureCalculationConfig::SignatureCalculationConfig(c) => SignatureOptions {
                block_size: c.block_size,
                crypto_hash_size: c.hash_size,
            },
        }
    }
}

pub fn calculate_signature(
    object_id: ObjectId,
    object_tracker: Arc<ObjectTracker>,
    signature_calculation_config: SignatureCalculationConfig<'_>,
) -> Vec<u8> {
    let object_bytes: Vec<u8> = match util::get_object_bytes(object_id, object_tracker) {
        Some(ob) => ob,
        None => vec![],
    };

    let signature_options = signature_calculation_config.into();
    Signature::calculate(&object_bytes, signature_options).into_serialized()
}

pub fn get_empty_signature(
    signature_calculation_config: SignatureCalculationConfig<'_>,
) -> Signature {
    let signature_options = signature_calculation_config.into();
    Signature::calculate(&vec![], signature_options)
}

pub fn deserialize_signature<'a>(
    serialized_signature: &'a [u8],
    signature_calculation_config: SignatureCalculationConfig<'_>,
) -> Result<Signature, ()> {
    // TODO error type
    if serialized_signature.len() == 0 {
        // NOTE: `fast_rsync` currently has problems deserializing an empty signature, so
        // we have to create an empty signature object here.
        return Ok(get_empty_signature(signature_calculation_config));
    }

    match Signature::deserialize(serialized_signature.to_vec()) {
        Ok(s) => Ok(s),
        Err(e) => {
            eprintln!("Could not deserialize signature: {}", e);
            return Err(());
        }
    }
}

pub fn calculate_diff(
    foreign_signature: &Signature,
    object_bytes: &[u8],
    out: &mut Vec<u8>,
) -> Result<(), ()> {
    match diff(&foreign_signature.index(), &object_bytes, out) {
        Ok(()) => Ok(()),
        Err(e) => {
            eprintln!("Could not calculate signature diff: {}", e);
            return Err(());
        }
    }
}