use optionize

This commit is contained in:
Luna Yao
2026-05-04 01:33:57 +02:00
parent 4b95f44a91
commit 348b83d768
4 changed files with 24 additions and 24 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ toml = "0.8.12"
chrono = { version = "0.4.37", features = ["serde"] } chrono = { version = "0.4.37", features = ["serde"] }
getset = "0.1.6" getset = "0.1.6"
optional_struct = "0.5.2" optionize = "0.1"
guarden = "0.1" guarden = "0.1"
+9 -9
View File
@@ -7,18 +7,18 @@ use crate::{
api::manage::ConfigSource as RpcConfigSource, api::manage::ConfigSource as RpcConfigSource,
common::{CompressionAlgoPb, PortForwardConfigPb, SecureModeConfig, SocketType}, common::{CompressionAlgoPb, PortForwardConfigPb, SecureModeConfig, SocketType},
}, },
tunnel::{IpScheme, TunnelScheme, generate_digest_from_str}, tunnel::{generate_digest_from_str, IpScheme, TunnelScheme},
utils, utils,
}; };
use anyhow::Context; use anyhow::Context;
use base64::{Engine as _, prelude::BASE64_STANDARD}; use base64::{prelude::BASE64_STANDARD, Engine as _};
use bon::Builder; use bon::Builder;
use clap::ValueEnum;
use clap::builder::PossibleValue; use clap::builder::PossibleValue;
use clap::ValueEnum;
use derivative::Derivative; use derivative::Derivative;
use derive_more::{Constructor, Deref}; use derive_more::{Constructor, Deref};
use getset::Getters; use getset::Getters;
use optional_struct::Applicable; use optionize::Optionized;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use std::{ use std::{
@@ -38,7 +38,7 @@ use tokio::io::AsyncReadExt as _;
)] )]
pub struct ConfigBase<Raw, Parsed, Data = ()> pub struct ConfigBase<Raw, Parsed, Data = ()>
where where
Raw: Applicable<Base = Parsed>, Raw: Optionized<Parsed>,
ConfigBase<Raw, Parsed, Data>: TryFrom<Raw>, ConfigBase<Raw, Parsed, Data>: TryFrom<Raw>,
{ {
#[deref] #[deref]
@@ -53,7 +53,7 @@ where
impl<Raw, Parsed, Data> Serialize for ConfigBase<Raw, Parsed, Data> impl<Raw, Parsed, Data> Serialize for ConfigBase<Raw, Parsed, Data>
where where
Raw: Applicable<Base = Parsed> + Serialize, Raw: Optionized<Parsed> + Serialize,
ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>, ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>,
{ {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -66,7 +66,7 @@ where
impl<Raw, Parsed, Data> Default for ConfigBase<Raw, Parsed, Data> impl<Raw, Parsed, Data> Default for ConfigBase<Raw, Parsed, Data>
where where
Raw: Applicable<Base = Parsed> + Default, Raw: Optionized<Parsed> + Default,
ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>, ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>,
{ {
fn default() -> Self { fn default() -> Self {
@@ -76,7 +76,7 @@ where
impl<Raw, Parsed, Data> ConfigBase<Raw, Parsed, Data> impl<Raw, Parsed, Data> ConfigBase<Raw, Parsed, Data>
where where
Raw: Applicable<Base = Parsed>, Raw: Optionized<Parsed>,
ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>, ConfigBase<Raw, Parsed, Data>: TryFrom<Raw, Error: Debug>,
{ {
pub fn into_parsed(self) -> Parsed { pub fn into_parsed(self) -> Parsed {
@@ -93,7 +93,7 @@ where
pub fn update(self, config: Raw) -> Result<Self, <Self as TryFrom<Raw>>::Error> { pub fn update(self, config: Raw) -> Result<Self, <Self as TryFrom<Raw>>::Error> {
let mut raw = self.into_raw(); let mut raw = self.into_raw();
config.apply_to_opt(&mut raw); raw.merge(config);
raw.try_into() raw.try_into()
} }
} }
+7 -6
View File
@@ -5,19 +5,21 @@ use crate::dns::config::{DNS_DEFAULT_ADDRESSES, DNS_DEFAULT_DOMAIN};
use crate::dns::utils::addr::NameServerAddrGroup; use crate::dns::utils::addr::NameServerAddrGroup;
use crate::proto::dns::GetExportConfigResponse; use crate::proto::dns::GetExportConfigResponse;
use hickory_proto::rr::LowerName; use hickory_proto::rr::LowerName;
use optional_struct::{Applicable, optional_struct};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use optionize::{optionized, Optionizable};
#[optional_struct(DnsConfigRaw)] #[optionized]
#[optionize(name = "DnsConfigRaw")]
#[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)] #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
pub struct DnsConfigParsed { pub struct DnsConfigParsed {
pub disabled: bool, pub disabled: bool,
#[serde(rename = "zone")] #[serde(rename = "zone")]
pub zones: Vec<ZoneConfig>, pub zones: Vec<ZoneConfig>,
#[optional_skip_wrap] #[optionize(flatten)]
#[serde(flatten)] #[serde(flatten)]
pub policies: HashMap<LowerName, DnsPolicyConfig>, pub policies: HashMap<LowerName, DnsPolicyConfig>,
#[optionize(flatten)]
pub name: Option<LowerName>, pub name: Option<LowerName>,
pub domain: LowerName, pub domain: LowerName,
pub addresses: NameServerAddrGroup, pub addresses: NameServerAddrGroup,
@@ -28,13 +30,12 @@ pub type DnsConfig = ConfigBase<DnsConfigRaw, DnsConfigParsed, ()>;
impl From<DnsConfigRaw> for DnsConfig { impl From<DnsConfigRaw> for DnsConfig {
fn from(raw: DnsConfigRaw) -> Self { fn from(raw: DnsConfigRaw) -> Self {
let default = DnsConfigParsed { let mut parsed = DnsConfigParsed {
domain: DNS_DEFAULT_DOMAIN.clone(), domain: DNS_DEFAULT_DOMAIN.clone(),
addresses: DNS_DEFAULT_ADDRESSES.clone(), addresses: DNS_DEFAULT_ADDRESSES.clone(),
..Default::default() ..Default::default()
}; };
parsed.load(raw.clone());
let parsed = raw.clone().build(default);
Self::new(parsed, raw, ()) Self::new(parsed, raw, ())
} }
} }
+7 -8
View File
@@ -7,11 +7,11 @@ use derive_more::From;
use hickory_proto::op::ResponseCode; use hickory_proto::op::ResponseCode;
use hickory_proto::rr::LowerName; use hickory_proto::rr::LowerName;
use maplit::hashset; use maplit::hashset;
use optional_struct::{Applicable, optional_struct};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use optionize::{optionized, Optionizable};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, From, Deserialize, Serialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Hash, From, Deserialize, Serialize)]
#[serde(untagged)] #[serde(untagged)]
@@ -38,15 +38,16 @@ impl From<i32> for Fallthrough {
} }
} }
#[optional_struct(ZoneConfigRaw)] #[optionized]
#[optionize(name = "ZoneConfigRaw")]
#[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)] #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
pub struct ZoneConfigParsed { pub struct ZoneConfigParsed {
#[optional_skip_wrap] #[optionize(flatten)]
pub origin: LowerName, pub origin: LowerName,
pub ttl: u32, pub ttl: u32,
pub records: Vec<String>, pub records: Vec<String>,
pub forwarders: NameServerAddrGroup, pub forwarders: NameServerAddrGroup,
#[optional_skip_wrap] #[optionize(flatten)]
#[serde(flatten)] #[serde(flatten)]
pub policy: ZonePolicyConfig, pub policy: ZonePolicyConfig,
pub fallthrough: HashSet<Fallthrough>, pub fallthrough: HashSet<Fallthrough>,
@@ -70,15 +71,13 @@ impl TryFrom<ZoneConfigRaw> for ZoneConfig {
type Error = anyhow::Error; type Error = anyhow::Error;
fn try_from(raw: ZoneConfigRaw) -> Result<Self, Self::Error> { fn try_from(raw: ZoneConfigRaw) -> Result<Self, Self::Error> {
let default = ZoneConfigParsed { let mut parsed = ZoneConfigParsed {
fallthrough: hashset! {Fallthrough::Any}, fallthrough: hashset! {Fallthrough::Any},
..Default::default() ..Default::default()
}; };
parsed.load(raw.clone());
let parsed = raw.clone().build(default);
let data = (&parsed).into(); let data = (&parsed).into();
let _ = Zone::try_from(&data)?; // validation let _ = Zone::try_from(&data)?; // validation
Ok(Self::new(parsed, raw, data)) Ok(Self::new(parsed, raw, data))
} }
} }