types: add WireCloneData

Summary: Serialization format for dag's CloneData.

Reviewed By: quark-zju

Differential Revision: D24717926

fbshipit-source-id: 51f3aa189260a4062cfd75e412b98defd2a8cf94
This commit is contained in:
Stefan Filip 2020-11-11 22:51:32 -08:00 committed by Facebook GitHub Bot
parent 596d54adfe
commit e5ada2f396
5 changed files with 186 additions and 1 deletions

View File

@ -10,6 +10,7 @@ default = ["for-tests"]
for-tests = []
[dependencies]
dag = { path = "../../dag", features = ["for-tests"] }
revisionstore_types = { path = "../../revisionstore/types" }
types = { path = "../../types" }
anyhow = "1.0"

View File

@ -50,6 +50,9 @@ pub use crate::metadata::{
pub use crate::tree::{TreeChildEntry, TreeEntry, TreeError, TreeRequest};
pub use crate::wire::{ToApi, ToWire, WireToApiConversionError};
// re-export CloneData
pub use dag::{CloneData, FlatSegment, PreparedFlatSegments};
#[cfg(any(test, feature = "for-tests"))]
use quickcheck::Arbitrary;
use thiserror::Error;

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
use std::collections::HashMap;
#[cfg(any(test, feature = "for-tests"))]
use quickcheck::Arbitrary;
use serde_derive::{Deserialize, Serialize};
use types::HgId;
use crate::wire::{ToApi, ToWire, WireDagId, WireHgId, WireToApiConversionError};
use crate::{CloneData, FlatSegment, PreparedFlatSegments};
// Only when an id has more than one parent it is sent over the wire.
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct WireCloneData {
#[serde(rename = "1")]
pub head_id: WireDagId,
#[serde(rename = "2")]
pub flat_segments: Vec<WireFlatSegment>,
#[serde(rename = "3")]
pub idmap: Vec<WireIdMapEntry>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct WireFlatSegment {
#[serde(rename = "1")]
pub low: WireDagId,
#[serde(rename = "2")]
pub high: WireDagId,
#[serde(rename = "3")]
pub parents: Vec<WireDagId>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct WireIdMapEntry {
#[serde(rename = "1")]
pub dag_id: WireDagId,
#[serde(rename = "2")]
pub hg_id: WireHgId,
}
impl ToWire for CloneData<HgId> {
type Wire = WireCloneData;
fn to_wire(self) -> Self::Wire {
let idmap = self
.idmap
.into_iter()
.map(|(k, v)| WireIdMapEntry {
dag_id: k.to_wire(),
hg_id: v.to_wire(),
})
.collect();
WireCloneData {
head_id: self.head_id.to_wire(),
flat_segments: self.flat_segments.segments.to_wire(),
idmap,
}
}
}
impl ToApi for WireCloneData {
type Api = CloneData<HgId>;
type Error = WireToApiConversionError;
fn to_api(self) -> Result<Self::Api, Self::Error> {
let mut idmap = HashMap::new();
for wie in self.idmap {
idmap.insert(wie.dag_id.to_api()?, wie.hg_id.to_api()?);
}
let flat_segments = PreparedFlatSegments {
segments: self.flat_segments.to_api()?,
};
Ok(CloneData {
head_id: self.head_id.to_api()?,
flat_segments,
idmap,
})
}
}
impl ToWire for FlatSegment {
type Wire = WireFlatSegment;
fn to_wire(self) -> Self::Wire {
WireFlatSegment {
low: self.low.to_wire(),
high: self.high.to_wire(),
parents: self.parents.to_wire(),
}
}
}
impl ToApi for WireFlatSegment {
type Api = FlatSegment;
type Error = WireToApiConversionError;
fn to_api(self) -> Result<Self::Api, Self::Error> {
Ok(FlatSegment {
low: self.low.to_api()?,
high: self.high.to_api()?,
parents: self.parents.to_api()?,
})
}
}
#[cfg(any(test, feature = "for-tests"))]
impl Arbitrary for WireFlatSegment {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
FlatSegment::arbitrary(g).to_wire()
}
}
#[cfg(any(test, feature = "for-tests"))]
impl Arbitrary for WireCloneData {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
CloneData::arbitrary(g).to_wire()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::wire::tests::{check_serialize_roundtrip, check_wire_roundtrip};
use quickcheck::quickcheck;
quickcheck! {
fn test_request_roundtrip_serialize(v: WireCloneData) -> bool {
check_serialize_roundtrip(v)
}
fn test_request_roundtrip_wire(v: CloneData<HgId>) -> bool {
check_wire_roundtrip(v)
}
}
}

View File

@ -45,6 +45,7 @@
//! 7. If the type has a corresponding API type, add a quickcheck wire-API round
//! trip test.
pub mod clone;
pub mod complete_tree;
pub mod file;
pub mod history;
@ -52,6 +53,7 @@ pub mod metadata;
pub mod tree;
pub use crate::wire::{
clone::{WireCloneData, WireIdMapEntry},
complete_tree::WireCompleteTreeRequest,
file::{WireFileEntry, WireFileRequest},
history::{WireHistoryRequest, WireHistoryResponseChunk, WireWireHistoryEntry},
@ -427,6 +429,26 @@ impl ToApi for u32 {
}
}
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WireDagId(u64);
impl ToWire for dag::Id {
type Wire = WireDagId;
fn to_wire(self) -> Self::Wire {
WireDagId(self.0)
}
}
impl ToApi for WireDagId {
type Api = dag::Id;
type Error = Infallible;
fn to_api(self) -> Result<Self::Api, Self::Error> {
Ok(dag::Id(self.0))
}
}
fn is_default<T: Default + PartialEq>(v: &T) -> bool {
v == &T::default()
}
@ -482,6 +504,13 @@ impl Arbitrary for WireRevisionstoreMetadata {
}
}
#[cfg(any(test, feature = "for-tests"))]
impl Arbitrary for WireDagId {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
dag::Id::arbitrary(g).to_wire()
}
}
#[cfg(test)]
pub mod tests {
use super::*;
@ -530,6 +559,10 @@ pub mod tests {
check_serialize_roundtrip(v)
}
fn test_dagid_roundtrip_serialize(v: WireDagId) -> bool {
check_serialize_roundtrip(v)
}
// API-Wire roundtrips
fn test_hgid_roundtrip_wire(v: HgId) -> bool {
check_wire_roundtrip(v)
@ -550,5 +583,9 @@ pub mod tests {
fn test_meta_roundtrip_wire(v: RevisionstoreMetadata) -> bool {
check_wire_roundtrip(v)
}
fn test_dagid_roundtrip_wire(v: dag::Id) -> bool {
check_wire_roundtrip(v)
}
}
}

View File

@ -6,7 +6,7 @@ version = "0.1.0"
include = ["src/**/*.rs"]
[dependencies]
dag = { path = "../dag" }
dag = { path = "../dag", features = ["for-tests"] }
edenapi = { path = "../edenapi" }
gitdag = { path = "../dag/gitdag" }
metalog = { path = "../metalog" }