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