mirror of
https://github.com/tlsnotary/tlsn-utils.git
synced 2026-01-09 12:48:03 -05:00
Redesign mpc-garble (#220)
* mpc-garble * move semihonest test to integration, expose some more types * value config doc * reenable all mpc crates * rename msg type * simplify config a bit * typo * add bound to StaticValueType * clean up setup_inputs * appease clippy * add more flexible methods to memory trait * add getter for value type * comments and tweaks * rename append -> append_string * fix registry corruption * drain filter * finalize bug * use matches! * use as_ref * remove default * make decode public * lower visibility for evaluator fn * eval doc fix * update buffering to be per value id * input buffer methods * move memory impl into separate module * encapsulate finalized state * flatten logic in value config * fixes in utils * docs
This commit is contained in:
166
utils/utils/src/id.rs
Normal file
166
utils/utils/src/id.rs
Normal file
@@ -0,0 +1,166 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A nested ID.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use utils::id::NestedId;
|
||||
/// let id = NestedId::new("foo");
|
||||
/// let id = id.append_string("bar");
|
||||
/// assert_eq!(id.to_string(), "foo/bar");
|
||||
/// let mut id = id.append_counter();
|
||||
/// assert_eq!(id.to_string(), "foo/bar/0");
|
||||
/// let new_id = id.increment();
|
||||
/// assert_eq!(new_id.to_string(), "foo/bar/1");
|
||||
/// assert!(new_id > id);
|
||||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum NestedId {
|
||||
String {
|
||||
id: String,
|
||||
root: Option<Arc<NestedId>>,
|
||||
},
|
||||
Counter {
|
||||
value: usize,
|
||||
root: Option<Arc<NestedId>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl NestedId {
|
||||
/// Create a new nested ID.
|
||||
pub fn new(id: &str) -> Self {
|
||||
NestedId::String {
|
||||
id: id.to_string(),
|
||||
root: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the root of this ID.
|
||||
pub fn root(&self) -> Option<&NestedId> {
|
||||
match self {
|
||||
NestedId::String { root, .. } => root,
|
||||
NestedId::Counter { root, .. } => root,
|
||||
}
|
||||
.as_ref()
|
||||
.map(|id| id.as_ref())
|
||||
}
|
||||
|
||||
/// Returns whether this ID is a counter ID.
|
||||
pub fn is_counter(&self) -> bool {
|
||||
match self {
|
||||
NestedId::String { .. } => false,
|
||||
NestedId::Counter { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this ID is a string ID.
|
||||
pub fn is_string(&self) -> bool {
|
||||
!self.is_counter()
|
||||
}
|
||||
|
||||
/// Creates a new ID with `self` as the root.
|
||||
pub fn append_string(&self, id: &str) -> NestedId {
|
||||
Self::String {
|
||||
id: id.to_string(),
|
||||
root: Some(Arc::new(self.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new counter ID with `self` as the root.
|
||||
pub fn append_counter(&self) -> NestedId {
|
||||
Self::Counter {
|
||||
value: 0,
|
||||
root: Some(Arc::new(self.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new ID with the counter incremented.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if this ID is not a counter ID.
|
||||
pub fn increment(&self) -> Self {
|
||||
let mut id = self.clone();
|
||||
id.increment_in_place();
|
||||
id
|
||||
}
|
||||
|
||||
/// Increments the counter of this ID, returning the previous value.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if this ID is not a counter ID.
|
||||
pub fn increment_in_place(&mut self) -> Self {
|
||||
let prev = self.clone();
|
||||
|
||||
match self {
|
||||
NestedId::String { .. } => panic!("cannot increment a string ID"),
|
||||
NestedId::Counter { value, .. } => *value += 1,
|
||||
}
|
||||
|
||||
prev
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for NestedId {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
NestedId::String { id, root } => match root {
|
||||
Some(root) => format!("{}/{}", root.to_string(), id),
|
||||
None => id.to_string(),
|
||||
},
|
||||
NestedId::Counter { value, root } => match root {
|
||||
Some(root) => format!("{}/{}", root.to_string(), value),
|
||||
None => value.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for NestedId {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.to_string().cmp(&other.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_nested_id() {
|
||||
let id = NestedId::new("foo");
|
||||
assert_eq!(id.to_string(), "foo");
|
||||
assert_eq!(id.root(), None);
|
||||
|
||||
let id = id.append_string("bar");
|
||||
assert_eq!(id.to_string(), "foo/bar");
|
||||
assert_eq!(id.root().unwrap().to_string(), "foo");
|
||||
assert!(id.is_string());
|
||||
|
||||
let id = id.append_string("baz");
|
||||
assert_eq!(id.to_string(), "foo/bar/baz");
|
||||
assert_eq!(id.root().unwrap().to_string(), "foo/bar");
|
||||
assert!(id.is_string());
|
||||
|
||||
let mut id = id.append_counter();
|
||||
assert_eq!(id.to_string(), "foo/bar/baz/0");
|
||||
assert_eq!(id.root().unwrap().to_string(), "foo/bar/baz");
|
||||
assert!(id.is_counter());
|
||||
|
||||
id.increment_in_place();
|
||||
assert_eq!(id.to_string(), "foo/bar/baz/1");
|
||||
assert_eq!(id.root().unwrap().to_string(), "foo/bar/baz");
|
||||
assert!(id.is_counter());
|
||||
|
||||
let new_id = id.increment();
|
||||
assert_eq!(new_id.to_string(), "foo/bar/baz/2");
|
||||
assert_eq!(new_id.root().unwrap().to_string(), "foo/bar/baz");
|
||||
assert!(new_id.is_counter());
|
||||
assert!(new_id > id);
|
||||
|
||||
let root = id.root().unwrap().root().unwrap().root().unwrap();
|
||||
assert_eq!(root.to_string(), "foo");
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,68 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
pub struct FilterDrainIter<'a, F, T> {
|
||||
vec: &'a mut Vec<T>,
|
||||
pos: usize,
|
||||
pred: F,
|
||||
}
|
||||
|
||||
impl<'a, F, T> Iterator for FilterDrainIter<'a, F, T>
|
||||
where
|
||||
F: Fn(&T) -> bool,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.pos >= self.vec.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if (self.pred)(&self.vec[self.pos]) {
|
||||
Some(self.vec.swap_remove(self.pos))
|
||||
} else {
|
||||
self.pos += 1;
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait that implements `drain_filter` which is not stable yet.
|
||||
///
|
||||
/// See [tracking issue](https://github.com/rust-lang/rust/issues/43244)
|
||||
///
|
||||
/// We call this `FilterDrain` to avoid the naming conflict with the standard library.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The order of the elements is not preserved.
|
||||
pub trait FilterDrain<'a, F, T>
|
||||
where
|
||||
F: Fn(&T) -> bool,
|
||||
{
|
||||
type Item;
|
||||
type Iter: Iterator<Item = Self::Item> + 'a;
|
||||
|
||||
fn filter_drain(&'a mut self, pred: F) -> Self::Iter;
|
||||
}
|
||||
|
||||
impl<'a, F, T> FilterDrain<'a, F, T> for Vec<T>
|
||||
where
|
||||
F: Fn(&T) -> bool + 'a,
|
||||
T: 'a,
|
||||
{
|
||||
type Item = T;
|
||||
type Iter = FilterDrainIter<'a, F, T>;
|
||||
|
||||
fn filter_drain(&'a mut self, pred: F) -> FilterDrainIter<'a, F, T> {
|
||||
FilterDrainIter {
|
||||
vec: self,
|
||||
pos: 0,
|
||||
pred,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -100,11 +162,23 @@ mod test {
|
||||
struct Container<T>(T);
|
||||
|
||||
impl<T> Container<T> {
|
||||
fn get<'a>(&'a self) -> &'a T {
|
||||
fn get(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_drain() {
|
||||
let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8];
|
||||
let mut even = v.filter_drain(|x| *x % 2 == 0).collect::<Vec<_>>();
|
||||
|
||||
v.sort();
|
||||
even.sort();
|
||||
|
||||
assert_eq!(even, vec![2, 4, 6, 8]);
|
||||
assert_eq!(v, vec![1, 3, 5, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_check_contains_dups() {
|
||||
let x = [0, 1, 1];
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod bits;
|
||||
pub mod id;
|
||||
pub mod iter;
|
||||
|
||||
Reference in New Issue
Block a user