1use byteorder::{LittleEndian, WriteBytesExt};
2use crate::{lp_encode, vlp_encode, InformalProperty, WithInformalProperty};
3use std::io;
4
5#[derive(Default, Debug)]
6pub struct DNSCryptProvider {
7 name: String,
8 pk: Vec<u8>,
9}
10
11impl DNSCryptProvider {
12 pub fn new(name: String, pk: Vec<u8>) -> Self {
13 DNSCryptProvider { name, pk }
14 }
15}
16
17#[derive(Default, Debug)]
18pub struct DNSCryptBuilder {
19 informal_properties: u64,
20 addrs: Vec<String>,
21 provider: DNSCryptProvider,
22}
23
24impl DNSCryptBuilder {
25 pub fn new(provider: DNSCryptProvider) -> Self {
26 DNSCryptBuilder {
27 informal_properties: 0,
28 addrs: vec![],
29 provider,
30 }
31 }
32
33 pub fn with_addr(mut self, addr: String) -> Self {
34 self.addrs.push(addr);
35 self
36 }
37
38 pub fn serialize(self) -> io::Result<String> {
39 let mut bin = vec![];
40 bin.push(0x01);
41 bin.write_u64::<LittleEndian>(self.informal_properties)?;
42 let addrs_bin: Vec<_> = self
43 .addrs
44 .iter()
45 .map(|addr| addr.as_bytes().to_vec())
46 .collect();
47 vlp_encode(&mut bin, &addrs_bin)?;
48 let provider_bin = {
49 let mut bin = vec![];
50 bin.extend(&self.provider.pk);
51 bin.extend(self.provider.name.as_str().as_bytes());
52 bin
53 };
54 lp_encode(&mut bin, &provider_bin)?;
55 let serialized = base64::encode_config(
56 &bin,
57 base64::Config::new(base64::CharacterSet::UrlSafe, false),
58 );
59 Ok(format!("sdns://{}", serialized))
60 }
61}
62
63impl WithInformalProperty for DNSCryptBuilder {
64 fn with_informal_property(mut self, informal_property: InformalProperty) -> Self {
65 self.informal_properties |= u64::from(informal_property);
66 self
67 }
68}