Live video on the AT Protocol
1use std::{fmt, str::FromStr};
2
3use snafu::Snafu;
4
5#[derive(Debug, Snafu, uniffi::Error)]
6#[snafu(module)]
7pub enum PublicKeyError {
8 Length { size: u64 },
9 Invalid { message: String },
10}
11
12/// A public key.
13///
14/// The key itself is just a 32 byte array, but a key has associated crypto
15/// information that is cached for performance reasons.
16#[derive(Clone, Copy, Eq, Ord, PartialOrd, uniffi::Object)]
17#[uniffi::export(Display)]
18pub struct PublicKey {
19 pub(crate) key: [u8; 32],
20}
21
22impl fmt::Debug for PublicKey {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 iroh::PublicKey::from(self).fmt(f)
25 }
26}
27
28impl From<iroh::PublicKey> for PublicKey {
29 fn from(key: iroh::PublicKey) -> Self {
30 PublicKey {
31 key: *key.as_bytes(),
32 }
33 }
34}
35
36impl From<&PublicKey> for iroh::PublicKey {
37 fn from(key: &PublicKey) -> Self {
38 iroh::PublicKey::from_bytes(&key.key).unwrap()
39 }
40}
41
42#[uniffi::export]
43impl PublicKey {
44 /// Returns true if the PublicKeys are equal
45 pub fn equal(&self, other: &PublicKey) -> bool {
46 *self == *other
47 }
48
49 /// Express the PublicKey as a byte array
50 pub fn as_vec(&self) -> Vec<u8> {
51 self.key.to_vec()
52 }
53
54 /// Make a PublicKey from base32 string
55 #[uniffi::constructor]
56 #[allow(clippy::result_large_err)]
57 pub fn from_string(s: String) -> Result<Self, PublicKeyError> {
58 if s.len() != 64 {
59 return Err(PublicKeyError::Length {
60 size: s.len() as u64,
61 });
62 }
63 let key = iroh::PublicKey::from_str(&s).map_err(|e| PublicKeyError::Invalid {
64 message: e.to_string(),
65 })?;
66 Ok(key.into())
67 }
68
69 /// Make a PublicKey from byte array
70 #[uniffi::constructor]
71 #[allow(clippy::result_large_err)]
72 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, PublicKeyError> {
73 if bytes.len() != 32 {
74 return Err(PublicKeyError::Length {
75 size: bytes.len() as u64,
76 });
77 }
78 let bytes: [u8; 32] = bytes.try_into().expect("checked above");
79 let key = iroh::PublicKey::from_bytes(&bytes).map_err(|e| PublicKeyError::Invalid {
80 message: e.to_string(),
81 })?;
82 Ok(key.into())
83 }
84
85 /// Convert to a base32 string limited to the first 10 bytes for a friendly string
86 /// representation of the key.
87 pub fn fmt_short(&self) -> String {
88 iroh::PublicKey::from(self).fmt_short()
89 }
90}
91
92impl PartialEq for PublicKey {
93 fn eq(&self, other: &PublicKey) -> bool {
94 self.key == other.key
95 }
96}
97
98impl fmt::Display for PublicKey {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 iroh::PublicKey::from(self).fmt(f)
101 }
102}