frame_decode/methods/
mod.rs

1// Copyright (C) 2022-2025 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the frame-decode crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16pub mod constant_decoder;
17pub mod constant_type_info;
18pub mod custom_value_decoder;
19pub mod custom_value_type_info;
20pub mod extrinsic_decoder;
21pub mod extrinsic_type_info;
22pub mod runtime_api_decoder;
23pub mod runtime_api_encoder;
24pub mod runtime_api_type_info;
25pub mod storage_decoder;
26pub mod storage_encoder;
27pub mod storage_type_info;
28pub mod view_function_decoder;
29pub mod view_function_encoder;
30pub mod view_function_type_info;
31
32use alloc::borrow::Cow;
33
34/// This represents either an entry name, or the name of the thing that the entry is
35/// in (for instance the name of a pallet or of a Runtime API trait).
36///
37/// Iterators returning this will iterate containers in order, first returning
38/// [`Entry::In`] to communicate which container (eg pallet or Runtime API trait) is being
39/// iterated over next, and then a [`Entry::Name`]s for the name of each of the entries in
40/// the given container.
41///
42/// A container name will not be handed back more than once.
43#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
44pub enum Entry<'info> {
45    /// The name of the thing that the following entries are in/under.
46    In(Cow<'info, str>),
47    /// The name of the entry in/under the last given [`Entry::In`].
48    Name(Cow<'info, str>),
49}
50
51impl<'info> Entry<'info> {
52    /// Take ownership of the entry, converting any lifetimes to `'static`.
53    pub fn into_owned(self) -> Entry<'static> {
54        match self {
55            Entry::In(name) => Entry::In(Cow::Owned(name.into_owned())),
56            Entry::Name(name) => Entry::Name(Cow::Owned(name.into_owned())),
57        }
58    }
59
60    /// Iterate over all of the entries in a specific container (ie all of the entries
61    /// which follow a specific [`Entry::In`]).
62    pub fn entries_in<'a>(
63        entries: impl Iterator<Item = Entry<'a>>,
64        container: &str,
65    ) -> impl Iterator<Item = Cow<'a, str>> {
66        entries
67            .skip_while(|c| c != &Entry::In(Cow::Borrowed(container)))
68            .skip(1)
69            .take_while(|c| matches!(c, Entry::Name(_)))
70            .filter_map(|c| match c {
71                Entry::In(_) => None,
72                Entry::Name(name) => Some(name),
73            })
74    }
75}
76
77#[cfg(test)]
78mod test {
79    use super::*;
80
81    #[test]
82    fn test_entries_in() {
83        fn entries() -> impl Iterator<Item = Entry<'static>> {
84            [
85                Entry::In("Baz".into()),
86                Entry::In("Foo".into()),
87                Entry::Name("foo_a".into()),
88                Entry::Name("foo_b".into()),
89                Entry::Name("foo_c".into()),
90                Entry::In("Bar".into()),
91                Entry::Name("bar_a".into()),
92                Entry::In("Wibble".into()),
93            ]
94            .into_iter()
95        }
96
97        assert!(Entry::entries_in(entries(), "Baz").next().is_none());
98        assert!(Entry::entries_in(entries(), "Wibble").next().is_none());
99
100        let foos: Vec<String> = Entry::entries_in(entries(), "Foo")
101            .map(|s| s.into_owned())
102            .collect();
103        assert_eq!(
104            foos,
105            Vec::from_iter(["foo_a".to_owned(), "foo_b".to_owned(), "foo_c".to_owned(),])
106        );
107
108        let bars: Vec<String> = Entry::entries_in(entries(), "Bar")
109            .map(|s| s.into_owned())
110            .collect();
111        assert_eq!(bars, Vec::from_iter(["bar_a".to_owned(),]));
112    }
113}