Skip to content
This repository was archived by the owner on Feb 28, 2025. It is now read-only.

Commit 3caa186

Browse files
committed
34: use From trait rather than ad hoc – final round of feedback
- code is more rust-like using From and into
1 parent 4342b61 commit 3caa186

File tree

2 files changed

+113
-48
lines changed

2 files changed

+113
-48
lines changed

lib/src/types/did_parser.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,7 @@ peg::parser! {
6464
= "0" i("x") digits:$(HEXDIG()+) ":" { Network::from(digits) }
6565

6666
rule network() -> Network
67-
// chain id networks
68-
= // named networks
69-
"mainnet:" { Network::Mainnet }
70-
/ "sepolia:" { Network::Sepolia }
71-
/ expected!("the only supported networks are `mainnet`, `sepolia`")
67+
= n:$(ALPHA()+) ":" { Network::from(n) }
7268

7369
rule account() -> Account
7470
= "0" i("x") digits:$(HEXDIG()*<40>) { Account::Address(Address::from_slice(&hex::decode(digits).unwrap())) }
@@ -338,6 +334,22 @@ mod tests {
338334
assert!(parsed.is_err());
339335
}
340336

337+
#[test]
338+
fn test_ethr_network_sepolia() {
339+
let parsed =
340+
parse_ethr_did("did:ethr:sepolia:0xb9c5714089478a327f09197987f16f9e5d936e8a").unwrap();
341+
assert_eq!(
342+
parsed,
343+
Did {
344+
method: Method::Ethr,
345+
network: Network::Sepolia,
346+
account: Account::Address(Address::from_slice(
347+
&hex::decode("b9c5714089478a327f09197987f16f9e5d936e8a").unwrap()
348+
))
349+
}
350+
);
351+
}
352+
341353
#[test]
342354
fn test_ethr_method_parser() {
343355
let parsed =
@@ -650,10 +662,10 @@ mod tests {
650662
assert_eq!(parsed.did.method, Method::Ethr);
651663
assert_eq!(parsed.did.network, Network::Mainnet);
652664
assert_eq!(
653-
parsed.did.account.to_address().unwrap(),
654665
Address::from_slice(
655666
&hex::decode(&"0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"[2..]).unwrap()
656-
)
667+
),
668+
parsed.did.account.into()
657669
);
658670
assert_eq!(parsed.path, Some("/a/b/c".to_string()));
659671
assert_eq!(parsed.query, None);

lib/src/types/did_url.rs

+94-41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Convenience Wrapper around [`Url`] for DID URIs according to the [DID Spec](https://www.w3.org/TR/did-core/#did-syntax)
22
3+
use std::default;
4+
35
use serde::{Deserialize, Serialize, Serializer};
46
use smart_default::SmartDefault;
57

@@ -18,6 +20,13 @@ fn public_key_to_address(key: &[u8]) -> String {
1820
format!("0x{}", hex::encode(address)).to_string()
1921
}
2022

23+
fn as_hex_digits(s: &str) -> &str {
24+
if s.starts_with("0x") {
25+
return s.strip_prefix("0x").unwrap();
26+
}
27+
s
28+
}
29+
2130
/// A DID URL, based on the did specification, [DID URL Syntax](https://www.w3.org/TR/did-core/#did-url-syntax)
2231
/// Currently only supports did:ethr: [did-ethr](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md)
2332
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -60,45 +69,49 @@ pub enum Account {
6069
HexKey(Vec<u8>),
6170
}
6271

63-
impl ToString for Account {
64-
fn to_string(&self) -> String {
65-
match self {
66-
Account::Address(addr) => format!("0x{}", hex::encode(addr.as_bytes())),
67-
Account::HexKey(key) => hex::encode(key).to_string(),
68-
}
72+
impl From<Address> for Account {
73+
fn from(addr: Address) -> Self {
74+
Account::Address(addr)
6975
}
7076
}
7177

72-
impl Account {
73-
pub fn from_hex_key(key: Vec<u8>) -> Self {
78+
impl From<Vec<u8>> for Account {
79+
fn from(key: Vec<u8>) -> Self {
7480
Account::HexKey(key)
7581
}
82+
}
7683

77-
pub fn from_address(addr: Address) -> Self {
78-
Account::Address(addr)
79-
}
80-
81-
pub fn from_string(s: &str) -> Self {
84+
impl From<&str> for Account {
85+
fn from(s: &str) -> Self {
8286
if s.starts_with("0x") {
83-
let hexes = s.strip_prefix("0x").unwrap();
84-
Account::Address(Address::from_slice(&hex::decode(hexes).unwrap()))
87+
Account::Address(Address::from_slice(&hex::decode(as_hex_digits(s)).unwrap()))
8588
} else {
8689
Account::HexKey(hex::decode(s).unwrap())
8790
}
8891
}
92+
}
8993

90-
pub fn to_address(&self) -> Option<Address> {
91-
match self {
92-
Account::Address(addr) => Some(*addr),
94+
impl From<Account> for Address {
95+
fn from(account: Account) -> Self {
96+
match account {
97+
Account::Address(addr) => addr,
9398
Account::HexKey(key) => {
94-
let addr = public_key_to_address(key);
95-
let hexes = addr.strip_prefix("0x").unwrap();
96-
Some(Address::from_slice(&hex::decode(hexes).unwrap()))
99+
let addr = public_key_to_address(&key);
100+
Address::from_slice(&hex::decode(as_hex_digits(&addr)).unwrap())
97101
}
98102
}
99103
}
100104
}
101105

106+
impl ToString for Account {
107+
fn to_string(&self) -> String {
108+
match self {
109+
Account::Address(addr) => format!("0x{}", hex::encode(addr.as_bytes())),
110+
Account::HexKey(key) => hex::encode(key).to_string(),
111+
}
112+
}
113+
}
114+
102115
#[derive(Debug, Clone, PartialEq, Eq, SmartDefault)]
103116
pub enum Method {
104117
#[default]
@@ -136,10 +149,8 @@ impl ToString for Network {
136149
}
137150
}
138151

139-
impl<'a> From<&'a str> for Network {
140-
fn from(chain_id: &'a str) -> Network {
141-
let chain_id = usize::from_str_radix(chain_id, 16).expect("String must be valid Hex");
142-
152+
impl From<usize> for Network {
153+
fn from(chain_id: usize) -> Network {
143154
match chain_id {
144155
1 => Network::Mainnet,
145156
#[allow(deprecated)]
@@ -150,6 +161,22 @@ impl<'a> From<&'a str> for Network {
150161
}
151162
}
152163

164+
impl<'a> From<&'a str> for Network {
165+
fn from(network: &'a str) -> Network {
166+
match network.to_lowercase().as_str() {
167+
"mainnet" => Network::Mainnet,
168+
#[allow(deprecated)]
169+
"goerli" => Network::Goerli,
170+
"sepolia" => Network::Sepolia,
171+
_ => {
172+
let chain_id = usize::from_str_radix(as_hex_digits(network), 16)
173+
.expect("String must be valid Hex");
174+
Network::from(chain_id)
175+
}
176+
}
177+
}
178+
}
179+
153180
impl DidUrl {
154181
/// Parses a Decentralized Identifier (DID) URI string.
155182
///
@@ -601,31 +628,29 @@ mod tests {
601628

602629
#[test]
603630
fn test_account_from_string() {
604-
let account = Account::from_string("0xb9c5714089478a327f09197987f16f9e5d936e8a");
631+
let account = Account::from("0xb9c5714089478a327f09197987f16f9e5d936e8a");
605632
assert_eq!(
606633
account,
607634
Account::Address(address("0xb9c5714089478a327f09197987f16f9e5d936e8a"))
608635
);
609636

610637
let account =
611-
Account::from_string("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
612-
assert_eq!(
613-
account.to_address().unwrap(),
614-
Account::Address(address("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"))
615-
.to_address()
616-
.unwrap()
617-
);
638+
Account::from("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
639+
let eth_address: Address = account.into();
640+
let expect_address: Address =
641+
Account::Address(address("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf")).into();
642+
assert_eq!(expect_address, eth_address);
618643
}
619644

620645
#[test]
621646
fn test_account_from_hex_key() {
622-
let account = Account::from_hex_key(vec![0x01, 0x02, 0x03]);
647+
let account = Account::from(vec![0x01, 0x02, 0x03]);
623648
assert_eq!(account, Account::HexKey(vec![0x01, 0x02, 0x03]));
624649
}
625650

626651
#[test]
627652
fn test_account_from_address() {
628-
let account = Account::from_address(address("0xb9c5714089478a327f09197987f16f9e5d936e8a"));
653+
let account = Account::from(address("0xb9c5714089478a327f09197987f16f9e5d936e8a"));
629654
assert_eq!(
630655
account,
631656
Account::Address(address("0xb9c5714089478a327f09197987f16f9e5d936e8a"))
@@ -636,18 +661,18 @@ mod tests {
636661
fn test_account_to_address_conversion() {
637662
let account = Account::Address(address("0xb9c5714089478a327f09197987f16f9e5d936e8a"));
638663
assert_eq!(
639-
account.to_address().unwrap(),
640664
Address::from_slice(
641-
&hex::decode(&"0xb9c5714089478a327f09197987f16f9e5d936e8a"[2..]).unwrap()
642-
)
665+
&hex::decode(as_hex_digits("0xb9c5714089478a327f09197987f16f9e5d936e8a")).unwrap()
666+
),
667+
account.into()
643668
);
644669

645670
let account = Account::HexKey(hex::decode("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap().to_vec());
646671
assert_eq!(
647-
account.to_address().unwrap(),
648672
Address::from_slice(
649-
&hex::decode(&"0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"[2..]).unwrap()
650-
)
673+
&hex::decode(as_hex_digits("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf")).unwrap()
674+
),
675+
account.into()
651676
);
652677
}
653678

@@ -661,4 +686,32 @@ mod tests {
661686
"0x7e5f4552091a69125d5dfcb7b8c2659029395bdf".to_string()
662687
);
663688
}
689+
690+
#[test]
691+
fn test_as_hex_str() {
692+
let address = "0x7e575682A8E450E33eB0493f9972821aE333cd7F";
693+
assert_eq!(
694+
as_hex_digits(address),
695+
"7e575682A8E450E33eB0493f9972821aE333cd7F"
696+
);
697+
let public_key = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8";
698+
assert_eq!(
699+
as_hex_digits(public_key),
700+
"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"
701+
);
702+
}
703+
704+
#[test]
705+
fn test_network_from_usize() {
706+
assert_eq!(Network::from(1), Network::Mainnet);
707+
assert_eq!(Network::from(11155111), Network::Sepolia);
708+
assert_eq!(Network::from(0x1a1), Network::Other(0x1a1));
709+
}
710+
711+
#[test]
712+
fn test_network_from_str() {
713+
assert_eq!(Network::from("mainnet"), Network::Mainnet);
714+
assert_eq!(Network::from("sepolia"), Network::Sepolia);
715+
assert_eq!(Network::from("1a1"), Network::Other(0x1a1));
716+
}
664717
}

0 commit comments

Comments
 (0)