Skip to content

Commit

Permalink
Replace Option<Value> with NilOrVal<Value> for clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Dec 8, 2023
1 parent db5f756 commit e13ddc3
Show file tree
Hide file tree
Showing 18 changed files with 351 additions and 179 deletions.
6 changes: 3 additions & 3 deletions Code/common/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
Address, Height, Proposal, PublicKey, Round, SignedVote, SigningScheme, Validator,
Address, Height, NilOrVal, Proposal, PublicKey, Round, SignedVote, SigningScheme, Validator,
ValidatorSet, Value, ValueId, Vote,
};

Expand Down Expand Up @@ -42,7 +42,7 @@ where
fn new_prevote(
height: Self::Height,
round: Round,
value_id: Option<ValueId<Self>>,
value_id: NilOrVal<ValueId<Self>>,
address: Self::Address,
) -> Self::Vote;

Expand All @@ -51,7 +51,7 @@ where
fn new_precommit(
height: Self::Height,
round: Round,
value_id: Option<ValueId<Self>>,
value_id: NilOrVal<ValueId<Self>>,
address: Self::Address,
) -> Self::Vote;
}
2 changes: 1 addition & 1 deletion Code/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ pub use signed_vote::SignedVote;
pub use signing::SigningScheme;
pub use timeout::{Timeout, TimeoutStep};
pub use validator_set::{Address, Validator, ValidatorSet, VotingPower};
pub use value::Value;
pub use value::{NilOrVal, Value};
pub use vote::{Vote, VoteType};
45 changes: 45 additions & 0 deletions Code/common/src/value.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
use core::fmt::Debug;

/// Represents either `Nil` or a value of type `Value`.
///
/// This type is isomorphic to `Option<Value>` but is more explicit about its intent.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum NilOrVal<Value> {
#[default]
Nil,

Val(Value),
}

impl<Value> NilOrVal<Value> {
pub fn is_nil(&self) -> bool {
matches!(self, Self::Nil)
}

pub fn is_val(&self) -> bool {
matches!(self, Self::Val(_))
}

pub fn map<NewValue, F: FnOnce(Value) -> NewValue>(self, f: F) -> NilOrVal<NewValue> {
match self {
NilOrVal::Nil => NilOrVal::Nil,
NilOrVal::Val(value) => NilOrVal::Val(f(value)),
}
}

pub fn as_ref(&self) -> NilOrVal<&Value> {
match self {
NilOrVal::Nil => NilOrVal::Nil,
NilOrVal::Val(value) => NilOrVal::Val(value),
}
}

pub fn value_or_default(self) -> Value
where
Value: Default,
{
match self {
NilOrVal::Nil => Value::default(),
NilOrVal::Val(value) => value,
}
}
}

/// Defines the requirements for the type of value to decide on.
pub trait Value
where
Expand Down
6 changes: 3 additions & 3 deletions Code/common/src/vote.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::fmt::Debug;

use crate::{Context, Round, Value};
use crate::{Context, NilOrVal, Round, Value};

/// A type of vote.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -28,10 +28,10 @@ where
fn round(&self) -> Round;

/// Get a reference to the value being voted for.
fn value(&self) -> &Option<<Ctx::Value as Value>::Id>;
fn value(&self) -> &NilOrVal<<Ctx::Value as Value>::Id>;

/// Take ownership of the value being voted for.
fn take_value(self) -> Option<<Ctx::Value as Value>::Id>;
fn take_value(self) -> NilOrVal<<Ctx::Value as Value>::Id>;

