stellar_xdr/
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(_)
34 | ScVal::ExecutableTag(_) => Ok(()),
35
36 ScVal::Vec(Some(v)) => {
37 for e in v.iter() {
38 e.validate()?;
39 }
40 Ok(())
41 }
42
43 ScVal::Symbol(s) => {
44 if s.iter()
46 .all(|c| matches!(*c as char, '_' | '0'..='9' | 'A'..='Z' | 'a'..='z'))
47 {
48 Ok(())
49 } else {
50 Err(Error::Invalid)
51 }
52 }
53 ScVal::Vec(None) | ScVal::Map(None) => Err(Error::Invalid),
54 ScVal::Map(Some(m)) => m.validate(),
55 }
56 }
57}
58
59impl Validate for ScMap {
60 type Error = Error;
61
62 fn validate(&self) -> Result<(), Self::Error> {
63 for pair in self.iter() {
65 pair.key.validate()?;
66 pair.val.validate()?;
67 }
68 if self.windows(2).all(|w| w[0].key < w[1].key) {
71 Ok(())
72 } else {
73 Err(Error::Invalid)
74 }
75 }
76}
77
78#[cfg(test)]
79mod test {
80 use crate::ScSymbol;
81
82 use super::{Error, ScVal, Validate};
83
84 #[test]
85 fn symbol() {
86 assert_eq!(
87 ScVal::Symbol(ScSymbol("".try_into().unwrap())).validate(),
88 Ok(())
89 );
90 assert_eq!(
91 ScVal::Symbol(ScSymbol("a0A_".try_into().unwrap())).validate(),
92 Ok(())
93 );
94 assert_eq!(
95 ScVal::Symbol(ScSymbol("]".try_into().unwrap())).validate(),
96 Err(Error::Invalid)
97 );
98 }
99
100 #[test]
101 #[cfg(feature = "alloc")]
102 fn map() {
103 use super::super::{ScMap, ScMapEntry};
104 extern crate alloc;
105 use alloc::vec;
106 assert_eq!(
109 ScVal::Map(Some(ScMap(
110 vec![
111 ScMapEntry {
112 key: ScVal::I64(0),
113 val: ScVal::U32(1),
114 },
115 ScMapEntry {
116 key: ScVal::I64(1),
117 val: ScVal::I64(1),
118 }
119 ]
120 .try_into()
121 .unwrap()
122 )))
123 .validate(),
124 Ok(())
125 );
126 assert_eq!(
127 ScVal::Map(Some(ScMap(
128 vec![
129 ScMapEntry {
130 key: ScVal::I64(0),
131 val: ScVal::I64(1),
132 },
133 ScMapEntry {
134 key: ScVal::I64(1),
135 val: ScVal::I64(1),
136 }
137 ]
138 .try_into()
139 .unwrap()
140 )))
141 .validate(),
142 Ok(())
143 );
144 assert_eq!(
145 ScVal::Map(Some(ScMap(
146 vec![
147 ScMapEntry {
148 key: ScVal::I64(2),
149 val: ScVal::I64(1),
150 },
151 ScMapEntry {
152 key: ScVal::I64(1),
153 val: ScVal::I64(1),
154 }
155 ]
156 .try_into()
157 .unwrap()
158 )))
159 .validate(),
160 Err(Error::Invalid)
161 );
162 assert_eq!(
163 ScVal::Map(Some(ScMap(
164 vec![
165 ScMapEntry {
166 key: ScVal::I64(2),
167 val: ScVal::I64(1),
168 },
169 ScMapEntry {
170 key: ScVal::U32(1),
171 val: ScVal::I64(1),
172 },
173 ]
174 .try_into()
175 .unwrap()
176 )))
177 .validate(),
178 Err(Error::Invalid)
179 );
180 }
181}