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