pro_metadata/
specs.rs

1// Copyright 2018-2021 Parity Technologies (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
15#![allow(clippy::new_ret_no_self)]
16
17use crate::serde_hex;
18#[cfg(not(feature = "std"))]
19use alloc::{
20    format,
21    vec,
22    vec::Vec,
23};
24use core::marker::PhantomData;
25use tetsy_scale_info::{
26    form::{
27        Form,
28        MetaForm,
29        PortableForm,
30    },
31    meta_type,
32    IntoPortable,
33    Registry,
34    TypeInfo,
35};
36use serde::{
37    de::DeserializeOwned,
38    Deserialize,
39    Serialize,
40};
41
42/// Describes a contract.
43#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(bound(
45    serialize = "F::Type: Serialize, F::String: Serialize",
46    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
47))]
48pub struct ContractSpec<F: Form = MetaForm> {
49    /// The set of constructors of the contract.
50    constructors: Vec<ConstructorSpec<F>>,
51    /// The external messages of the contract.
52    messages: Vec<MessageSpec<F>>,
53    /// The events of the contract.
54    events: Vec<EventSpec<F>>,
55    /// The contract documentation.
56    docs: Vec<F::String>,
57}
58
59impl IntoPortable for ContractSpec {
60    type Output = ContractSpec<PortableForm>;
61
62    fn into_portable(self, registry: &mut Registry) -> Self::Output {
63        ContractSpec {
64            constructors: self
65                .constructors
66                .into_iter()
67                .map(|constructor| constructor.into_portable(registry))
68                .collect::<Vec<_>>(),
69            messages: self
70                .messages
71                .into_iter()
72                .map(|msg| msg.into_portable(registry))
73                .collect::<Vec<_>>(),
74            events: self
75                .events
76                .into_iter()
77                .map(|event| event.into_portable(registry))
78                .collect::<Vec<_>>(),
79            docs: registry.map_into_portable(self.docs),
80        }
81    }
82}
83
84impl<F> ContractSpec<F>
85where
86    F: Form,
87{
88    /// Returns the set of constructors of the contract.
89    pub fn constructors(&self) -> &[ConstructorSpec<F>] {
90        &self.constructors
91    }
92
93    /// Returns the external messages of the contract.
94    pub fn messages(&self) -> &[MessageSpec<F>] {
95        &self.messages
96    }
97
98    /// Returns the events of the contract.
99    pub fn events(&self) -> &[EventSpec<F>] {
100        &self.events
101    }
102
103    /// Returns the contract documentation.
104    pub fn docs(&self) -> &[F::String] {
105        &self.docs
106    }
107}
108
109/// The message builder is ready to finalize construction.
110pub enum Valid {}
111/// The message builder is not ready to finalize construction.
112pub enum Invalid {}
113
114/// A builder for contracts.
115pub struct ContractSpecBuilder<S = Invalid> {
116    /// The to-be-constructed contract specification.
117    spec: ContractSpec,
118    /// Marker for compile-time checking of valid contract specifications.
119    marker: PhantomData<fn() -> S>,
120}
121
122impl ContractSpecBuilder<Invalid> {
123    /// Sets the constructors of the contract specification.
124    pub fn constructors<C>(self, constructors: C) -> ContractSpecBuilder<Valid>
125    where
126        C: IntoIterator<Item = ConstructorSpec>,
127    {
128        debug_assert!(self.spec.constructors.is_empty());
129        ContractSpecBuilder {
130            spec: ContractSpec {
131                constructors: constructors.into_iter().collect::<Vec<_>>(),
132                ..self.spec
133            },
134            marker: Default::default(),
135        }
136    }
137}
138
139impl<S> ContractSpecBuilder<S> {
140    /// Sets the messages of the contract specification.
141    pub fn messages<M>(self, messages: M) -> Self
142    where
143        M: IntoIterator<Item = MessageSpec>,
144    {
145        debug_assert!(self.spec.messages.is_empty());
146        Self {
147            spec: ContractSpec {
148                messages: messages.into_iter().collect::<Vec<_>>(),
149                ..self.spec
150            },
151            ..self
152        }
153    }
154
155    /// Sets the events of the contract specification.
156    pub fn events<E>(self, events: E) -> Self
157    where
158        E: IntoIterator<Item = EventSpec>,
159    {
160        debug_assert!(self.spec.events.is_empty());
161        Self {
162            spec: ContractSpec {
163                events: events.into_iter().collect::<Vec<_>>(),
164                ..self.spec
165            },
166            ..self
167        }
168    }
169
170    /// Sets the documentation of the contract specification.
171    pub fn docs<D>(self, docs: D) -> Self
172    where
173        D: IntoIterator<Item = &'static str>,
174    {
175        debug_assert!(self.spec.docs.is_empty());
176        Self {
177            spec: ContractSpec {
178                docs: docs.into_iter().collect::<Vec<_>>(),
179                ..self.spec
180            },
181            ..self
182        }
183    }
184}
185
186impl ContractSpecBuilder<Valid> {
187    /// Finalizes construction of the contract specification.
188    pub fn done(self) -> ContractSpec {
189        assert!(
190            !self.spec.constructors.is_empty(),
191            "must have at least one constructor"
192        );
193        assert!(
194            !self.spec.messages.is_empty(),
195            "must have at least one message"
196        );
197        self.spec
198    }
199}
200
201impl ContractSpec {
202    /// Creates a new contract specification.
203    pub fn new() -> ContractSpecBuilder {
204        ContractSpecBuilder {
205            spec: Self {
206                constructors: Vec::new(),
207                messages: Vec::new(),
208                events: Vec::new(),
209                docs: Vec::new(),
210            },
211            marker: PhantomData,
212        }
213    }
214}
215
216/// Describes a constructor of a contract.
217#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
218#[serde(bound(
219    serialize = "F::Type: Serialize, F::String: Serialize",
220    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
221))]
222pub struct ConstructorSpec<F: Form = MetaForm> {
223    /// The name of the message.
224    ///
225    /// In case of a trait provided constructor the trait name is prefixed.
226    pub name: Vec<F::String>,
227    /// The selector hash of the message.
228    pub selector: Selector,
229    /// The parameters of the deploy handler.
230    pub args: Vec<MessageParamSpec<F>>,
231    /// The deploy handler documentation.
232    pub docs: Vec<F::String>,
233}
234
235impl IntoPortable for ConstructorSpec {
236    type Output = ConstructorSpec<PortableForm>;
237
238    fn into_portable(self, registry: &mut Registry) -> Self::Output {
239        ConstructorSpec {
240            name: registry.map_into_portable(self.name),
241            selector: self.selector,
242            args: self
243                .args
244                .into_iter()
245                .map(|arg| arg.into_portable(registry))
246                .collect::<Vec<_>>(),
247            docs: registry.map_into_portable(self.docs),
248        }
249    }
250}
251
252impl<F> ConstructorSpec<F>
253where
254    F: Form,
255{
256    /// Returns the name of the message.
257    ///
258    /// In case of a trait provided constructor the trait name is prefixed.
259    pub fn name(&self) -> &[F::String] {
260        &self.name
261    }
262
263    /// Returns the selector hash of the message.
264    pub fn selector(&self) -> &Selector {
265        &self.selector
266    }
267
268    /// Returns the parameters of the deploy handler.
269    pub fn args(&self) -> &[MessageParamSpec<F>] {
270        &self.args
271    }
272
273    /// Returns the deploy handler documentation.
274    pub fn docs(&self) -> &[F::String] {
275        &self.docs
276    }
277}
278
279/// A builder for constructors.
280///
281/// # Dev
282///
283/// Some of the fields are guarded by a type-state pattern to
284/// fail at compile-time instead of at run-time. This is useful
285/// to better debug code-gen macros.
286pub struct ConstructorSpecBuilder<Selector> {
287    spec: ConstructorSpec,
288    marker: PhantomData<fn() -> Selector>,
289}
290
291impl ConstructorSpec {
292    /// Creates a new constructor spec builder.
293    fn from_name_segments(
294        segments: Vec<&'static str>,
295    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
296        ConstructorSpecBuilder {
297            spec: Self {
298                name: segments,
299                selector: Selector::default(),
300                args: Vec::new(),
301                docs: Vec::new(),
302            },
303            marker: PhantomData,
304        }
305    }
306
307    /// Creates a new constructor spec builder.
308    pub fn from_name(
309        name: &'static str,
310    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
311        Self::from_name_segments(vec![name])
312    }
313
314    /// Creates a new constructor spec builder for a trait provided constructor.
315    pub fn from_trait_and_name(
316        trait_name: &'static str,
317        constructor_name: &'static str,
318    ) -> ConstructorSpecBuilder<Missing<state::Selector>> {
319        Self::from_name_segments(vec![trait_name, constructor_name])
320    }
321}
322
323impl ConstructorSpecBuilder<Missing<state::Selector>> {
324    /// Sets the function selector of the message.
325    pub fn selector(self, selector: [u8; 4]) -> ConstructorSpecBuilder<state::Selector> {
326        ConstructorSpecBuilder {
327            spec: ConstructorSpec {
328                selector: selector.into(),
329                ..self.spec
330            },
331            marker: PhantomData,
332        }
333    }
334}
335
336impl<S> ConstructorSpecBuilder<S> {
337    /// Sets the input arguments of the message specification.
338    pub fn args<A>(self, args: A) -> Self
339    where
340        A: IntoIterator<Item = MessageParamSpec>,
341    {
342        let mut this = self;
343        debug_assert!(this.spec.args.is_empty());
344        this.spec.args = args.into_iter().collect::<Vec<_>>();
345        this
346    }
347
348    /// Sets the documentation of the message specification.
349    pub fn docs<D>(self, docs: D) -> Self
350    where
351        D: IntoIterator<Item = &'static str>,
352    {
353        let mut this = self;
354        debug_assert!(this.spec.docs.is_empty());
355        this.spec.docs = docs.into_iter().map(str::trim).collect::<Vec<_>>();
356        this
357    }
358}
359
360impl ConstructorSpecBuilder<state::Selector> {
361    /// Finishes construction of the constructor.
362    pub fn done(self) -> ConstructorSpec {
363        self.spec
364    }
365}
366
367/// Describes a contract message.
368#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
369#[serde(bound(
370    serialize = "F::Type: Serialize, F::String: Serialize",
371    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
372))]
373#[serde(rename_all = "camelCase")]
374pub struct MessageSpec<F: Form = MetaForm> {
375    /// The name of the message and some optional prefixes.
376    ///
377    /// In case of trait provided messages and constructors the prefix
378    /// by convention in pro! is the name of the trait.
379    name: Vec<F::String>,
380    /// The selector hash of the message.
381    selector: Selector,
382    /// If the message is allowed to mutate the contract state.
383    mutates: bool,
384    /// If the message is payable by the caller.
385    payable: bool,
386    /// The parameters of the message.
387    args: Vec<MessageParamSpec<F>>,
388    /// The return type of the message.
389    return_type: ReturnTypeSpec<F>,
390    /// The message documentation.
391    docs: Vec<F::String>,
392}
393
394/// Type state for builders to tell that some mandatory state has not yet been set
395/// yet or to fail upon setting the same state multiple times.
396pub struct Missing<S>(PhantomData<fn() -> S>);
397
398mod state {
399    //! Type states that tell what state of a message has not
400    //! yet been set properly for a valid construction.
401
402    /// Type state for the message selector of a message.
403    pub struct Selector;
404    /// Type state for the mutability of a message.
405    pub struct Mutates;
406    /// Type state for telling if the message is payable.
407    pub struct IsPayable;
408    /// Type state for the return type of a message.
409    pub struct Returns;
410}
411
412impl MessageSpec {
413    /// Creates a new message spec from the given name segments.
414    fn from_name_segments(
415        segments: Vec<&'static str>,
416    ) -> MessageSpecBuilder<
417        Missing<state::Selector>,
418        Missing<state::Mutates>,
419        Missing<state::IsPayable>,
420        Missing<state::Returns>,
421    > {
422        MessageSpecBuilder {
423            spec: Self {
424                name: segments,
425                selector: Selector::default(),
426                mutates: false,
427                payable: false,
428                args: Vec::new(),
429                return_type: ReturnTypeSpec::new(None),
430                docs: Vec::new(),
431            },
432            marker: PhantomData,
433        }
434    }
435
436    /// Creates a new message spec builder.
437    pub fn from_name(
438        name: &'static str,
439    ) -> MessageSpecBuilder<
440        Missing<state::Selector>,
441        Missing<state::Mutates>,
442        Missing<state::IsPayable>,
443        Missing<state::Returns>,
444    > {
445        Self::from_name_segments(vec![name])
446    }
447
448    /// Creates a new message spec builder for a trait provided message.
449    pub fn from_trait_and_name(
450        trait_name: &'static str,
451        message_name: &'static str,
452    ) -> MessageSpecBuilder<
453        Missing<state::Selector>,
454        Missing<state::Mutates>,
455        Missing<state::IsPayable>,
456        Missing<state::Returns>,
457    > {
458        Self::from_name_segments(vec![trait_name, message_name])
459    }
460}
461
462impl<F> MessageSpec<F>
463where
464    F: Form,
465{
466    /// Returns the name of the message and some optional prefixes.
467    ///
468    /// In case of trait provided messages and constructors the prefix
469    /// by convention in pro! is the name of the trait.
470    pub fn name(&self) -> &[F::String] {
471        &self.name
472    }
473
474    /// Returns the selector hash of the message.
475    pub fn selector(&self) -> &Selector {
476        &self.selector
477    }
478
479    /// Returns true if the message is allowed to mutate the contract state.
480    pub fn mutates(&self) -> bool {
481        self.mutates
482    }
483
484    /// Returns true if the message is payable by the caller.
485    pub fn payable(&self) -> bool {
486        self.payable
487    }
488
489    /// Returns the parameters of the message.
490    pub fn args(&self) -> &[MessageParamSpec<F>] {
491        &self.args
492    }
493
494    /// Returns the return type of the message.
495    pub fn return_type(&self) -> &ReturnTypeSpec<F> {
496        &self.return_type
497    }
498
499    /// Returns the message documentation.
500    pub fn docs(&self) -> &[F::String] {
501        &self.docs
502    }
503}
504
505/// A builder for messages.
506///
507/// # Dev
508///
509/// Some of the fields are guarded by a type-state pattern to
510/// fail at compile-time instead of at run-time. This is useful
511/// to better debug code-gen macros.
512#[allow(clippy::type_complexity)]
513pub struct MessageSpecBuilder<Selector, Mutates, IsPayable, Returns> {
514    spec: MessageSpec,
515    marker: PhantomData<fn() -> (Selector, Mutates, IsPayable, Returns)>,
516}
517
518impl<M, P, R> MessageSpecBuilder<Missing<state::Selector>, M, P, R> {
519    /// Sets the function selector of the message.
520    pub fn selector(
521        self,
522        selector: [u8; 4],
523    ) -> MessageSpecBuilder<state::Selector, M, P, R> {
524        MessageSpecBuilder {
525            spec: MessageSpec {
526                selector: selector.into(),
527                ..self.spec
528            },
529            marker: PhantomData,
530        }
531    }
532}
533
534impl<S, P, R> MessageSpecBuilder<S, Missing<state::Mutates>, P, R> {
535    /// Sets if the message is mutable, thus taking `&mut self` or not thus taking `&self`.
536    pub fn mutates(self, mutates: bool) -> MessageSpecBuilder<S, state::Mutates, P, R> {
537        MessageSpecBuilder {
538            spec: MessageSpec {
539                mutates,
540                ..self.spec
541            },
542            marker: PhantomData,
543        }
544    }
545}
546
547impl<S, M, R> MessageSpecBuilder<S, M, Missing<state::IsPayable>, R> {
548    /// Sets if the message is mutable, thus taking `&mut self` or not thus taking `&self`.
549    pub fn payable(
550        self,
551        is_payable: bool,
552    ) -> MessageSpecBuilder<S, M, state::IsPayable, R> {
553        MessageSpecBuilder {
554            spec: MessageSpec {
555                payable: is_payable,
556                ..self.spec
557            },
558            marker: PhantomData,
559        }
560    }
561}
562
563impl<M, S, P> MessageSpecBuilder<S, M, P, Missing<state::Returns>> {
564    /// Sets the return type of the message.
565    pub fn returns(
566        self,
567        return_type: ReturnTypeSpec,
568    ) -> MessageSpecBuilder<S, M, P, state::Returns> {
569        MessageSpecBuilder {
570            spec: MessageSpec {
571                return_type,
572                ..self.spec
573            },
574            marker: PhantomData,
575        }
576    }
577}
578
579impl<S, M, P, R> MessageSpecBuilder<S, M, P, R> {
580    /// Sets the input arguments of the message specification.
581    pub fn args<A>(self, args: A) -> Self
582    where
583        A: IntoIterator<Item = MessageParamSpec>,
584    {
585        let mut this = self;
586        debug_assert!(this.spec.args.is_empty());
587        this.spec.args = args.into_iter().collect::<Vec<_>>();
588        this
589    }
590
591    /// Sets the documentation of the message specification.
592    pub fn docs<D>(self, docs: D) -> Self
593    where
594        D: IntoIterator<Item = &'static str>,
595    {
596        let mut this = self;
597        debug_assert!(this.spec.docs.is_empty());
598        this.spec.docs = docs.into_iter().collect::<Vec<_>>();
599        this
600    }
601}
602
603impl
604    MessageSpecBuilder<state::Selector, state::Mutates, state::IsPayable, state::Returns>
605{
606    /// Finishes construction of the message.
607    pub fn done(self) -> MessageSpec {
608        self.spec
609    }
610}
611
612impl IntoPortable for MessageSpec {
613    type Output = MessageSpec<PortableForm>;
614
615    fn into_portable(self, registry: &mut Registry) -> Self::Output {
616        MessageSpec {
617            name: registry.map_into_portable(self.name),
618            selector: self.selector,
619            mutates: self.mutates,
620            payable: self.payable,
621            args: self
622                .args
623                .into_iter()
624                .map(|arg| arg.into_portable(registry))
625                .collect::<Vec<_>>(),
626            return_type: self.return_type.into_portable(registry),
627            docs: registry.map_into_portable(self.docs),
628        }
629    }
630}
631
632/// Describes an event definition.
633#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
634#[serde(bound(
635    serialize = "F::Type: Serialize, F::String: Serialize",
636    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
637))]
638pub struct EventSpec<F: Form = MetaForm> {
639    /// The name of the event.
640    name: F::String,
641    /// The event arguments.
642    args: Vec<EventParamSpec<F>>,
643    /// The event documentation.
644    docs: Vec<F::String>,
645}
646
647/// An event specification builder.
648pub struct EventSpecBuilder {
649    spec: EventSpec,
650}
651
652impl EventSpecBuilder {
653    /// Sets the input arguments of the event specification.
654    pub fn args<A>(self, args: A) -> Self
655    where
656        A: IntoIterator<Item = EventParamSpec>,
657    {
658        let mut this = self;
659        debug_assert!(this.spec.args.is_empty());
660        this.spec.args = args.into_iter().collect::<Vec<_>>();
661        this
662    }
663
664    /// Sets the input arguments of the event specification.
665    pub fn docs<D>(self, docs: D) -> Self
666    where
667        D: IntoIterator<Item = &'static str>,
668    {
669        let mut this = self;
670        debug_assert!(this.spec.docs.is_empty());
671        this.spec.docs = docs.into_iter().collect::<Vec<_>>();
672        this
673    }
674
675    /// Finalizes building the event specification.
676    pub fn done(self) -> EventSpec {
677        self.spec
678    }
679}
680
681impl IntoPortable for EventSpec {
682    type Output = EventSpec<PortableForm>;
683
684    fn into_portable(self, registry: &mut Registry) -> Self::Output {
685        EventSpec {
686            name: self.name.into_portable(registry),
687            args: self
688                .args
689                .into_iter()
690                .map(|arg| arg.into_portable(registry))
691                .collect::<Vec<_>>(),
692            docs: registry.map_into_portable(self.docs),
693        }
694    }
695}
696
697impl EventSpec {
698    /// Creates a new event specification builder.
699    pub fn new(name: &'static str) -> EventSpecBuilder {
700        EventSpecBuilder {
701            spec: Self {
702                name,
703                args: Vec::new(),
704                docs: Vec::new(),
705            },
706        }
707    }
708}
709
710impl<F> EventSpec<F>
711where
712    F: Form,
713{
714    /// Returns the name of the event.
715    pub fn name(&self) -> &F::String {
716        &self.name
717    }
718
719    /// The event arguments.
720    pub fn args(&self) -> &[EventParamSpec<F>] {
721        &self.args
722    }
723
724    /// The event documentation.
725    pub fn docs(&self) -> &[F::String] {
726        &self.docs
727    }
728}
729
730/// The 4 byte selector to identify constructors and messages
731#[derive(Debug, Default, PartialEq, Eq, derive_more::From)]
732pub struct Selector([u8; 4]);
733
734impl serde::Serialize for Selector {
735    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
736    where
737        S: serde::Serializer,
738    {
739        serde_hex::serialize(&self.0, serializer)
740    }
741}
742
743impl<'de> serde::Deserialize<'de> for Selector {
744    fn deserialize<D>(d: D) -> Result<Self, D::Error>
745    where
746        D: serde::Deserializer<'de>,
747    {
748        let mut arr = [0; 4];
749        serde_hex::deserialize_check_len(d, serde_hex::ExpectedLen::Exact(&mut arr[..]))?;
750        Ok(arr.into())
751    }
752}
753
754impl Selector {
755    /// Returns the underlying selector bytes.
756    pub fn to_bytes(&self) -> &[u8] {
757        &self.0
758    }
759}
760
761/// Describes the syntactical name of a type at a given type position.
762///
763/// This is important when trying to work with type aliases.
764/// Normally a type alias is transparent and so scenarios such as
765/// ```no_compile
766/// type Foo = i32;
767/// fn bar(foo: Foo);
768/// ```
769/// Will only communicate that `foo` is of type `i32` which is correct,
770/// however, it will miss the potentially important information that it
771/// is being used through a type alias named `Foo`.
772///
773/// In pro! we current experience this problem with environmental types
774/// such as the `Balance` type that is just a type alias to `u128` in the
775/// default setup. Even though it would be useful for third party tools
776/// such as the Polkadot UI to know that we are handling with `Balance`
777/// types, we currently cannot communicate this without display names.
778pub type DisplayName<F> = tetsy_scale_info::Path<F>;
779
780/// A type specification.
781///
782/// This contains the actual type as well as an optional compile-time
783/// known displayed representation of the type. This is useful for cases
784/// where the type is used through a type alias in order to provide
785/// information about the alias name.
786///
787/// # Examples
788///
789/// Consider the following Rust function:
790/// ```no_compile
791/// fn is_sorted(input: &[i32], pred: Predicate) -> bool;
792/// ```
793/// In this above example `input` would have no displayable name,
794/// `pred`'s display name is `Predicate` and the display name of
795/// the return type is simply `bool`. Note that `Predicate` could
796/// simply be a type alias to `fn(i32, i32) -> Ordering`.
797#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
798#[serde(bound(
799    serialize = "F::Type: Serialize, F::String: Serialize",
800    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
801))]
802#[serde(rename_all = "camelCase")]
803pub struct TypeSpec<F: Form = MetaForm> {
804    /// The actual type.
805    #[serde(rename = "type")]
806    ty: F::Type,
807    /// The compile-time known displayed representation of the type.
808    display_name: DisplayName<F>,
809}
810
811impl IntoPortable for TypeSpec {
812    type Output = TypeSpec<PortableForm>;
813
814    fn into_portable(self, registry: &mut Registry) -> Self::Output {
815        TypeSpec {
816            ty: registry.register_type(&self.ty),
817            display_name: self.display_name.into_portable(registry),
818        }
819    }
820}
821
822impl TypeSpec {
823    /// Creates a new type specification with a display name.
824    ///
825    /// The name is any valid Rust identifier or path.
826    ///
827    /// # Examples
828    ///
829    /// Valid display names are `foo`, `foo::bar`, `foo::bar::Baz`, etc.
830    ///
831    /// # Panics
832    ///
833    /// Panics if the given display name is invalid.
834    pub fn with_name_str<T>(display_name: &'static str) -> Self
835    where
836        T: TypeInfo + 'static,
837    {
838        Self::with_name_segs::<T, _>(display_name.split("::"))
839    }
840
841    /// Creates a new type specification with a display name
842    /// represented by the given path segments.
843    ///
844    /// The display name segments all must be valid Rust identifiers.
845    ///
846    /// # Examples
847    ///
848    /// Valid display names are `foo`, `foo::bar`, `foo::bar::Baz`, etc.
849    ///
850    /// # Panics
851    ///
852    /// Panics if the given display name is invalid.
853    pub fn with_name_segs<T, S>(segments: S) -> Self
854    where
855        T: TypeInfo + 'static,
856        S: IntoIterator<Item = &'static str>,
857    {
858        Self {
859            ty: meta_type::<T>(),
860            display_name: DisplayName::from_segments(segments)
861                .expect("display name is invalid"),
862        }
863    }
864
865    /// Creates a new type specification without a display name.
866    pub fn new<T>() -> Self
867    where
868        T: TypeInfo + 'static,
869    {
870        Self {
871            ty: meta_type::<T>(),
872            display_name: DisplayName::default(),
873        }
874    }
875}
876
877impl<F> TypeSpec<F>
878where
879    F: Form,
880{
881    /// Returns the actual type.
882    pub fn ty(&self) -> &F::Type {
883        &self.ty
884    }
885
886    /// Returns the compile-time known displayed representation of the type.
887    pub fn display_name(&self) -> &DisplayName<F> {
888        &self.display_name
889    }
890}
891
892/// Describes a pair of parameter name and type.
893#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
894#[serde(bound(
895    serialize = "F::Type: Serialize, F::String: Serialize",
896    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
897))]
898pub struct EventParamSpec<F: Form = MetaForm> {
899    /// The name of the parameter.
900    name: F::String,
901    /// If the event parameter is indexed.
902    indexed: bool,
903    /// The type of the parameter.
904    #[serde(rename = "type")]
905    ty: TypeSpec<F>,
906    /// The documentation associated with the arguments.
907    docs: Vec<F::String>,
908}
909
910impl IntoPortable for EventParamSpec {
911    type Output = EventParamSpec<PortableForm>;
912
913    fn into_portable(self, registry: &mut Registry) -> Self::Output {
914        EventParamSpec {
915            name: self.name.into_portable(registry),
916            indexed: self.indexed,
917            ty: self.ty.into_portable(registry),
918            docs: registry.map_into_portable(self.docs),
919        }
920    }
921}
922
923impl EventParamSpec {
924    /// Creates a new event parameter specification builder.
925    pub fn new(name: &'static str) -> EventParamSpecBuilder {
926        EventParamSpecBuilder {
927            spec: Self {
928                name,
929                // By default event parameters are not indexed.
930                indexed: false,
931                // We initialize every parameter type as `()`.
932                ty: TypeSpec::new::<()>(),
933                // We start with empty docs.
934                docs: vec![],
935            },
936        }
937    }
938}
939
940impl<F> EventParamSpec<F>
941where
942    F: Form,
943{
944    /// Returns the name of the parameter.
945    pub fn name(&self) -> &F::String {
946        &self.name
947    }
948
949    /// Returns true if the event parameter is indexed.
950    pub fn indexed(&self) -> bool {
951        self.indexed
952    }
953
954    /// Returns the type of the parameter.
955    pub fn ty(&self) -> &TypeSpec<F> {
956        &self.ty
957    }
958
959    /// Returns the documentation associated with the arguments.
960    pub fn docs(&self) -> &[F::String] {
961        &self.docs
962    }
963}
964
965/// Used to construct an event parameter specification.
966pub struct EventParamSpecBuilder {
967    /// The built-up event parameter specification.
968    spec: EventParamSpec,
969}
970
971impl EventParamSpecBuilder {
972    /// Sets the type of the event parameter.
973    pub fn of_type(self, spec: TypeSpec) -> Self {
974        let mut this = self;
975        this.spec.ty = spec;
976        this
977    }
978
979    /// If the event parameter is indexed.
980    pub fn indexed(self, is_indexed: bool) -> Self {
981        let mut this = self;
982        this.spec.indexed = is_indexed;
983        this
984    }
985
986    /// Sets the documentation of the event parameter.
987    pub fn docs<D>(self, docs: D) -> Self
988    where
989        D: IntoIterator<Item = &'static str>,
990    {
991        debug_assert!(self.spec.docs.is_empty());
992        Self {
993            spec: EventParamSpec {
994                docs: docs.into_iter().collect::<Vec<_>>(),
995                ..self.spec
996            },
997        }
998    }
999
1000    /// Finishes constructing the event parameter spec.
1001    pub fn done(self) -> EventParamSpec {
1002        self.spec
1003    }
1004}
1005
1006/// Describes the return type of a contract message.
1007#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1008#[serde(transparent)]
1009#[serde(bound(
1010    serialize = "F::Type: Serialize, F::String: Serialize",
1011    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1012))]
1013pub struct ReturnTypeSpec<F: Form = MetaForm> {
1014    #[serde(rename = "type")]
1015    opt_type: Option<TypeSpec<F>>,
1016}
1017
1018impl IntoPortable for ReturnTypeSpec {
1019    type Output = ReturnTypeSpec<PortableForm>;
1020
1021    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1022        ReturnTypeSpec {
1023            opt_type: self
1024                .opt_type
1025                .map(|opt_type| opt_type.into_portable(registry)),
1026        }
1027    }
1028}
1029
1030impl ReturnTypeSpec {
1031    /// Creates a new return type specification from the given type or `None`.
1032    ///
1033    /// # Examples
1034    ///
1035    /// ```no_run
1036    /// # use pro_metadata::{TypeSpec, ReturnTypeSpec};
1037    /// ReturnTypeSpec::new(None); // no return type;
1038    /// ReturnTypeSpec::new(TypeSpec::new::<i32>()); // return type of `i32`
1039    /// ```
1040    pub fn new<T>(ty: T) -> Self
1041    where
1042        T: Into<Option<TypeSpec>>,
1043    {
1044        Self {
1045            opt_type: ty.into(),
1046        }
1047    }
1048}
1049
1050impl<F> ReturnTypeSpec<F>
1051where
1052    F: Form,
1053{
1054    /// Returns the optional return type
1055    pub fn opt_type(&self) -> Option<&TypeSpec<F>> {
1056        self.opt_type.as_ref()
1057    }
1058}
1059
1060/// Describes a pair of parameter name and type.
1061#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
1062#[serde(bound(
1063    serialize = "F::Type: Serialize, F::String: Serialize",
1064    deserialize = "F::Type: DeserializeOwned, F::String: DeserializeOwned"
1065))]
1066pub struct MessageParamSpec<F: Form = MetaForm> {
1067    /// The name of the parameter.
1068    name: F::String,
1069    /// The type of the parameter.
1070    #[serde(rename = "type")]
1071    ty: TypeSpec<F>,
1072}
1073
1074impl IntoPortable for MessageParamSpec {
1075    type Output = MessageParamSpec<PortableForm>;
1076
1077    fn into_portable(self, registry: &mut Registry) -> Self::Output {
1078        MessageParamSpec {
1079            name: self.name.into_portable(registry),
1080            ty: self.ty.into_portable(registry),
1081        }
1082    }
1083}
1084
1085impl MessageParamSpec {
1086    /// Constructs a new message parameter specification via builder.
1087    pub fn new(name: &'static str) -> MessageParamSpecBuilder {
1088        MessageParamSpecBuilder {
1089            spec: Self {
1090                name,
1091                // Uses `()` type by default.
1092                ty: TypeSpec::new::<()>(),
1093            },
1094        }
1095    }
1096}
1097
1098impl<F> MessageParamSpec<F>
1099where
1100    F: Form,
1101{
1102    /// Returns the name of the parameter.
1103    pub fn name(&self) -> &F::String {
1104        &self.name
1105    }
1106
1107    /// Returns the type of the parameter.
1108    pub fn ty(&self) -> &TypeSpec<F> {
1109        &self.ty
1110    }
1111}
1112
1113/// Used to construct a message parameter specification.
1114pub struct MessageParamSpecBuilder {
1115    /// The to-be-constructed message parameter specification.
1116    spec: MessageParamSpec,
1117}
1118
1119impl MessageParamSpecBuilder {
1120    /// Sets the type of the message parameter.
1121    pub fn of_type(self, ty: TypeSpec) -> Self {
1122        let mut this = self;
1123        this.spec.ty = ty;
1124        this
1125    }
1126
1127    /// Finishes construction of the message parameter.
1128    pub fn done(self) -> MessageParamSpec {
1129        self.spec
1130    }
1131}