mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
mercurial-types: allow encoding Sha1 as a Thrift structure
Summary: Will be used for Thrift envelopes. Reviewed By: jsgf Differential Revision: D7771214 fbshipit-source-id: 3f0dbf77793064f2606ebe34672629c4e49cc7fe
This commit is contained in:
parent
c133d8cedf
commit
d005c83751
@ -10,6 +10,7 @@ pub use failure::{Error, ResultExt};
|
||||
pub enum ErrorKind {
|
||||
#[fail(display = "invalid sha-1 input: {}", _0)] InvalidSha1Input(String),
|
||||
#[fail(display = "invalid fragment list: {}", _0)] InvalidFragmentList(String),
|
||||
#[fail(display = "invalid Thrift structure '{}': {}", _0, _1)] InvalidThrift(String, String),
|
||||
}
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
@ -12,6 +12,8 @@ use quickcheck::{single_shrinker, Arbitrary, Gen};
|
||||
use rust_crypto::digest::Digest;
|
||||
use rust_crypto::sha1;
|
||||
|
||||
use thrift;
|
||||
|
||||
use errors::*;
|
||||
|
||||
pub const NULL: Sha1 = Sha1([0; 20]);
|
||||
@ -40,6 +42,20 @@ impl Sha1 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_thrift(h: thrift::Sha1) -> Result<Self> {
|
||||
// Currently this doesn't require consuming b, but hopefully with T26959816 this
|
||||
// code will be able to convert a SmallVec directly into an array.
|
||||
if h.0.len() != 20 {
|
||||
bail_err!(ErrorKind::InvalidThrift(
|
||||
"Sha1".into(),
|
||||
format!("wrong length: expected 20, got {}", h.0.len())
|
||||
));
|
||||
}
|
||||
let mut arr = [0u8; 20];
|
||||
arr.copy_from_slice(&h.0[..]);
|
||||
Ok(Sha1(arr))
|
||||
}
|
||||
|
||||
/// Construct a `Sha1` from an array of 20 bytes.
|
||||
#[inline]
|
||||
pub const fn from_byte_array(arr: [u8; 20]) -> Sha1 {
|
||||
@ -64,6 +80,12 @@ impl Sha1 {
|
||||
AsciiString::from_ascii_unchecked(v)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_thrift(self) -> thrift::Sha1 {
|
||||
// This doesn't need to consume self today, but once T26959816 is implemented it
|
||||
// should be possible to do that without copying.
|
||||
thrift::Sha1(self.0.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// Context for incrementally computing a `Sha1` hash.
|
||||
@ -163,10 +185,11 @@ impl Context {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Sha1, NULL};
|
||||
use quickcheck::TestResult;
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
const NILHASH: Sha1 = Sha1([0xda, 0x39, 0xa3, 0xee,
|
||||
0x5e, 0x6b, 0x4b, 0x0d,
|
||||
@ -241,6 +264,24 @@ mod test {
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_thrift() {
|
||||
let null_thrift = thrift::Sha1(vec![0; 20]);
|
||||
assert_eq!(NULL, Sha1::from_thrift(null_thrift.clone()).unwrap());
|
||||
assert_eq!(NULL.into_thrift(), null_thrift);
|
||||
|
||||
let nil_thrift = thrift::Sha1(NILHASH.0.to_vec());
|
||||
assert_eq!(NILHASH, Sha1::from_thrift(nil_thrift.clone()).unwrap());
|
||||
assert_eq!(NILHASH.into_thrift(), nil_thrift);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_thrift_bad() {
|
||||
Sha1::from_thrift(thrift::Sha1(vec![])).expect_err("unexpected OK - zero len");
|
||||
Sha1::from_thrift(thrift::Sha1(vec![0; 19])).expect_err("unexpected OK - too short");
|
||||
Sha1::from_thrift(thrift::Sha1(vec![0; 21])).expect_err("unexpected OK - too long");
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn parse_roundtrip(v: Vec<u8>) -> TestResult {
|
||||
if v.len() != 20 {
|
||||
@ -253,6 +294,13 @@ mod test {
|
||||
TestResult::from_bool(h == sh)
|
||||
}
|
||||
|
||||
fn thrift_roundtrip(h: Sha1) -> bool {
|
||||
let v = h.into_thrift();
|
||||
let sh = Sha1::from_thrift(v)
|
||||
.expect("converting a valid Thrift structure should always work");
|
||||
h == sh
|
||||
}
|
||||
|
||||
fn to_hex_roundtrip(h: Sha1) -> bool {
|
||||
let v = h.to_hex();
|
||||
let sh = Sha1::from_ascii_str(&v).unwrap();
|
||||
|
@ -76,6 +76,7 @@ extern crate serde_derive;
|
||||
|
||||
extern crate futures_ext;
|
||||
extern crate mononoke_types;
|
||||
extern crate mononoke_types_thrift;
|
||||
extern crate storage_types;
|
||||
|
||||
pub mod bdiff;
|
||||
@ -114,6 +115,10 @@ pub use errors::{Error, ErrorKind};
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod thrift {
|
||||
pub use mononoke_types_thrift::*;
|
||||
}
|
||||
|
||||
impl asyncmemo::Weight for RepositoryId {
|
||||
fn get_weight(&self) -> usize {
|
||||
std::mem::size_of::<RepositoryId>()
|
||||
|
@ -35,6 +35,10 @@ typedef Blake2 UnodeId (hs.newtype)
|
||||
typedef Blake2 ChangesetId (hs.newtype)
|
||||
typedef Blake2 ContentId (hs.newtype)
|
||||
|
||||
// mercurial_types defines Sha1, and it's most convenient to stick this in here.
|
||||
// This can be moved away in the future if necessary.
|
||||
typedef binary Sha1 (hs.newtype)
|
||||
|
||||
// A path in a repo is stored as a list of elements. This is so that the sort
|
||||
// order of paths is the same as that of a tree traversal, so that deltas on
|
||||
// manifests can be applied in a streaming way.
|
||||
|
Loading…
Reference in New Issue
Block a user