ink_storage_traits/storage.rs
1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use ink_primitives::Key;
16
17/// Trait for representing types which can be read and written to storage.
18///
19/// This trait is not the same as the [`scale::Codec`]. Each type that implements
20/// [`scale::Codec`] are storable by default and transferable between contracts.
21/// But not each storable type is transferable.
22pub trait Storable: Sized {
23 /// Convert self to a slice and append it to the destination.
24 fn encode<T: scale::Output + ?Sized>(&self, dest: &mut T);
25
26 /// Attempt to deserialize the value from input.
27 fn decode<I: scale::Input>(input: &mut I) -> Result<Self, scale::Error>;
28
29 /// The exact number of bytes this type consumes in the encoded form.
30 fn encoded_size(&self) -> usize;
31}
32
33/// Types which implement `scale::Encode` and `scale::Decode` are `Storable` by default
34/// because they can be written directly into the storage cell.
35impl<P> Storable for P
36where
37 P: scale::Codec,
38{
39 #[inline]
40 fn encode<T: scale::Output + ?Sized>(&self, dest: &mut T) {
41 scale::Encode::encode_to(self, dest)
42 }
43
44 #[inline]
45 fn decode<I: scale::Input>(input: &mut I) -> Result<Self, scale::Error> {
46 scale::Decode::decode(input)
47 }
48
49 #[inline]
50 fn encoded_size(&self) -> usize {
51 <P as scale::Encode>::encoded_size(self)
52 }
53}
54
55/// Decode and consume all the given input data.
56///
57/// If not all data is consumed, an error is returned.
58pub fn decode_all<T: Storable>(input: &mut &[u8]) -> Result<T, scale::Error> {
59 let res = <T as Storable>::decode(input)?;
60
61 if input.is_empty() {
62 Ok(res)
63 } else {
64 Err("Input buffer has still data left after decoding!".into())
65 }
66}
67
68pub(crate) mod private {
69 /// Seals the implementation of `Packed`.
70 pub trait Sealed {}
71}
72
73/// Trait for describing types that can be read and written to storage while all fields
74/// occupy only a single storage cell.
75///
76/// If at least one of the fields in the type occupies its own storage cell, this type
77/// is considered non-packed.
78///
79/// # Note
80///
81/// The trait is automatically implemented for types that implement [`scale::Codec`]
82/// via blanket implementation.
83#[diagnostic::on_unimplemented(
84 message = "expected `{Self}` to use a \"packed\" layout",
85 label = "`{Self}` does not currently use a \"packed\" layout",
86 note = "consider adding `#[ink::storage_item(packed)]` to `{Self}`",
87 note = "if `{Self}` is a standard library collection like `Vec<T>`, then consider adding `#[ink::storage_item(packed)]` to `T`",
88 note = "learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout"
89)]
90pub trait Packed: Storable + scale::Codec + private::Sealed {}
91
92/// Holds storage key for the type.
93///
94/// # Note
95///
96/// The trait is automatically implemented for [`Packed`] types
97/// via blanket implementation.
98pub trait StorageKey {
99 /// Storage key of the type.
100 const KEY: Key;
101
102 /// Returns the storage key.
103 fn key(&self) -> Key {
104 Self::KEY
105 }
106}
107
108/// Describes the type that should be used for storing the value and preferred storage
109/// key.
110///
111/// # Note
112///
113/// The trait is automatically implemented for [`Packed`] types
114/// via blanket implementation.
115pub trait StorableHint<Key: StorageKey> {
116 /// Storable type with storage key inside.
117 type Type: Storable;
118 /// The storage key that the type prefers. It can be overwritten by an auto-generated
119 /// storage key.
120 type PreferredKey: StorageKey;
121}
122
123/// Automatically returns the type that should be used for storing the value.
124///
125/// The trait is used by codegen to determine which storage key the type should have.
126pub trait AutoStorableHint<Key: StorageKey> {
127 /// Storable type with storage key inside.
128 type Type: Storable;
129}