Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jscatena/vector clock types #42

Merged
merged 10 commits into from
Jul 8, 2024
32 changes: 17 additions & 15 deletions src/codec/meta/actor_settings.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
use ecdsa::signature::rand_core::CryptoRngCore;
use futures::{AsyncWrite, AsyncWriteExt};
use winnow::binary::le_u8;
use winnow::token::take;
use winnow::Parser;
use winnow::{binary::le_u8, token::take, Parser};

use crate::codec::crypto::{
AccessKey, AsymLockedAccessKey, AsymLockedAccessKeyError, SigningKey, VerifyingKey,
use crate::codec::{
crypto::{AccessKey, AsymLockedAccessKey, AsymLockedAccessKeyError, SigningKey, VerifyingKey},
header::AccessMask,
meta::{UserAgent, VectorClockActorSnapshot},
ParserResult, Stream,
};
use crate::codec::header::AccessMask;
use crate::codec::meta::{UserAgent, VectorClock, VectorClockSnapshot};
use crate::codec::{ParserResult, Stream};

const KEY_PRESENT_BIT: u8 = 0b0000_0001;

#[derive(Clone, Debug)]
pub struct ActorSettings {
verifying_key: VerifyingKey,
vector_clock: VectorClock,
vector_clock: VectorClockActorSnapshot,
sstelfox marked this conversation as resolved.
Show resolved Hide resolved

access_mask: AccessMask,
filesystem_key: Option<AsymLockedAccessKey>,
Expand Down Expand Up @@ -176,8 +174,12 @@ impl ActorSettings {
Ok(Some(open_key))
}

pub fn new(verifying_key: VerifyingKey, access_mask: AccessMask) -> Self {
let vector_clock = VectorClock::initialize();
pub fn new(
verifying_key: VerifyingKey,
access_mask: AccessMask,
vector_clock: VectorClockActorSnapshot,
) -> Self {
// Should we test that the actor id associated with the verifying key matches the actor id of the vector clock?
let user_agent = UserAgent::current();

Self {
Expand All @@ -195,7 +197,7 @@ impl ActorSettings {

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, verifying_key) = VerifyingKey::parse(input)?;
let (input, vector_clock) = VectorClock::parse(input)?;
let (input, vector_clock) = VectorClockActorSnapshot::parse(input)?;
let (input, access_mask) = AccessMask::parse(input)?;
let (input, user_agent) = UserAgent::parse(input)?;

Expand All @@ -220,7 +222,7 @@ impl ActorSettings {

pub const fn size() -> usize {
VerifyingKey::size()
+ VectorClock::size()
+ VectorClockActorSnapshot::size()
+ AccessMask::size()
+ UserAgent::size()
+ 3 * (1 + AsymLockedAccessKey::size())
Expand All @@ -234,8 +236,8 @@ impl ActorSettings {
self.user_agent.clone()
}

pub fn vector_clock(&self) -> VectorClockSnapshot {
VectorClockSnapshot::from(&self.vector_clock)
pub fn vector_clock(&self) -> VectorClockActorSnapshot {
self.vector_clock
}

pub fn verifying_key(&self) -> VerifyingKey {
Expand Down
12 changes: 7 additions & 5 deletions src/codec/meta/journal_checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

use futures::io::AsyncWrite;

use crate::codec::meta::{Cid, VectorClockSnapshot};
use crate::codec::meta::{Cid, VectorClockFilesystemSnapshot};
use crate::codec::{ParserResult, Stream};

#[derive(Clone, Debug, PartialEq)]
pub struct JournalCheckpoint {
merkle_root_cid: Cid,
vector: VectorClockSnapshot,
vector: VectorClockFilesystemSnapshot,
}

impl JournalCheckpoint {
Expand All @@ -27,7 +27,7 @@ impl JournalCheckpoint {

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, merkle_root_cid) = Cid::parse(input)?;
let (input, vector) = VectorClockSnapshot::parse(input)?;
let (input, vector) = VectorClockFilesystemSnapshot::parse(input)?;

let journal_checkpoint = JournalCheckpoint {
merkle_root_cid,
Expand All @@ -38,14 +38,16 @@ impl JournalCheckpoint {
}

pub const fn size() -> usize {
Cid::size() + VectorClockSnapshot::size()
Cid::size() + VectorClockFilesystemSnapshot::size()
}
}

#[cfg(test)]
mod tests {
use winnow::Partial;

use crate::codec::VectorClockFilesystem;

use super::*;

#[cfg(target_arch = "wasm32")]
Expand All @@ -56,7 +58,7 @@ mod tests {
async fn test_user_agent_roundtrip() {
let checkpoint = JournalCheckpoint {
merkle_root_cid: Cid::from([0; 32]),
vector: VectorClockSnapshot::from(0),
vector: (&VectorClockFilesystem::initialize()).as_snapshot(),
};

let mut buffer = Vec::with_capacity(JournalCheckpoint::size());
Expand Down
8 changes: 7 additions & 1 deletion src/codec/meta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ pub use journal_checkpoint::JournalCheckpoint;
pub use meta_key::MetaKey;
pub use permanent_id::PermanentId;
pub use user_agent::UserAgent;
pub use vector_clock::{VectorClock, VectorClockSnapshot};
pub use vector_clock::{
Actor as VectorClockActor, ActorSnapshot as VectorClockActorSnapshot,
Filesystem as VectorClockFilesystem,
FilesystemActorSnapshot as VectorClockFilesystemActorSnapshot,
FilesystemSnapshot as VectorClockFilesystemSnapshot, Node as VectorClockNode,
NodeActorSnapshot as VectorClockNodeActorSnapshot, NodeSnapshot as VectorClockNodeSnapshot,
};
93 changes: 93 additions & 0 deletions src/codec/meta/vector_clock/actor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::clock_inner::{ClockInner, ClockInnerSnapshot};
use crate::codec::{ActorId, ParserResult, Stream};

use futures::AsyncWrite;

#[derive(Debug, PartialEq, Clone)]
pub struct Actor {
id: ActorId,
clock: ClockInner,
}

impl Actor {
fn new(id: ActorId, clock: ClockInner) -> Self {
Self { id, clock }
}

pub fn initialize(actor_id: ActorId) -> Self {
Self::new(actor_id, ClockInner::initialize())
}

pub fn as_snapshot(&self) -> ActorSnapshot {
self.into()
}

pub async fn encode<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut W,
) -> std::io::Result<usize> {
ActorSnapshot::from(self).encode(writer).await
}

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, snapshot) = ActorSnapshot::parse(input)?;
Ok((input, Self::new(snapshot.id, snapshot.clock.into())))
}
}

impl From<ActorSnapshot> for Actor {
fn from(value: ActorSnapshot) -> Self {
Self::new(value.id, value.clock.into())
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ActorSnapshot {
id: ActorId,
clock: ClockInnerSnapshot,
}

impl ActorSnapshot {
fn new(id: ActorId, clock: ClockInnerSnapshot) -> Self {
Self { id, clock }
}

pub const fn size() -> usize {
ActorId::size() + ClockInnerSnapshot::size()
}

pub async fn encode<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut W,
) -> std::io::Result<usize> {
self.id.encode(writer).await?;
self.clock.encode(writer).await
}

pub fn parse(input: Stream) -> ParserResult<Self> {
let (input, id) = ActorId::parse(input)?;
let (input, clock) = ClockInnerSnapshot::parse(input)?;
Ok((input, Self::new(id, clock)))
}
}

impl PartialOrd for ActorSnapshot {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for ActorSnapshot {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id).then(self.clock.cmp(&other.clock))
}
}

impl From<&Actor> for ActorSnapshot {
fn from(value: &Actor) -> Self {
Self {
id: value.id,
clock: (&value.clock).into(),
}
}
}
Loading
Loading