pub fn apply_policy_op(&mut self, op: CrdtPolicyOperation<A, P>) -> Result<()> {
        // First check op is validly signed.
        // Note: Perms for the op are checked at the upper Sequence layer.
        let sig = op.signature.ok_or(Error::CrdtMissingOpSignature)?;
        let bytes_to_verify = utils::serialise(&op.crdt_op).map_err(|err| {
            Error::Serialisation(format!(
                "Could not serialise CRDT data operation to verify signature: {}",
                err
            ))
        })?;
        op.source.verify(&sig, &bytes_to_verify)?;

        let new_lseq = if let Some((policy_id, item_id)) = op.ctx {
            // policy op has a context/causality info,
            // let's check it's causally ready for applying
            if self.policy.find_entry(&policy_id).is_none() {
                // The policy is not causally ready, return an error
                // so the sender can retry later and/or send the missing ops
                return Err(Error::OpNotCausallyReady);
            } else {
                // Retrieve the LSeq corresponding to the Policy this op depends on,
                let lseq = self
                    .data
                    .get(&policy_id)
                    .ok_or(Error::CrdtUnexpectedState)?;

                // FIXME: Check that we actually have perms to be adding a new policy here, based on prev one...

                match item_id {
                    None => {
                        // The Policy doesn't depend on any item thus we copy the entire Sequence
                        lseq.clone()
                    }
                    Some(id) => {
                        // The Policy depends on specific item Id, create a copy with only
                        // items which Identifier is less than or equal to such Id.
                        // Note this logic is essentially copying the Sequence and undoing
                        // some Append ops which shall be filtered out based on their Id.
                        let actor = self.policy.actor();
                        let mut new_lseq =
                            LSeq::new_with_args(actor, LSEQ_TREE_BASE, LSEQ_BOUNDARY);

                        lseq.iter_entries().for_each(|entry| {
                            if entry.id <= id {
                                let op = Op::Insert {
                                    id: entry.id.clone(),
                                    dot: entry.dot.clone(),
                                    val: entry.val.clone(),
                                };
                                new_lseq.apply(op);
                            }
                        });

                        new_lseq
                    }
                }
            }
        } else {
            // Create an empty LSeq since there are no items yet for this Policy
            let actor = self.policy.actor();
            LSeq::new_with_args(actor, LSEQ_TREE_BASE, LSEQ_BOUNDARY)
        };

        let policy_id = op.crdt_op.id();
        if !self.data.contains_key(policy_id) {
            let _ = self.data.insert(policy_id.clone(), new_lseq);
        }

        // Apply the CRDT operation to the local replica of the policy
        self.policy.apply(op.crdt_op);

        Ok(())
    }
/// Apply a remote policy CRDT operation to this replica, keeping the current one in the history.
Apply a remote policy CRDT operation to this replica, keeping the current one in the history.
Apply a remote policy CRDT operation to this replica keeping the current one in the history .
pub fn apply_policy_op(&mut self, op: CrdtPolicyOperation<A, P>) -> Result<()> {
        // First check op is validly signed.
        // Note: Perms for the op are checked at the upper Sequence layer.
        let sig = op.signature.ok_or(Error::CrdtMissingOpSignature)?;
        let bytes_to_verify = utils::serialise(&op.crdt_op).map_err(|err| {
            Error::Serialisation(format!(
                "Could not serialise CRDT data operation to verify signature: {}",
                err
            ))
        })?;
        op.source.verify(&sig, &bytes_to_verify)?;
        let new_lseq = if let Some((policy_id, item_id)) = op.ctx {
            // policy op has a context/causality info,
            // let's check it's causally ready for applying
            if self.policy.find_entry(&policy_id).is_none() {
                // The policy is not causally ready, return an error
                // so the sender can retry later and/or send the missing ops
                return Err(Error::OpNotCausallyReady);
            } else {
                // Retrieve the LSeq corresponding to the Policy this op depends on,
                let lseq = self
                    .data
                    .get(&policy_id)
                    .ok_or(Error::CrdtUnexpectedState)?;
                // FIXME: Check that we actually have perms to be adding a new policy here, based on prev one...
                match item_id {
                    None => {
                        // The Policy doesn't depend on any item thus we copy the entire Sequence
                        lseq.clone()
                    }
                    Some(id) => {
                        // The Policy depends on specific item Id, create a copy with only
                        // items which Identifier is less than or equal to such Id.
                        // Note this logic is essentially copying the Sequence and undoing
                        // some Append ops which shall be filtered out based on their Id.
                        let actor = self.policy.actor();
                        let mut new_lseq =
                            LSeq::new_with_args(actor, LSEQ_TREE_BASE, LSEQ_BOUNDARY);
                        lseq.iter_entries().for_each(|entry| {
                            if entry.id <= id {
                                let op = Op::Insert {
                                    id: entry.id.clone(),
                                    dot: entry.dot.clone(),
                                    val: entry.val.clone(),
                                };
                                new_lseq.apply(op);
                            }
                        });
                        new_lseq
                    }
                }
            }
        } else {
            // Create an empty LSeq since there are no items yet for this Policy
            let actor = self.policy.actor();
            LSeq::new_with_args(actor, LSEQ_TREE_BASE, LSEQ_BOUNDARY)
        };
        let policy_id = op.crdt_op.id();
        if !self.data.contains_key(policy_id) {
            let _ = self.data.insert(policy_id.clone(), new_lseq);
        }
        // Apply the CRDT operation to the local replica of the policy
        self.policy.apply(op.crdt_op);
        Ok(())
    }
