Skip to main content

gear_common/
code_storage.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4use super::*;
5use crate::storage::MapStorage;
6use gear_core::code::{CodeAndId, CodeMetadata, InstrumentedCode, InstrumentedCodeAndMetadata};
7
8#[derive(Clone, Copy, Debug)]
9pub enum Error {
10    /// Code already exists in storage.
11    DuplicateItem,
12}
13
14/// Trait to work with program binary codes in a storage.
15pub trait CodeStorage {
16    type InstrumentedCodeMap: MapStorage<Key = CodeId, Value = InstrumentedCode>;
17    type OriginalCodeMap: MapStorage<Key = CodeId, Value = Vec<u8>>;
18    type CodeMetadataMap: MapStorage<Key = CodeId, Value = CodeMetadata>;
19
20    /// Attempt to remove all items from all the associated maps.
21    fn reset() {
22        Self::CodeMetadataMap::clear();
23        Self::OriginalCodeMap::clear();
24        Self::InstrumentedCodeMap::clear();
25    }
26
27    /// Add the code to the storage.
28    fn add_code(code_and_id: CodeAndId) -> Result<(), Error> {
29        let (code, code_id) = code_and_id.into_parts();
30        let (original_code, instrumented_code, code_metadata) = code.into_parts();
31
32        Self::OriginalCodeMap::mutate(code_id, |maybe| {
33            if maybe.is_some() {
34                return Err(CodeStorageError::DuplicateItem);
35            }
36
37            Self::InstrumentedCodeMap::insert(code_id, instrumented_code);
38            Self::CodeMetadataMap::insert(code_id, code_metadata);
39
40            *maybe = Some(original_code);
41            Ok(())
42        })
43    }
44
45    /// Update the corresponding code and metadata in the storage.
46    fn update_instrumented_code_and_metadata(
47        code_id: CodeId,
48        instrumented_code_and_metadata: InstrumentedCodeAndMetadata,
49    ) {
50        Self::InstrumentedCodeMap::insert(
51            code_id,
52            instrumented_code_and_metadata.instrumented_code,
53        );
54        Self::CodeMetadataMap::insert(code_id, instrumented_code_and_metadata.metadata);
55    }
56
57    /// Update the corresponding metadata in the storage.
58    fn update_code_metadata(code_id: CodeId, metadata: CodeMetadata) {
59        Self::CodeMetadataMap::insert(code_id, metadata);
60    }
61
62    /// Returns true if the original code associated with given id exists.
63    fn original_code_exists(code_id: CodeId) -> bool {
64        Self::OriginalCodeMap::contains_key(&code_id)
65    }
66
67    /// Returns true if the instrumented code associated with given id exists.
68    fn instrumented_code_exists(code_id: CodeId) -> bool {
69        Self::InstrumentedCodeMap::contains_key(&code_id)
70    }
71
72    /// Returns true if the code associated with given id was removed.
73    ///
74    /// If there is no code for the given id then false is returned.
75    fn remove_code(code_id: CodeId) -> bool {
76        Self::OriginalCodeMap::mutate(code_id, |maybe| {
77            if maybe.is_none() {
78                return false;
79            }
80
81            Self::InstrumentedCodeMap::remove(code_id);
82            Self::CodeMetadataMap::remove(code_id);
83
84            *maybe = None;
85            true
86        })
87    }
88
89    fn get_instrumented_code(code_id: CodeId) -> Option<InstrumentedCode> {
90        Self::InstrumentedCodeMap::get(&code_id)
91    }
92
93    fn get_original_code(code_id: CodeId) -> Option<Vec<u8>> {
94        Self::OriginalCodeMap::get(&code_id)
95    }
96
97    fn get_code_metadata(code_id: CodeId) -> Option<CodeMetadata> {
98        Self::CodeMetadataMap::get(&code_id)
99    }
100}