diem_types/
write_set.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8//! For each transaction the VM executes, the VM will output a `WriteSet` that
9//! contains each access path it updates. For each access path, the VM can
10//! either give its new value or delete it.
11
12use crate::access_path::AccessPath;
13use anyhow::Result;
14use serde::{Deserialize, Serialize};
15
16#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
17pub enum WriteOp {
18    Deletion,
19    Value(#[serde(with = "serde_bytes")] Vec<u8>),
20}
21
22impl WriteOp {
23    #[inline]
24    pub fn is_deletion(&self) -> bool {
25        match self {
26            WriteOp::Deletion => true,
27            WriteOp::Value(_) => false,
28        }
29    }
30}
31
32impl std::fmt::Debug for WriteOp {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        match self {
35            WriteOp::Value(value) => write!(
36                f,
37                "Value({})",
38                value
39                    .iter()
40                    .map(|byte| format!("{:02x}", byte))
41                    .collect::<String>()
42            ),
43            WriteOp::Deletion => write!(f, "Deletion"),
44        }
45    }
46}
47
48/// `WriteSet` contains all access paths that one transaction modifies. Each of
49/// them is a `WriteOp` where `Value(val)` means that serialized representation
50/// should be updated to `val`, and `Deletion` means that we are going to delete
51/// this access path.
52#[derive(
53    Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize,
54)]
55pub struct WriteSet(WriteSetMut);
56
57impl WriteSet {
58    #[inline]
59    pub fn is_empty(&self) -> bool { self.0.is_empty() }
60
61    #[inline]
62    pub fn iter(&self) -> ::std::slice::Iter<'_, (AccessPath, WriteOp)> {
63        self.into_iter()
64    }
65
66    #[inline]
67    pub fn into_mut(self) -> WriteSetMut { self.0 }
68}
69
70/// A mutable version of `WriteSet`.
71///
72/// This is separate because it goes through validation before becoming an
73/// immutable `WriteSet`.
74#[derive(
75    Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize,
76)]
77pub struct WriteSetMut {
78    write_set: Vec<(AccessPath, WriteOp)>,
79}
80
81impl WriteSetMut {
82    pub fn new(write_set: Vec<(AccessPath, WriteOp)>) -> Self {
83        Self { write_set }
84    }
85
86    pub fn push(&mut self, item: (AccessPath, WriteOp)) {
87        self.write_set.push(item);
88    }
89
90    #[inline]
91    pub fn is_empty(&self) -> bool { self.write_set.is_empty() }
92
93    pub fn freeze(self) -> Result<WriteSet> {
94        // TODO: add structural validation
95        Ok(WriteSet(self))
96    }
97}
98
99impl ::std::iter::FromIterator<(AccessPath, WriteOp)> for WriteSetMut {
100    fn from_iter<I: IntoIterator<Item = (AccessPath, WriteOp)>>(
101        iter: I,
102    ) -> Self {
103        let mut ws = WriteSetMut::default();
104        for write in iter {
105            ws.push((write.0, write.1));
106        }
107        ws
108    }
109}
110
111impl<'a> IntoIterator for &'a WriteSet {
112    type IntoIter = ::std::slice::Iter<'a, (AccessPath, WriteOp)>;
113    type Item = &'a (AccessPath, WriteOp);
114
115    fn into_iter(self) -> Self::IntoIter { self.0.write_set.iter() }
116}
117
118impl ::std::iter::IntoIterator for WriteSet {
119    type IntoIter = ::std::vec::IntoIter<(AccessPath, WriteOp)>;
120    type Item = (AccessPath, WriteOp);
121
122    fn into_iter(self) -> Self::IntoIter { self.0.write_set.into_iter() }
123}