/// The type of vote.
fn vote_type(&self) -> VoteType;
Expand Down
6 changes: 3 additions & 3 deletions Code/itf/tests/votekeeper/runner.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use malachite_common::{Context, Round, Value};
use malachite_common::{Context, NilOrVal, Round, Value};
use malachite_itf::types::{Value as ModelValue, VoteType};
use malachite_itf::votekeeper::VoteKeeperOutput::*;
use malachite_itf::votekeeper::{State, WeightedVote};
Expand Down Expand Up @@ -82,7 +82,7 @@ impl ItfRunner for VoteKeeperRunner {
(Output::PolkaAny, PolkaAny(_expected_round)) => (),
(Output::PolkaValue(value), PolkaValue(_expected_round, expected_value)) => {
assert_eq!(
Some(value),
NilOrVal::Val(value),
value_from_model(&ModelValue::Val(expected_value.to_string())).as_ref()
);
}
Expand All @@ -92,7 +92,7 @@ impl ItfRunner for VoteKeeperRunner {
PrecommitValue(_expected_round, expected_value),
) => {
assert_eq!(
Some(value),
NilOrVal::Val(value),
value_from_model(&ModelValue::Val(expected_value.to_string())).as_ref()
);
}
Expand Down
11 changes: 6 additions & 5 deletions Code/itf/tests/votekeeper/utils.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use std::collections::HashMap;

use malachite_common::NilOrVal;
use malachite_itf::types::Value;
use malachite_test::{Address, ValueId};

pub const ADDRESSES: [&str; 3] = ["alice", "bob", "john"];

pub fn value_from_model(value: &Value) -> Option<ValueId> {
pub fn value_from_model(value: &Value) -> NilOrVal<ValueId> {
match value {
Value::Nil => None,
Value::Nil => NilOrVal::Nil,
Value::Val(v) => match v.as_str() {
"v1" => Some(1.into()),
"v2" => Some(2.into()),
"v3" => Some(3.into()),
"v1" => NilOrVal::Val(1.into()),
"v2" => NilOrVal::Val(2.into()),
"v3" => NilOrVal::Val(3.into()),
_ => unimplemented!("unknown value {value:?}"),
},
}
Expand Down
6 changes: 3 additions & 3 deletions Code/round/src/output.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::fmt;

use malachite_common::{Context, Round, Timeout, TimeoutStep, ValueId};
use malachite_common::{Context, NilOrVal, Round, Timeout, TimeoutStep, ValueId};

use crate::state::RoundValue;

Expand Down Expand Up @@ -29,7 +29,7 @@ impl<Ctx: Context> Output<Ctx> {
pub fn prevote(
height: Ctx::Height,
round: Round,
value_id: Option<ValueId<Ctx>>,
value_id: NilOrVal<ValueId<Ctx>>,
address: Ctx::Address,
) -> Self {
Output::Vote(Ctx::new_prevote(height, round, value_id, address))
Expand All @@ -38,7 +38,7 @@ impl<Ctx: Context> Output<Ctx> {
pub fn precommit(
height: Ctx::Height,
round: Round,
value_id: Option<ValueId<Ctx>>,
value_id: NilOrVal<ValueId<Ctx>>,
address: Ctx::Address,
) -> Self {
Output::Vote(Ctx::new_precommit(height, round, value_id, address))
Expand Down
27 changes: 19 additions & 8 deletions Code/round/src/state_machine.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use malachite_common::{Context, Proposal, Round, TimeoutStep, Value};
use malachite_common::{Context, NilOrVal, Proposal, Round, TimeoutStep, Value};

use crate::input::Input;
use crate::output::Output;
Expand Down Expand Up @@ -259,10 +259,10 @@ where
let vr = proposal.round();
let proposed = proposal.value().id();
let value = match &state.locked {
Some(locked) if locked.round <= vr => Some(proposed), // unlock and prevote
Some(locked) if locked.value.id() == proposed => Some(proposed), // already locked on value
Some(_) => None, // we're locked on a higher round with a different value, prevote nil
None => Some(proposed), // not locked, prevote the value
Some(locked) if locked.round <= vr => NilOrVal::Val(proposed), // unlock and prevote
Some(locked) if locked.value.id() == proposed => NilOrVal::Val(proposed), // already locked on value
Some(_) => NilOrVal::Nil, // we're locked on a higher round with a different value, prevote nil
None => NilOrVal::Val(proposed), // not locked, prevote the value
};

let output = Output::prevote(state.height.clone(), state.round, value, address.clone());
Expand All @@ -276,7 +276,13 @@ pub fn prevote_nil<Ctx>(state: State<Ctx>, address: &Ctx::Address) -> Transition
where
Ctx: Context,
{
let output = Output::prevote(state.height.clone(), state.round, None, address.clone());
let output = Output::prevote(
state.height.clone(),
state.round,
NilOrVal::Nil,
address.clone(),
);

Transition::to(state.with_step(Step::Prevote)).with_output(output)
}

Expand Down Expand Up @@ -306,7 +312,7 @@ where
let output = Output::precommit(
state.height.clone(),
state.round,
Some(value.id()),
NilOrVal::Val(value.id()),
address.clone(),
);

Expand All @@ -325,7 +331,12 @@ pub fn precommit_nil<Ctx>(state: State<Ctx>, address: &Ctx::Address) -> Transiti
where
Ctx: Context,
{
let output = Output::precommit(state.height.clone(), state.round, None, address.clone());
let output = Output::precommit(
state.height.clone(),
state.round,
NilOrVal::Nil,
address.clone(),
);
Transition::to(state.with_step(Step::Precommit)).with_output(output)
}

Expand Down
5 changes: 3 additions & 2 deletions Code/test/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use malachite_common::Context;
use malachite_common::NilOrVal;
use malachite_common::Round;
use malachite_common::SignedVote;

Expand Down Expand Up @@ -50,7 +51,7 @@ impl Context for TestContext {
fn new_prevote(
height: Height,
round: Round,
value_id: Option<ValueId>,
value_id: NilOrVal<ValueId>,
address: Address,
) -> Vote {
Vote::new_prevote(height, round, value_id, address)
Expand All @@ -59,7 +60,7 @@ impl Context for TestContext {
fn new_precommit(
height: Height,
round: Round,
value_id: Option<ValueId>,
value_id: NilOrVal<ValueId>,
address: Address,
) -> Vote {
Vote::new_precommit(height, round, value_id, address)
Expand Down
28 changes: 19 additions & 9 deletions Code/test/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rand::rngs::StdRng;
use rand::SeedableRng;

use malachite_common::{Round, Timeout, VotingPower};
use malachite_common::{NilOrVal, Round, Timeout, VotingPower};
use malachite_driver::{Input, Output, ProposerSelector, Validity};
use malachite_round::state::{RoundValue, State, Step};

Expand Down Expand Up @@ -87,7 +87,7 @@ pub fn prevote_output(
let value = Value::new(9999);

Some(Output::Vote(
Vote::new_prevote(Height::new(1), round, Some(value.id()), *addr).signed(sk),
Vote::new_prevote(Height::new(1), round, NilOrVal::Val(value.id()), *addr).signed(sk),
))
}

Expand All @@ -97,26 +97,34 @@ pub fn prevote_nil_output(
sk: &PrivateKey,
) -> Option<Output<TestContext>> {
Some(Output::Vote(
Vote::new_prevote(Height::new(1), round, None, *addr).signed(sk),
Vote::new_prevote(Height::new(1), round, NilOrVal::Nil, *addr).signed(sk),
))
}

pub fn prevote_input(addr: &Address, sk: &PrivateKey) -> Input<TestContext> {
let value = Value::new(9999);

Input::Vote(
Vote::new_prevote(Height::new(1), Round::new(0), Some(value.id()), *addr).signed(sk),
Vote::new_prevote(
Height::new(1),
Round::new(0),
NilOrVal::Val(value.id()),
*addr,
)
.signed(sk),
)
}

pub fn prevote_nil_input(addr: &Address, sk: &PrivateKey) -> Input<TestContext> {
Input::Vote(Vote::new_prevote(Height::new(1), Round::new(0), None, *addr).signed(sk))
Input::Vote(Vote::new_prevote(Height::new(1), Round::new(0), NilOrVal::Nil, *addr).signed(sk))
}

pub fn prevote_input_at(round: Round, addr: &Address, sk: &PrivateKey) -> Input<TestContext> {
let value = Value::new(9999);

Input::Vote(Vote::new_prevote(Height::new(1), round, Some(value.id()), *addr).signed(sk))
Input::Vote(
Vote::new_prevote(Height::new(1), round, NilOrVal::Val(value.id()), *addr).signed(sk),
)
}

pub fn precommit_output(
Expand All @@ -126,7 +134,7 @@ pub fn precommit_output(
sk: &PrivateKey,
) -> Option<Output<TestContext>> {
Some(Output::Vote(
Vote::new_precommit(Height::new(1), round, Some(value.id()), *addr).signed(sk),
Vote::new_precommit(Height::new(1), round, NilOrVal::Val(value.id()), *addr).signed(sk),
))
}

Expand All @@ -136,7 +144,7 @@ pub fn precommit_nil_output(
sk: &PrivateKey,
) -> Option<Output<TestContext>> {
Some(Output::Vote(
Vote::new_precommit(Height::new(1), round, None, *addr).signed(sk),
Vote::new_precommit(Height::new(1), round, NilOrVal::Nil, *addr).signed(sk),
))
}

Expand All @@ -146,7 +154,9 @@ pub fn precommit_input(
addr: &Address,
sk: &PrivateKey,
) -> Input<TestContext> {
Input::Vote(Vote::new_precommit(Height::new(1), round, Some(value.id()), *addr).signed(sk))
Input::Vote(
Vote::new_precommit(Height::new(1), round, NilOrVal::Val(value.id()), *addr).signed(sk),
)
}

pub fn decide_output(round: Round, value: Value) -> Option<Output<TestContext>> {
Expand Down
Loading

0 comments on commit e13ddc3

Please sign in to comment.