pub fn apply_policy_op ( & mut self , op : CrdtPolicyOperation < A , P > ) -> Result < ( ) > { // First check op is validly signed. // Note: Perms for the op are checked at the upper Sequence layer. let sig = op . signature . ok_or ( Error :: CrdtMissingOpSignature ) ? ; let bytes_to_verify = utils :: serialise ( & op . crdt_op ) . map_err ( | err | { Error :: Serialisation ( format ! ( " " err ) ) } ) ? ; op . source . verify ( & sig , & bytes_to_verify ) ? ; let new_lseq = if let Some ( ( policy_id , item_id ) ) = op . ctx { // policy op has a context/causality info, // let's check it's causally ready for applying if self . policy . find_entry ( & policy_id ) . is_none ( ) { // The policy is not causally ready, return an error // so the sender can retry later and/or send the missing ops return Err ( Error :: OpNotCausallyReady ) ; } else { // Retrieve the LSeq corresponding to the Policy this op depends on, let lseq = self . data . get ( & policy_id ) . ok_or ( Error :: CrdtUnexpectedState ) ? ; // FIXME: Check that we actually have perms to be adding a new policy here, based on prev one... match item_id { None => { // The Policy doesn't depend on any item thus we copy the entire Sequence lseq . clone ( ) } Some ( id ) => { // The Policy depends on specific item Id, create a copy with only // items which Identifier is less than or equal to such Id. // Note this logic is essentially copying the Sequence and undoing // some Append ops which shall be filtered out based on their Id. let actor = self . policy . actor ( ) ; let mut new_lseq = LSeq :: new_with_args ( actor , LSEQ_TREE_BASE , LSEQ_BOUNDARY ) ; lseq . iter_entries ( ) . for_each ( | entry | { if entry . id <= id { let op = Op :: Insert { id : entry . id . clone ( ) , dot : entry . dot . clone ( ) , val : entry . val . clone ( ) , } ; new_lseq . apply ( op ) ; } } ) ; new_lseq } } } } else { // Create an empty LSeq since there are no items yet for this Policy let actor = self . policy . actor ( ) ; LSeq :: new_with_args ( actor , LSEQ_TREE_BASE , LSEQ_BOUNDARY ) } ; let policy_id = op . crdt_op . id ( ) ; if ! self . data . contains_key ( policy_id ) { let _ = self . data . insert ( policy_id . clone ( ) , new_lseq ) ; } // Apply the CRDT operation to the local replica of the policy self . policy . apply ( op . crdt_op ) ; Ok ( ( ) ) }
Apply a remote policy CRDT operation to this replica, keeping the current one in the history.
Apply a remote policy CRDT operation to this replica keeping the current one in the history .
&mut self
op
CrdtPolicyOperation<A, P>
&mut self
op
CrdtPolicyOperation<A, P>