minor optimization to 'to_canonical_json'
* don't clone hash keys, just use references * we don't need a String, stick to Vec<u8> and use serde_json::to_writer to avoid a temporary strings altogether Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
2774566b03
commit
20a4e4e252
@ -130,39 +130,47 @@ impl BackupManifest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate cannonical json
|
// Generate cannonical json
|
||||||
fn to_canonical_json(value: &Value, output: &mut String) -> Result<(), Error> {
|
fn to_canonical_json(value: &Value) -> Result<Vec<u8>, Error> {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
Self::write_canonical_json(value, &mut data)?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_canonical_json(value: &Value, output: &mut Vec<u8>) -> Result<(), Error> {
|
||||||
match value {
|
match value {
|
||||||
Value::Null => bail!("got unexpected null value"),
|
Value::Null => bail!("got unexpected null value"),
|
||||||
Value::String(_) => {
|
Value::String(_) | Value::Number(_) | Value::Bool(_) => {
|
||||||
output.push_str(&serde_json::to_string(value)?);
|
serde_json::to_writer(output, &value)?;
|
||||||
},
|
|
||||||
Value::Number(_) => {
|
|
||||||
output.push_str(&serde_json::to_string(value)?);
|
|
||||||
}
|
}
|
||||||
Value::Bool(_) => {
|
|
||||||
output.push_str(&serde_json::to_string(value)?);
|
|
||||||
},
|
|
||||||
Value::Array(list) => {
|
Value::Array(list) => {
|
||||||
output.push('[');
|
output.push(b'[');
|
||||||
for (i, item) in list.iter().enumerate() {
|
let mut iter = list.iter();
|
||||||
if i != 0 { output.push(','); }
|
if let Some(item) = iter.next() {
|
||||||
Self::to_canonical_json(item, output)?;
|
Self::write_canonical_json(item, output)?;
|
||||||
|
for item in iter {
|
||||||
|
output.push(b',');
|
||||||
|
Self::write_canonical_json(item, output)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.push(']');
|
output.push(b']');
|
||||||
}
|
}
|
||||||
Value::Object(map) => {
|
Value::Object(map) => {
|
||||||
output.push('{');
|
output.push(b'{');
|
||||||
let mut keys: Vec<String> = map.keys().map(|s| s.clone()).collect();
|
let mut keys: Vec<&str> = map.keys().map(String::as_str).collect();
|
||||||
keys.sort();
|
keys.sort();
|
||||||
for (i, key) in keys.iter().enumerate() {
|
let mut iter = keys.into_iter();
|
||||||
let item = map.get(key).unwrap();
|
if let Some(key) = iter.next() {
|
||||||
if i != 0 { output.push(','); }
|
output.extend(key.as_bytes());
|
||||||
|
output.push(b':');
|
||||||
output.push_str(&serde_json::to_string(&Value::String(key.clone()))?);
|
Self::write_canonical_json(&map[key], output)?;
|
||||||
output.push(':');
|
for key in iter {
|
||||||
Self::to_canonical_json(item, output)?;
|
output.push(b',');
|
||||||
|
output.extend(key.as_bytes());
|
||||||
|
output.push(b':');
|
||||||
|
Self::write_canonical_json(&map[key], output)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output.push('}');
|
output.push(b'}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -182,10 +190,9 @@ impl BackupManifest {
|
|||||||
|
|
||||||
signed_data.as_object_mut().unwrap().remove("unprotected"); // exclude
|
signed_data.as_object_mut().unwrap().remove("unprotected"); // exclude
|
||||||
|
|
||||||
let mut canonical = String::new();
|
let canonical = Self::to_canonical_json(&signed_data)?;
|
||||||
Self::to_canonical_json(&signed_data, &mut canonical)?;
|
|
||||||
|
|
||||||
let sig = crypt_config.compute_auth_tag(canonical.as_bytes());
|
let sig = crypt_config.compute_auth_tag(&canonical);
|
||||||
|
|
||||||
Ok(sig)
|
Ok(sig)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user