contract_transcode/scon/
mod.rs

1// Copyright (C) Use Ink (UK) Ltd.
2// This file is part of cargo-contract.
3//
4// cargo-contract is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// cargo-contract is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with cargo-contract.  If not, see <http://www.gnu.org/licenses/>.
16
17//! SCALE Object Notation (SCON)
18
19mod display;
20mod parse;
21
22use indexmap::IndexMap;
23
24use crate::util;
25use std::{
26    cmp::{
27        Eq,
28        Ordering,
29    },
30    hash::{
31        Hash,
32        Hasher,
33    },
34    iter::FromIterator,
35    ops::{
36        Index,
37        IndexMut,
38    },
39    str::FromStr,
40};
41
42use serde::{
43    ser::SerializeMap,
44    Serialize,
45};
46
47pub use self::parse::parse_value;
48
49#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
50pub enum Value {
51    Bool(bool),
52    Char(char),
53    UInt(u128),
54    Int(i128),
55    Map(Map),
56    Tuple(Tuple),
57    String(String),
58    Seq(Seq),
59    Hex(Hex),
60    Literal(String),
61    Unit,
62}
63
64#[derive(Clone, Debug)]
65pub struct Map {
66    ident: Option<String>,
67    map: IndexMap<Value, Value>,
68}
69
70// `IndexMap` is defined outside and can not be made serializable.
71// Therefore, we implement custom implementation for the wrapping `Map`
72impl Serialize for Map {
73    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74    where
75        S: serde::Serializer,
76    {
77        let mut map = serializer.serialize_map(Some(self.map.len()))?;
78        for (k, v) in &self.map {
79            // we need to convert the key to a string
80            // because serde_json disallows non-string keys
81            map.serialize_entry(&k.to_string(), v)?;
82        }
83        map.end()
84    }
85}
86
87impl Eq for Map {}
88
89impl Hash for Map {
90    fn hash<H: Hasher>(&self, state: &mut H) {
91        self.iter().for_each(|x| x.hash(state));
92    }
93}
94
95impl Index<&Value> for Map {
96    type Output = Value;
97
98    fn index(&self, index: &Value) -> &Self::Output {
99        &self.map[index]
100    }
101}
102
103impl IndexMut<&Value> for Map {
104    fn index_mut(&mut self, index: &Value) -> &mut Self::Output {
105        self.map.get_mut(index).expect("no entry found for key")
106    }
107}
108
109impl Ord for Map {
110    fn cmp(&self, other: &Map) -> Ordering {
111        self.iter().cmp(other.iter())
112    }
113}
114
115/// Note: equality is only given if both values and order of values match
116impl PartialEq for Map {
117    fn eq(&self, other: &Map) -> bool {
118        if self.map.len() != other.map.len() {
119            return false
120        }
121        self.iter().zip(other.iter()).all(|(a, b)| a == b)
122    }
123}
124
125impl PartialOrd for Map {
126    fn partial_cmp(&self, other: &Map) -> Option<Ordering> {
127        Some(self.cmp(other))
128    }
129}
130
131impl FromIterator<(Value, Value)> for Map {
132    fn from_iter<T: IntoIterator<Item = (Value, Value)>>(iter: T) -> Self {
133        Map::new(None, IndexMap::from_iter(iter))
134    }
135}
136
137impl Map {
138    /// Creates a new, empty `Map`.
139    pub fn new(ident: Option<&str>, map: IndexMap<Value, Value>) -> Map {
140        Map {
141            ident: ident.map(|s| s.to_string()),
142            map,
143        }
144    }
145
146    /// Return the identifier of the [`Map`].
147    pub fn ident(&self) -> Option<String> {
148        self.ident.clone()
149    }
150
151    /// Iterate all key-value pairs.
152    pub fn iter(&self) -> impl DoubleEndedIterator<Item = (&Value, &Value)> {
153        self.map.iter()
154    }
155
156    /// Return an iterator over the map's values
157    pub fn values(&self) -> impl Iterator<Item = &Value> {
158        self.map.values()
159    }
160
161    /// Return a reference to the value stored for string key, if it is present, else
162    /// None.
163    pub fn get_by_str(&self, key: &str) -> Option<&Value> {
164        self.map.get(&Value::String(key.to_string()))
165    }
166}
167
168#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
169pub struct Tuple {
170    ident: Option<String>,
171    values: Vec<Value>,
172}
173
174impl From<Vec<Value>> for Tuple {
175    fn from(values: Vec<Value>) -> Self {
176        Tuple {
177            ident: None,
178            values,
179        }
180    }
181}
182
183impl Tuple {
184    pub fn new(ident: Option<&str>, values: Vec<Value>) -> Self {
185        Tuple {
186            ident: ident.map(|s| s.into()),
187            values,
188        }
189    }
190
191    pub fn ident(&self) -> Option<String> {
192        self.ident.clone()
193    }
194
195    /// Returns an iterator over the tuple's values
196    pub fn values(&self) -> impl Iterator<Item = &Value> {
197        self.values.iter()
198    }
199}
200
201#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
202pub struct Seq {
203    elems: Vec<Value>,
204}
205
206impl From<Vec<Value>> for Seq {
207    fn from(elems: Vec<Value>) -> Self {
208        Self::new(elems)
209    }
210}
211
212impl Seq {
213    pub fn new(elems: Vec<Value>) -> Self {
214        Seq { elems }
215    }
216
217    pub fn elems(&self) -> &[Value] {
218        &self.elems
219    }
220
221    pub fn len(&self) -> usize {
222        self.elems.len()
223    }
224}
225
226#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
227pub struct Hex {
228    s: String,
229    #[serde(skip_serializing)]
230    bytes: Vec<u8>,
231}
232
233impl FromStr for Hex {
234    type Err = hex::FromHexError;
235
236    fn from_str(s: &str) -> Result<Self, Self::Err> {
237        let s = s.trim_start_matches("0x").to_string();
238        let bytes = util::decode_hex(&s)?;
239        Ok(Self { s, bytes })
240    }
241}
242
243impl Hex {
244    pub fn as_str(&self) -> &str {
245        &self.s
246    }
247
248    pub fn bytes(&self) -> &[u8] {
249        &self.bytes
250    }
251}