From: Aaron Lauterer <a.lauterer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH 08/12] tui: remove now unused utils.rs
Date: Wed, 25 Oct 2023 18:00:07 +0200 [thread overview]
Message-ID: <20231025160011.3617524-9-a.lauterer@proxmox.com> (raw)
In-Reply-To: <20231025160011.3617524-1-a.lauterer@proxmox.com>
all it did moved to the common crate
Signed-off-by: Aaron Lauterer <a.lauterer@proxmox.com>
---
proxmox-tui-installer/src/utils.rs | 268 -----------------------------
1 file changed, 268 deletions(-)
delete mode 100644 proxmox-tui-installer/src/utils.rs
diff --git a/proxmox-tui-installer/src/utils.rs b/proxmox-tui-installer/src/utils.rs
deleted file mode 100644
index 89349ed..0000000
--- a/proxmox-tui-installer/src/utils.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-use std::{
- fmt,
- net::{AddrParseError, IpAddr},
- num::ParseIntError,
- str::FromStr,
-};
-
-use serde::Deserialize;
-
-/// Possible errors that might occur when parsing CIDR addresses.
-#[derive(Debug)]
-pub enum CidrAddressParseError {
- /// No delimiter for separating address and mask was found.
- NoDelimiter,
- /// The IP address part could not be parsed.
- InvalidAddr(AddrParseError),
- /// The mask could not be parsed.
- InvalidMask(Option<ParseIntError>),
-}
-
-/// An IP address (IPv4 or IPv6), including network mask.
-///
-/// See the [`IpAddr`] type for more information how IP addresses are handled.
-/// The mask is appropriately enforced to be `0 <= mask <= 32` for IPv4 or
-/// `0 <= mask <= 128` for IPv6 addresses.
-///
-/// # Examples
-/// ```
-/// use std::net::{Ipv4Addr, Ipv6Addr};
-/// let ipv4 = CidrAddress::new(Ipv4Addr::new(192, 168, 0, 1), 24).unwrap();
-/// let ipv6 = CidrAddress::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xc0a8, 1), 32).unwrap();
-///
-/// assert_eq!(ipv4.to_string(), "192.168.0.1/24");
-/// assert_eq!(ipv6.to_string(), "2001:db8::c0a8:1/32");
-/// ```
-#[derive(Clone, Debug, PartialEq)]
-pub struct CidrAddress {
- addr: IpAddr,
- mask: usize,
-}
-
-impl CidrAddress {
- /// Constructs a new CIDR address.
- ///
- /// It fails if the mask is invalid for the given IP address.
- pub fn new<T: Into<IpAddr>>(addr: T, mask: usize) -> Result<Self, CidrAddressParseError> {
- let addr = addr.into();
-
- if mask > mask_limit(&addr) {
- Err(CidrAddressParseError::InvalidMask(None))
- } else {
- Ok(Self { addr, mask })
- }
- }
-
- /// Returns only the IP address part of the address.
- pub fn addr(&self) -> IpAddr {
- self.addr
- }
-
- /// Returns `true` if this address is an IPv4 address, `false` otherwise.
- pub fn is_ipv4(&self) -> bool {
- self.addr.is_ipv4()
- }
-
- /// Returns `true` if this address is an IPv6 address, `false` otherwise.
- pub fn is_ipv6(&self) -> bool {
- self.addr.is_ipv6()
- }
-
- /// Returns only the mask part of the address.
- pub fn mask(&self) -> usize {
- self.mask
- }
-}
-
-impl FromStr for CidrAddress {
- type Err = CidrAddressParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- let (addr, mask) = s
- .split_once('/')
- .ok_or(CidrAddressParseError::NoDelimiter)?;
-
- let addr = addr.parse().map_err(CidrAddressParseError::InvalidAddr)?;
-
- let mask = mask
- .parse()
- .map_err(|err| CidrAddressParseError::InvalidMask(Some(err)))?;
-
- if mask > mask_limit(&addr) {
- Err(CidrAddressParseError::InvalidMask(None))
- } else {
- Ok(Self { addr, mask })
- }
- }
-}
-
-impl fmt::Display for CidrAddress {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}/{}", self.addr, self.mask)
- }
-}
-
-fn mask_limit(addr: &IpAddr) -> usize {
- if addr.is_ipv4() {
- 32
- } else {
- 128
- }
-}
-
-/// Possible errors that might occur when parsing FQDNs.
-#[derive(Debug, Eq, PartialEq)]
-pub enum FqdnParseError {
- MissingHostname,
- NumericHostname,
- InvalidPart(String),
-}
-
-impl fmt::Display for FqdnParseError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use FqdnParseError::*;
- match self {
- MissingHostname => write!(f, "missing hostname part"),
- NumericHostname => write!(f, "hostname cannot be purely numeric"),
- InvalidPart(part) => write!(
- f,
- "FQDN must only consist of alphanumeric characters and dashes. Invalid part: '{part}'",
- ),
- }
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Fqdn {
- parts: Vec<String>,
-}
-
-impl Fqdn {
- pub fn from(fqdn: &str) -> Result<Self, FqdnParseError> {
- let parts = fqdn
- .split('.')
- .map(ToOwned::to_owned)
- .collect::<Vec<String>>();
-
- for part in &parts {
- if !Self::validate_single(part) {
- return Err(FqdnParseError::InvalidPart(part.clone()));
- }
- }
-
- if parts.len() < 2 {
- Err(FqdnParseError::MissingHostname)
- } else if parts[0].chars().all(|c| c.is_ascii_digit()) {
- // Not allowed/supported on Debian systems.
- Err(FqdnParseError::NumericHostname)
- } else {
- Ok(Self { parts })
- }
- }
-
- pub fn host(&self) -> Option<&str> {
- self.has_host().then_some(&self.parts[0])
- }
-
- pub fn domain(&self) -> String {
- let parts = if self.has_host() {
- &self.parts[1..]
- } else {
- &self.parts
- };
-
- parts.join(".")
- }
-
- /// Checks whether the FQDN has a hostname associated with it, i.e. is has more than 1 part.
- fn has_host(&self) -> bool {
- self.parts.len() > 1
- }
-
- fn validate_single(s: &String) -> bool {
- !s.is_empty()
- // First character must be alphanumeric
- && s.chars()
- .next()
- .map(|c| c.is_ascii_alphanumeric())
- .unwrap_or_default()
- // .. last character as well,
- && s.chars()
- .last()
- .map(|c| c.is_ascii_alphanumeric())
- .unwrap_or_default()
- // and anything between must be alphanumeric or -
- && s.chars()
- .skip(1)
- .take(s.len().saturating_sub(2))
- .all(|c| c.is_ascii_alphanumeric() || c == '-')
- }
-}
-
-impl FromStr for Fqdn {
- type Err = FqdnParseError;
-
- fn from_str(value: &str) -> Result<Self, Self::Err> {
- Self::from(value)
- }
-}
-
-impl fmt::Display for Fqdn {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", self.parts.join("."))
- }
-}
-
-impl<'de> Deserialize<'de> for Fqdn {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- let s: String = Deserialize::deserialize(deserializer)?;
- s.parse()
- .map_err(|_| serde::de::Error::custom("invalid FQDN"))
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn fqdn_construct() {
- use FqdnParseError::*;
- assert!(Fqdn::from("foo.example.com").is_ok());
- assert!(Fqdn::from("foo-bar.com").is_ok());
- assert!(Fqdn::from("a-b.com").is_ok());
-
- assert_eq!(Fqdn::from("foo"), Err(MissingHostname));
-
- assert_eq!(Fqdn::from("-foo.com"), Err(InvalidPart("-foo".to_owned())));
- assert_eq!(Fqdn::from("foo-.com"), Err(InvalidPart("foo-".to_owned())));
- assert_eq!(Fqdn::from("foo.com-"), Err(InvalidPart("com-".to_owned())));
- assert_eq!(Fqdn::from("-o-.com"), Err(InvalidPart("-o-".to_owned())));
-
- assert_eq!(Fqdn::from("123.com"), Err(NumericHostname));
- assert!(Fqdn::from("foo123.com").is_ok());
- assert!(Fqdn::from("123foo.com").is_ok());
- }
-
- #[test]
- fn fqdn_parts() {
- let fqdn = Fqdn::from("pve.example.com").unwrap();
- assert_eq!(fqdn.host().unwrap(), "pve");
- assert_eq!(fqdn.domain(), "example.com");
- assert_eq!(
- fqdn.parts,
- &["pve".to_owned(), "example".to_owned(), "com".to_owned()]
- );
- }
-
- #[test]
- fn fqdn_display() {
- assert_eq!(
- Fqdn::from("foo.example.com").unwrap().to_string(),
- "foo.example.com"
- );
- }
-}
--
2.39.2
next prev parent reply other threads:[~2023-10-25 16:00 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-25 15:59 [pve-devel] [PATCH 00/12] installer: add crate for common code Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 01/12] add proxmox-installer-common crate Aaron Lauterer
2023-10-27 10:59 ` Christoph Heiss
2023-10-25 16:00 ` [pve-devel] [PATCH 02/12] common: copy common code from tui-installer Aaron Lauterer
2023-10-27 11:14 ` Christoph Heiss
2023-10-25 16:00 ` [pve-devel] [PATCH 03/12] common: utils: add dependency for doc test Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 04/12] common: make InstallZfsOption public Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 05/12] common: disk_checks: make functions public Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 06/12] tui-installer: add dependency for new common crate Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 07/12] tui: switch to " Aaron Lauterer
2023-10-25 16:00 ` Aaron Lauterer [this message]
2023-10-25 16:00 ` [pve-devel] [PATCH 09/12] common: add installer_setup method Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 10/12] common: document " Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 11/12] tui: use installer_setup from common cate Aaron Lauterer
2023-10-25 16:00 ` [pve-devel] [PATCH 12/12] tui: remove unused read_json function Aaron Lauterer
2023-10-27 11:06 ` Christoph Heiss
2023-10-27 11:39 ` [pve-devel] [PATCH installer] buildsys: copy over `proxmox-installer-common` crate to build directory Christoph Heiss
2023-10-27 11:41 ` [pve-devel] [PATCH 00/12] installer: add crate for common code Christoph Heiss
2023-10-30 9:45 ` Aaron Lauterer
2023-11-02 19:05 ` [pve-devel] applied-series: " Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231025160011.3617524-9-a.lauterer@proxmox.com \
--to=a.lauterer@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal