ouisync/protocol/
repository.rs1use crate::crypto::{
2 sign::{self, PublicKey},
3 Digest, Hash, Hashable,
4};
5use serde::{Deserialize, Serialize};
6use std::str::FromStr;
7
8#[derive(PartialEq, Eq, Hash, Clone, Debug, Copy, Serialize, Deserialize)]
9#[repr(transparent)]
10#[serde(transparent)]
11pub struct RepositoryId(PublicKey);
12
13derive_sqlx_traits_for_byte_array_wrapper!(RepositoryId);
14
15impl RepositoryId {
16 pub const SIZE: usize = PublicKey::SIZE;
17
18 #[cfg(test)]
19 pub fn generate<R: rand::Rng + rand::CryptoRng>(rng: &mut R) -> Self {
20 crate::crypto::sign::Keypair::generate(rng)
21 .public_key()
22 .into()
23 }
24
25 #[cfg(test)]
26 pub fn random() -> Self {
27 Self::generate(&mut rand::rngs::OsRng)
28 }
29
30 pub fn salted_hash(&self, salt: &[u8]) -> Hash {
32 (self, salt).hash()
33 }
34
35 pub fn write_public_key(&self) -> &PublicKey {
36 &self.0
37 }
38}
39
40impl FromStr for RepositoryId {
41 type Err = sign::ParseError;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 Ok(Self(PublicKey::from_str(s)?))
45 }
46}
47
48impl AsRef<[u8]> for RepositoryId {
49 fn as_ref(&self) -> &[u8] {
50 self.0.as_ref()
51 }
52}
53
54impl TryFrom<&'_ [u8]> for RepositoryId {
55 type Error = sign::SignatureError;
56
57 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
58 Ok(Self(PublicKey::try_from(bytes)?))
59 }
60}
61
62impl From<PublicKey> for RepositoryId {
63 fn from(pk: PublicKey) -> Self {
64 Self(pk)
65 }
66}
67
68impl Hashable for RepositoryId {
69 fn update_hash<S: Digest>(&self, state: &mut S) {
70 self.0.update_hash(state)
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::crypto::sign::Keypair;
78
79 #[test]
80 fn serialize_deserialize() {
81 let public_key = Keypair::random().public_key();
82 let id = RepositoryId::from(public_key);
83
84 let bytes = public_key.as_ref();
85
86 let serialized_expected = serde_json::to_string(bytes).unwrap();
87 let serialized_actual = serde_json::to_string(&id).unwrap();
88
89 assert_eq!(serialized_actual, serialized_expected);
90
91 let deserialized_actual: RepositoryId = serde_json::from_str(&serialized_actual).unwrap();
92 assert_eq!(deserialized_actual, id);
93 }
94}