sway_core/language/ty/expression/
storage.rs

1use super::TyExpression;
2use crate::{engine_threading::*, type_system::TypeId};
3use serde::{Deserialize, Serialize};
4use std::hash::{Hash, Hasher};
5use sway_types::{Ident, Span, Spanned};
6
7/// Describes the full storage access including all the subfields
8#[derive(Clone, Debug, Serialize, Deserialize)]
9pub struct TyStorageAccess {
10    pub fields: Vec<TyStorageAccessDescriptor>,
11    pub storage_field_names: Vec<String>,
12    pub struct_field_names: Vec<String>,
13    pub key_expression: Option<Box<TyExpression>>,
14    pub storage_keyword_span: Span,
15}
16
17impl EqWithEngines for TyStorageAccess {}
18impl PartialEqWithEngines for TyStorageAccess {
19    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
20        self.fields.len() == other.fields.len()
21            && self.fields.eq(&other.fields, ctx)
22            && self.storage_field_names.len() == other.storage_field_names.len()
23            && self.storage_field_names.eq(&other.storage_field_names)
24            && self.struct_field_names.len() == other.struct_field_names.len()
25            && self.struct_field_names.eq(&other.struct_field_names)
26            && self.key_expression.eq(&other.key_expression, ctx)
27    }
28}
29
30impl HashWithEngines for TyStorageAccess {
31    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
32        let TyStorageAccess {
33            fields,
34            storage_keyword_span,
35            storage_field_names,
36            struct_field_names,
37            key_expression,
38        } = self;
39        fields.hash(state, engines);
40        storage_field_names.hash(state);
41        struct_field_names.hash(state);
42        key_expression.hash(state, engines);
43        storage_keyword_span.hash(state);
44    }
45}
46
47impl Spanned for TyStorageAccess {
48    fn span(&self) -> Span {
49        // TODO: Use Span::join_all().
50        self.fields
51            .iter()
52            .fold(self.fields[0].span.clone(), |acc, field| {
53                Span::join(acc, &field.span)
54            })
55    }
56}
57
58impl TyStorageAccess {
59    pub fn storage_field_name(&self) -> Ident {
60        self.fields[0].name.clone()
61    }
62}
63
64/// Describes a single subfield access in the sequence when accessing a subfield within storage.
65#[derive(Clone, Debug, Serialize, Deserialize)]
66pub struct TyStorageAccessDescriptor {
67    pub name: Ident,
68    pub type_id: TypeId,
69    pub(crate) span: Span,
70}
71
72impl EqWithEngines for TyStorageAccessDescriptor {}
73impl PartialEqWithEngines for TyStorageAccessDescriptor {
74    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
75        let type_engine = ctx.engines().te();
76        self.name == other.name
77            && type_engine
78                .get(self.type_id)
79                .eq(&type_engine.get(other.type_id), ctx)
80    }
81}
82
83impl HashWithEngines for TyStorageAccessDescriptor {
84    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
85        let TyStorageAccessDescriptor {
86            name,
87            type_id,
88            // these fields are not hashed because they aren't relevant/a
89            // reliable source of obj v. obj distinction
90            span: _,
91        } = self;
92        let type_engine = engines.te();
93        name.hash(state);
94        type_engine.get(*type_id).hash(state, engines);
95    }
96}