diem_types/
access_path.rs1use crate::account_address::AccountAddress;
39use diem_crypto::hash::HashValue;
40use move_core_types::language_storage::{ModuleId, ResourceKey, StructTag, CODE_TAG, RESOURCE_TAG};
41#[cfg(any(test, feature = "fuzzing"))]
42use proptest_derive::Arbitrary;
43use serde::{Deserialize, Serialize};
44use std::{convert::TryFrom, fmt};
45
46#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
47#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
48pub struct AccessPath {
49 pub address: AccountAddress,
50 #[serde(with = "serde_bytes")]
51 pub path: Vec<u8>,
52}
53
54#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
55pub enum Path {
56 Code(ModuleId),
57 Resource(StructTag),
58}
59
60impl AccessPath {
61 pub fn new(address: AccountAddress, path: Vec<u8>) -> Self {
62 AccessPath { address, path }
63 }
64
65 pub fn resource_access_vec(tag: StructTag) -> Vec<u8> {
66 bcs::to_bytes(&Path::Resource(tag)).expect("Unexpected serialization error")
67 }
68
69 pub fn resource_access_path(key: ResourceKey) -> AccessPath {
72 let path = AccessPath::resource_access_vec(key.type_);
73 AccessPath {
74 address: key.address,
75 path,
76 }
77 }
78
79 fn code_access_path_vec(key: ModuleId) -> Vec<u8> {
80 bcs::to_bytes(&Path::Code(key)).expect("Unexpected serialization error")
81 }
82
83 pub fn code_access_path(key: ModuleId) -> AccessPath {
84 let address = *key.address();
85 let path = AccessPath::code_access_path_vec(key);
86 AccessPath { address, path }
87 }
88
89 pub fn get_path(&self) -> Path {
91 bcs::from_bytes::<Path>(&self.path).expect("Unexpected serialization error")
92 }
93
94 pub fn get_struct_tag(&self) -> Option<StructTag> {
97 match self.get_path() {
98 Path::Resource(s) => Some(s),
99 Path::Code(_) => None,
100 }
101 }
102}
103
104impl fmt::Debug for AccessPath {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
106 write!(
107 f,
108 "AccessPath {{ address: {:x}, path: {} }}",
109 self.address,
110 hex::encode(&self.path)
111 )
112 }
113}
114
115impl fmt::Display for AccessPath {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 if self.path.len() < 1 + HashValue::LENGTH {
118 write!(f, "{:?}", self)
119 } else {
120 write!(f, "AccessPath {{ address: {:x}, ", self.address)?;
121 match self.path[0] {
122 RESOURCE_TAG => write!(f, "type: Resource, ")?,
123 CODE_TAG => write!(f, "type: Module, ")?,
124 tag => write!(f, "type: {:?}, ", tag)?,
125 };
126 write!(
127 f,
128 "hash: {:?}, ",
129 hex::encode(&self.path[1..=HashValue::LENGTH])
130 )?;
131 write!(
132 f,
133 "suffix: {:?} }} ",
134 String::from_utf8_lossy(&self.path[1 + HashValue::LENGTH..])
135 )
136 }
137 }
138}
139
140impl From<&ModuleId> for AccessPath {
141 fn from(id: &ModuleId) -> AccessPath {
142 AccessPath {
143 address: *id.address(),
144 path: id.access_vector(),
145 }
146 }
147}
148
149impl TryFrom<&[u8]> for Path {
150 type Error = bcs::Error;
151
152 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
153 bcs::from_bytes::<Path>(bytes)
154 }
155}
156
157impl TryFrom<&Vec<u8>> for Path {
158 type Error = bcs::Error;
159
160 fn try_from(bytes: &Vec<u8>) -> Result<Self, Self::Error> {
161 bcs::from_bytes::<Path>(bytes)
162 }
163}