initial commit
This commit is contained in:
commit
2b2306b57c
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/Cargo.lock
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "lâmpada"
|
||||||
|
authors = ["cel <cel@blos.sm>"]
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,182 @@
|
||||||
|
use std::{
|
||||||
|
net::{Ipv4Addr, Ipv6Addr},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct JID {
|
||||||
|
// TODO: validate localpart (length, char]
|
||||||
|
localpart: Option<String>,
|
||||||
|
domainpart: Domainpart,
|
||||||
|
resourcepart: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
enum Domainpart {
|
||||||
|
IPLiteral(Ipv6Addr),
|
||||||
|
IPv4Address(Ipv4Addr),
|
||||||
|
// TODO: domain name type, not string
|
||||||
|
IFQDN(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Domainpart {
|
||||||
|
type Err = DomainpartParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s.parse::<Ipv6Addr>() {
|
||||||
|
Ok(ip) => Ok(Domainpart::IPLiteral(ip)),
|
||||||
|
Err(_) => match s.parse::<Ipv4Addr>() {
|
||||||
|
Ok(ip) => Ok(Domainpart::IPv4Address(ip)),
|
||||||
|
Err(_) => Ok(Domainpart::IFQDN(s.to_owned())),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for Domainpart {
|
||||||
|
type Error = DomainpartParseError;
|
||||||
|
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
|
value.parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum DomainpartParseError {}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum JIDParseError {
|
||||||
|
Empty,
|
||||||
|
Domainpart(DomainpartParseError),
|
||||||
|
Malformed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JID {
|
||||||
|
fn new(localpart: Option<String>, domainpart: String, resourcepart: Option<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
localpart,
|
||||||
|
domainpart: domainpart.parse().unwrap(),
|
||||||
|
resourcepart,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for JID {
|
||||||
|
type Err = JIDParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let split: Vec<&str> = s.split('@').collect();
|
||||||
|
match split.len() {
|
||||||
|
0 => Err(JIDParseError::Empty),
|
||||||
|
1 => {
|
||||||
|
let split: Vec<&str> = split[0].split('/').collect();
|
||||||
|
match split.len() {
|
||||||
|
1 => Ok(JID::new(None, split[0].to_string(), None)),
|
||||||
|
2 => Ok(JID::new(
|
||||||
|
None,
|
||||||
|
split[0].to_string(),
|
||||||
|
Some(split[1].to_string()),
|
||||||
|
)),
|
||||||
|
_ => Err(JIDParseError::Malformed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
let split2: Vec<&str> = split[1].split('/').collect();
|
||||||
|
match split2.len() {
|
||||||
|
1 => Ok(JID::new(
|
||||||
|
Some(split[0].to_string()),
|
||||||
|
split2[0].to_string(),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
2 => Ok(JID::new(
|
||||||
|
Some(split[0].to_string()),
|
||||||
|
split2[0].to_string(),
|
||||||
|
Some(split2[1].to_string()),
|
||||||
|
)),
|
||||||
|
_ => Err(JIDParseError::Malformed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(JIDParseError::Malformed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for JID {
|
||||||
|
type Error = JIDParseError;
|
||||||
|
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
|
value.parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for JID {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}{}{}",
|
||||||
|
self.localpart.clone().map(|l| l + "@").unwrap_or_default(),
|
||||||
|
match &self.domainpart {
|
||||||
|
Domainpart::IPLiteral(addr) => addr.to_string(),
|
||||||
|
Domainpart::IPv4Address(addr) => addr.to_string(),
|
||||||
|
Domainpart::IFQDN(domain) => domain.to_owned(),
|
||||||
|
},
|
||||||
|
self.resourcepart
|
||||||
|
.clone()
|
||||||
|
.map(|r| "/".to_owned() + &r)
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn jid_to_string() {
|
||||||
|
assert_eq!(
|
||||||
|
JID::new(Some("cel".into()), "blos.sm".into(), None).to_string(),
|
||||||
|
"cel@blos.sm".to_owned()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_full_jid() {
|
||||||
|
assert_eq!(
|
||||||
|
"cel@blos.sm/greenhouse".parse::<JID>().unwrap(),
|
||||||
|
JID::new(
|
||||||
|
Some("cel".into()),
|
||||||
|
"blos.sm".into(),
|
||||||
|
Some("greenhouse".into())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_bare_jid() {
|
||||||
|
assert_eq!(
|
||||||
|
"cel@blos.sm".parse::<JID>().unwrap(),
|
||||||
|
JID::new(Some("cel".into()), "blos.sm".into(), None)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_domain_jid() {
|
||||||
|
assert_eq!(
|
||||||
|
"component.blos.sm".parse::<JID>().unwrap(),
|
||||||
|
JID::new(None, "component.blos.sm".into(), None)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_full_domain_jid() {
|
||||||
|
assert_eq!(
|
||||||
|
"component.blos.sm/bot".parse::<JID>().unwrap(),
|
||||||
|
JID::new(None, "component.blos.sm".into(), Some("bot".into()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
mod jid;
|
||||||
|
|
||||||
|
pub fn add(left: usize, right: usize) -> usize {
|
||||||
|
left + right
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let result = add(2, 2);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue