1use std::{collections::BTreeSet, net::SocketAddr};
7
8use nested_enum_utils::common_fields;
9use serde::{Deserialize, Serialize};
10use snafu::{Backtrace, Snafu};
11
12use crate::{key::NodeId, relay_url::RelayUrl};
13
14mod node;
15
16pub use self::node::NodeTicket;
17
18pub trait Ticket: Sized {
31 const KIND: &'static str;
35
36 fn to_bytes(&self) -> Vec<u8>;
38
39 fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError>;
41
42 fn serialize(&self) -> String {
44 let mut out = Self::KIND.to_string();
45 data_encoding::BASE32_NOPAD.encode_append(&self.to_bytes(), &mut out);
46 out.to_ascii_lowercase()
47 }
48
49 fn deserialize(str: &str) -> Result<Self, ParseError> {
51 let expected = Self::KIND;
52 let Some(rest) = str.strip_prefix(expected) else {
53 return Err(KindSnafu { expected }.build());
54 };
55 let bytes = data_encoding::BASE32_NOPAD.decode(rest.to_ascii_uppercase().as_bytes())?;
56 let ticket = Self::from_bytes(&bytes)?;
57 Ok(ticket)
58 }
59}
60
61#[common_fields({
63 backtrace: Option<Backtrace>,
64 #[snafu(implicit)]
65 span_trace: n0_snafu::SpanTrace,
66})]
67#[derive(Debug, Snafu)]
68#[allow(missing_docs)]
69#[snafu(visibility(pub(crate)))]
70#[non_exhaustive]
71pub enum ParseError {
72 #[snafu(display("wrong prefix, expected {expected}"))]
74 Kind {
75 expected: &'static str,
77 },
78 #[snafu(transparent)]
80 Postcard { source: postcard::Error },
81 #[snafu(transparent)]
83 Encoding { source: data_encoding::DecodeError },
84 #[snafu(display("verification failed: {message}"))]
86 Verify { message: &'static str },
87}
88
89impl ParseError {
90 pub fn wrong_prefix(expected: &'static str) -> Self {
95 KindSnafu { expected }.build()
96 }
97
98 pub fn verification_failed(message: &'static str) -> Self {
101 VerifySnafu { message }.build()
102 }
103}
104
105#[derive(Serialize, Deserialize)]
106struct Variant0NodeAddr {
107 node_id: NodeId,
108 info: Variant0AddrInfo,
109}
110
111#[derive(Serialize, Deserialize)]
112struct Variant0AddrInfo {
113 relay_url: Option<RelayUrl>,
114 direct_addresses: BTreeSet<SocketAddr>,
115}