libsignal_protocol/
address.rs1use libsignal_protocol_sys as sys;
2use std::{
3 fmt::{self, Debug, Formatter},
4 hash::{Hash, Hasher},
5 os::raw::c_char,
6 pin::Pin,
7 rc::Rc,
8};
9
10#[derive(PartialEq, Eq, Hash)]
13pub struct Address(Rc<OwnedAddress>);
14
15impl Address {
16 pub fn new<N: AsRef<[u8]>>(name: N, device_id: i32) -> Address {
18 Address(Rc::new(OwnedAddress::new(name.as_ref(), device_id)))
19 }
20
21 pub(crate) unsafe fn from_raw(
28 raw: sys::signal_protocol_address,
29 ) -> Address {
30 let name =
31 std::slice::from_raw_parts(raw.name as *const _, raw.name_len);
32 Address::new(name, raw.device_id)
33 }
34
35 pub(crate) unsafe fn from_ptr(
41 raw: *const sys::signal_protocol_address,
42 ) -> Address {
43 Address::from_raw(raw.read())
44 }
45
46 pub fn bytes(&self) -> &[u8] { self.0.name_bytes() }
51
52 pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
54 self.0.name_utf8()
55 }
56
57 pub fn device_id(&self) -> i32 { self.0.device_id() }
59
60 pub(crate) fn raw(&self) -> &sys::signal_protocol_address { &self.0.raw }
61}
62
63impl Debug for Address {
64 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
65}
66
67impl Clone for Address {
68 fn clone(&self) -> Address { Address(Rc::clone(&self.0)) }
69}
70
71struct OwnedAddress {
72 raw: sys::signal_protocol_address,
73 name: Pin<Box<[u8]>>,
74}
75
76impl OwnedAddress {
77 fn new(name: &[u8], device_id: i32) -> OwnedAddress {
78 let name = name.to_vec().into_boxed_slice();
79 let name = Pin::new(name);
80
81 OwnedAddress {
82 raw: sys::signal_protocol_address {
83 name: name.as_ptr() as *const c_char,
84 name_len: name.len(),
85 device_id,
86 },
87 name,
88 }
89 }
90
91 pub fn name_bytes(&self) -> &[u8] { &self.name }
92
93 pub fn name_utf8(&self) -> Result<&str, std::str::Utf8Error> {
94 std::str::from_utf8(self.name_bytes())
95 }
96
97 pub const fn device_id(&self) -> i32 { self.raw.device_id }
98}
99
100impl Debug for OwnedAddress {
101 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
102 let mut f = f.debug_struct("Address");
103
104 match self.name_utf8() {
105 Ok(name) => {
106 f.field("name", &name);
107 },
108 Err(_) => {
109 f.field("name", &self.name_bytes());
110 },
111 }
112
113 f.field("device_id", &self.device_id()).finish()
114 }
115}
116
117impl Clone for OwnedAddress {
118 fn clone(&self) -> OwnedAddress {
119 OwnedAddress::new(&self.name, self.raw.device_id)
120 }
121}
122
123impl PartialEq for OwnedAddress {
124 fn eq(&self, other: &OwnedAddress) -> bool {
125 self.device_id() == other.device_id()
126 && self.name_bytes() == other.name_bytes()
127 }
128}
129
130impl Eq for OwnedAddress {}
131
132impl Hash for OwnedAddress {
133 fn hash<H: Hasher>(&self, h: &mut H) {
134 h.write_i32(self.device_id());
135 h.write(self.name_bytes());
136 }
137}