initial commit
This commit is contained in:
commit
24616479be
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "ipcalc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
93
src/ip.rs
Normal file
93
src/ip.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use std::fmt::{self,Display}; // needed to implement Display for Ip
|
||||
use std::convert::From; // needed to implement u32::from(&ip)
|
||||
|
||||
// Debug needed for {:?} format
|
||||
// PartialEq and Eq allows comparisons (usefull for unit tests)
|
||||
#[derive(Debug,PartialEq,Eq)]
|
||||
pub enum Ip {
|
||||
V4([u8 ; 4]),
|
||||
// V6([u16 ; 8]) // not implemented yet...
|
||||
}
|
||||
|
||||
// implement methods on the Ip type
|
||||
// 'new' and 'from_str' are arbitrary and could be named differently
|
||||
impl Ip {
|
||||
pub fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
|
||||
Ip::V4([a, b, c, d])
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
let tbl : Vec<u8> = s.split('.')
|
||||
.filter_map(|s| s.parse().ok())
|
||||
.collect();
|
||||
Some(Ip::V4(tbl.try_into().ok()?))
|
||||
}
|
||||
|
||||
// totaly useless but an example of an object method :)
|
||||
pub fn is_even(&self) -> bool {
|
||||
let Ip::V4([_,_,_,n]) = self;
|
||||
n % 2 == 0
|
||||
}
|
||||
}
|
||||
|
||||
// allows conversion from ip to u32 with this syntax:
|
||||
// `let nbr = u32::from(&ip);`
|
||||
// use the std::convert::From trait
|
||||
impl From<&Ip> for u32 {
|
||||
fn from(src: &Ip) -> u32 {
|
||||
let mut ip : u32 = 0;
|
||||
let Ip::V4(array) = src;
|
||||
for (idx, n) in array.iter().enumerate() {
|
||||
ip += (*n as u32) << (8 * (3 - idx));
|
||||
}
|
||||
ip
|
||||
}
|
||||
}
|
||||
|
||||
// Display is a standard trait used by format! and println! and others
|
||||
// to display objects...
|
||||
impl Display for Ip {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Ip::V4(arr) => write!(f, "{}.{}.{}.{}",
|
||||
arr[0], arr[1], arr[2], arr[3]),
|
||||
/*
|
||||
Ip::V6(arr) => write!(f,
|
||||
"{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
|
||||
arr[0], arr[1], arr[2], arr[3],
|
||||
arr[4], arr[5], arr[6], arr[7])
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some unit tests, run with:
|
||||
// `$ cargo test`
|
||||
#[test]
|
||||
fn test_ip_new() {
|
||||
let ip = Ip::new(127, 0, 0, 1);
|
||||
assert_eq!(ip, Ip::V4([127, 0, 0, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ip_from_str() {
|
||||
let ip1 = Ip::from_str("127.0.0.1");
|
||||
assert_eq!(ip1, Some(Ip::V4([127, 0, 0, 1])));
|
||||
|
||||
let ip2 = Ip::from_str("512.0.0.1");
|
||||
assert_eq!(ip2, None);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ip_is_even() {
|
||||
assert_eq!(Ip::new(127, 0, 0, 1).is_even(), false);
|
||||
assert_eq!(Ip::new(192, 168, 0, 2).is_even(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u32_from_ip() {
|
||||
let ip = Ip::new(127, 0, 0, 1);
|
||||
let nbr = u32::from(&ip);
|
||||
assert_eq!(nbr, 0x7f000001);
|
||||
}
|
30
src/main.rs
Normal file
30
src/main.rs
Normal file
@ -0,0 +1,30 @@
|
||||
mod ip; // declare that there is a ip.rs module needed by this project
|
||||
|
||||
use ip::Ip; // import the Ip type from the ip module
|
||||
|
||||
fn main() {
|
||||
let Some(arg) = std::env::args().nth(1) else {
|
||||
println!("we need one argument.");
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(ip) = Ip::from_str(&arg) else {
|
||||
println!("'{}' is is not a valid ipv4 address.", arg);
|
||||
return;
|
||||
};
|
||||
|
||||
let nbr = u32::from(&ip);
|
||||
|
||||
println!("Canonical: {}", ip);
|
||||
println!("Debug....: {:?}", ip);
|
||||
println!("Binary...: {:b}", nbr);
|
||||
println!("Hexa.....: 0x{:x}", nbr);
|
||||
|
||||
let comment = match ip {
|
||||
Ip::V4([127, 0, 0, 1]) => "This is you.",
|
||||
Ip::V4([192,168,_,_]) => "This is a local area network",
|
||||
Ip::V4([10,_,_,_]) => "This is a big local area network",
|
||||
_ => "Nothing special to say about this address"
|
||||
};
|
||||
println!("{}", comment);
|
||||
}
|
Loading…
Reference in New Issue
Block a user