1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use borsh::{BorshDeserialize, BorshSerialize};
use serde::Serialize;
use std::convert::{TryFrom, TryInto};
use crate::env::is_valid_account_id;
use crate::AccountId;
#[derive(
Debug, Clone, PartialEq, PartialOrd, Ord, Eq, BorshDeserialize, BorshSerialize, Serialize,
)]
pub struct ValidAccountId(AccountId);
impl ValidAccountId {
fn is_valid(&self) -> bool {
is_valid_account_id(&self.0.as_bytes())
}
}
impl AsRef<AccountId> for ValidAccountId {
fn as_ref(&self) -> &AccountId {
&self.0
}
}
impl<'de> serde::Deserialize<'de> for ValidAccountId {
fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
where
D: serde::Deserializer<'de>,
{
let s = <String as serde::Deserialize>::deserialize(deserializer)?;
s.try_into()
.map_err(|err: Box<dyn std::error::Error>| serde::de::Error::custom(err.to_string()))
}
}
impl TryFrom<&str> for ValidAccountId {
type Error = Box<dyn std::error::Error>;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::try_from(value.to_string())
}
}
impl TryFrom<String> for ValidAccountId {
type Error = Box<dyn std::error::Error>;
fn try_from(value: String) -> Result<Self, Self::Error> {
let res = Self(value);
if res.is_valid() {
Ok(res)
} else {
Err("The account ID is invalid".into())
}
}
}
impl From<ValidAccountId> for AccountId {
fn from(value: ValidAccountId) -> Self {
value.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::convert::TryInto;
#[test]
fn test_deser() {
let key: ValidAccountId = serde_json::from_str("\"alice.near\"").unwrap();
assert_eq!(key.0, "alice.near".to_string());
let key: Result<ValidAccountId, _> = serde_json::from_str("Alice.near");
assert!(key.is_err());
}
#[test]
fn test_ser() {
let key: ValidAccountId = "alice.near".try_into().unwrap();
let actual: String = serde_json::to_string(&key).unwrap();
assert_eq!(actual, "\"alice.near\"");
}
#[test]
fn test_from_str() {
let key = ValidAccountId::try_from("alice.near").unwrap();
assert_eq!(key.as_ref(), &"alice.near".to_string());
}
}