zone_update/bunny/
types.rs

1use serde::{Deserialize, Deserializer, Serialize};
2
3use crate::{errors::Error, RecordType};
4
5
6#[derive(Deserialize, Debug)]
7#[serde(rename_all = "PascalCase")]
8pub(crate) struct ZoneInfo {
9    pub id: u64,
10    pub domain: String,
11    // ...
12}
13
14#[derive(Deserialize, Debug)]
15#[serde(rename_all = "PascalCase")]
16pub(crate) struct ZoneList {
17    pub items: Vec<ZoneInfo>,
18}
19
20// {
21//   "Id": 12681448,
22//   "Type": 0,
23//   "Ttl": 300,
24//   "Value": "170.64.213.116",
25//   "Name": "www",
26//   "Weight": 100,
27//   "Priority": 0,
28//   "Port": 0,
29//   "Flags": 0,
30//   "Tag": "",
31//   "Accelerated": false,
32//   "AcceleratedPullZoneId": 0,
33//   "LinkName": "",
34//   "IPGeoLocationInfo": {
35//     "CountryCode": "AU",
36//     "Country": "Australia",
37//     "ASN": 14061,
38//     "OrganizationName": "Digital Ocean",
39//     "City": "Sydney"
40//   },
41//   "GeolocationInfo": null,
42//   "MonitorStatus": 0,
43//   "MonitorType": 0,
44//   "GeolocationLatitude": 0.0,
45//   "GeolocationLongitude": 0.0,
46//   "EnviromentalVariables": [],
47//   "LatencyZone": null,
48//   "SmartRoutingType": 0,
49//   "Disabled": false,
50//   "Comment": null,
51//   "AutoSslIssuance": true
52// }
53#[allow(unused)]
54#[derive(Deserialize, Debug)]
55#[serde(rename_all = "PascalCase")]
56pub(crate) struct Record<T> {
57    pub id: u64,
58    #[serde(rename = "Type", deserialize_with = "de_recordtype")]
59    pub rtype: RecordType,
60    pub value: T,
61    pub name: String,
62    pub ttl: u64,
63}
64
65#[derive(Serialize, Debug)]
66#[serde(rename_all = "PascalCase")]
67pub(crate) struct CreateUpdate<T> {
68    pub value: T,
69    pub name: String,
70    pub ttl: u64,
71    #[serde(rename = "Type", serialize_with = "ser_recordtype")]
72    pub rtype: RecordType,
73}
74
75// Bunny has it's own mappings for A, AAAA, TXT, etc.
76//
77// 0 = A
78// 1 = AAAA
79// 2 = CNAME
80// 3 = TXT
81// 4 = MX
82// 5 = Redirect
83// 6 = Flatten
84// 7 = PullZone
85// 8 = SRV
86// 9 = CAA
87// 10 = PTR
88// 11 = Script
89// 12 = NS
90// 13 = SVCB
91// 14 = HTTPS
92impl TryFrom<u64> for RecordType {
93    type Error = Error;
94
95    fn try_from(value: u64) -> std::result::Result<Self, Self::Error> {
96        let to = match value {
97            0 => RecordType::A,
98            1 => RecordType::AAAA,
99            2 => RecordType::CNAME,
100            3 => RecordType::TXT,
101            4 => RecordType::MX,
102            // 5 => RecordType::Redirect,
103            // 6 => RecordType::Flatten,
104            // 7 => RecordType::PullZone,
105            8 => RecordType::SRV,
106            9 => RecordType::CAA,
107            10 => RecordType::PTR,
108            // 11 => RecordType::Script,
109            12 => RecordType::NS,
110            13 => RecordType::SVCB,
111            14 => RecordType::HTTPS,
112            _ => return Err(Error::ApiError(format!("Invalid RecordType ID {value}")))
113        };
114        Ok(to)
115    }
116}
117
118impl From<RecordType> for u64 {
119    fn from(value: RecordType) -> Self {
120        match value {
121            RecordType::A => 0,
122            RecordType::AAAA => 1,
123            RecordType::CNAME => 2,
124            RecordType::TXT => 3,
125            RecordType::MX => 4,
126            RecordType::SRV => 8,
127            RecordType::CAA => 9,
128            RecordType::PTR => 10,
129            RecordType::NS => 12,
130            RecordType::SVCB => 13,
131            RecordType::HTTPS => 14,
132        }
133    }
134}
135
136pub(crate) fn de_recordtype<'de, D>(deser: D) -> std::result::Result<RecordType, D::Error>
137where
138    D: Deserializer<'de>,
139{
140    let v = u64::deserialize(deser)?;
141    RecordType::try_from(v)
142       .map_err(serde::de::Error::custom)
143}
144
145
146fn ser_recordtype<S>(rt: &RecordType, serializer: S) -> std::result::Result<S::Ok, S::Error>
147where
148    S: serde::Serializer,
149{
150    u64::from(rt.clone()).serialize(serializer)
151}