stellar_xdr/curr/
scval_validations.rs1#![allow(clippy::missing_errors_doc)]
2
3use super::{Error, ScMap, ScVal};
4
5pub trait Validate {
6 type Error;
7 fn validate(&self) -> Result<(), Self::Error>;
8}
9
10impl Validate for ScVal {
11 type Error = Error;
12
13 fn validate(&self) -> Result<(), <Self as Validate>::Error> {
14 match self {
15 ScVal::U32(_)
16 | ScVal::I32(_)
17 | ScVal::Error(_)
18 | ScVal::Bool(_)
19 | ScVal::Void
20 | ScVal::U64(_)
21 | ScVal::I64(_)
22 | ScVal::Timepoint(_)
23 | ScVal::Duration(_)
24 | ScVal::U128(_)
25 | ScVal::I128(_)
26 | ScVal::U256(_)
27 | ScVal::I256(_)
28 | ScVal::Bytes(_)
29 | ScVal::String(_)
30 | ScVal::Address(_)
31 | ScVal::LedgerKeyContractInstance
32 | ScVal::LedgerKeyNonce(_)
33 | ScVal::ContractInstance(_) => Ok(()),
34
35 ScVal::Vec(Some(v)) => {
36 for e in v.iter() {
37 e.validate()?;
38 }
39 Ok(())
40 }
41
42 ScVal::Symbol(s) => {
43 if s.iter()
45 .all(|c| matches!(*c as char, '_' | '0'..='9' | 'A'..='Z' | 'a'..='z'))
46 {
47 Ok(())
48 } else {
49 Err(Error::Invalid)
50 }
51 }
52 ScVal::Vec(None) | ScVal::Map(None) => Err(Error::Invalid),
53 ScVal::Map(Some(m)) => m.validate(),
54 }
55 }
56}
57
58impl Validate for ScMap {
59 type Error = Error;
60
61 fn validate(&self) -> Result<(), Self::Error> {
62 for pair in self.iter() {
64 pair.key.validate()?;
65 pair.val.validate()?;
66 }
67 if self.windows(2).all(|w| w[0].key < w[1].key) {
70 Ok(())
71 } else {
72 Err(Error::Invalid)
73 }
74 }
75}
76
77#[cfg(test)]
78mod test {
79 use crate::curr::ScSymbol;
80
81 use super::{Error, ScVal, Validate};
82
83 #[test]
84 fn symbol() {
85 assert_eq!(
86 ScVal::Symbol(ScSymbol("".try_into().unwrap())).validate(),
87 Ok(())
88 );
89 assert_eq!(
90 ScVal::Symbol(ScSymbol("a0A_".try_into().unwrap())).validate(),
91 Ok(())
92 );
93 assert_eq!(
94 ScVal::Symbol(ScSymbol("]".try_into().unwrap())).validate(),
95 Err(Error::Invalid)
96 );
97 }
98
99 #[test]
100 #[cfg(feature = "alloc")]
101 fn map() {
102 use super::super::{ScMap, ScMapEntry};
103 extern crate alloc;
104 use alloc::vec;
105 assert_eq!(
108 ScVal::Map(Some(ScMap(
109 vec![
110 ScMapEntry {
111 key: ScVal::I64(0),
112 val: ScVal::U32(1),
113 },
114 ScMapEntry {
115 key: ScVal::I64(1),
116 val: ScVal::I64(1),
117 }
118 ]
119 .try_into()
120 .unwrap()
121 )))
122 .validate(),
123 Ok(())
124 );
125 assert_eq!(
126 ScVal::Map(Some(ScMap(
127 vec![
128 ScMapEntry {
129 key: ScVal::I64(0),
130 val: ScVal::I64(1),
131 },
132 ScMapEntry {
133 key: ScVal::I64(1),
134 val: ScVal::I64(1),
135 }
136 ]
137 .try_into()
138 .unwrap()
139 )))
140 .validate(),
141 Ok(())
142 );
143 assert_eq!(
144 ScVal::Map(Some(ScMap(
145 vec![
146 ScMapEntry {
147 key: ScVal::I64(2),
148 val: ScVal::I64(1),
149 },
150 ScMapEntry {
151 key: ScVal::I64(1),
152 val: ScVal::I64(1),
153 }
154 ]
155 .try_into()
156 .unwrap()
157 )))
158 .validate(),
159 Err(Error::Invalid)
160 );
161 assert_eq!(
162 ScVal::Map(Some(ScMap(
163 vec![
164 ScMapEntry {
165 key: ScVal::I64(2),
166 val: ScVal::I64(1),
167 },
168 ScMapEntry {
169 key: ScVal::U32(1),
170 val: ScVal::I64(1),
171 },
172 ]
173 .try_into()
174 .unwrap()
175 )))
176 .validate(),
177 Err(Error::Invalid)
178 );
179 }
180}