curuam/
lib.rs

1use std::time::{
2    Duration,
3    SystemTimeError,
4};
5
6pub const ICMP_HEADER_SIZE: usize = std::mem::size_of::<IcmpHeader>();
7pub const ARP_HEADER_SIZE: usize = std::mem::size_of::<ArpHeader>();
8pub const ETH_HEADER_SIZE: usize = std::mem::size_of::<EthHeader>();
9pub const IP_HEADER_SIZE: usize = std::mem::size_of::<Ipv4Header>();
10pub const IPV6_LEN: usize = 16;
11pub const IPV4_LEN: usize = 4;
12pub const MAC_LEN: usize = 6;
13
14/// trait for conveting one type into other similar to the From trait
15/// # Examples
16/// ```
17/// use curuam::*;
18///
19/// enum Bit {
20///     One,
21///     Zero
22/// }
23///
24/// impl Handle<bool> for Bit {
25///     fn from(value: bool) -> Self {
26///         match value {
27///             true => Self::One,
28///             false => Self::Zero
29///         }
30///     }
31///     fn to(&self) -> bool {
32///         match *self {
33///             Self::One => true,
34///             Self::Zero => false,
35///         }
36///     }
37/// }
38///
39/// let boolean: bool = Bit::Zero.to();
40///
41/// assert_eq!(boolean, false)
42/// ```
43pub trait Handle<T> {
44    fn from(value: T) -> Self;
45    fn to(&self) -> T;
46}
47
48/// struct for representing prime numbers
49pub struct Prime;
50
51/// struct for representing ipv4 addresses
52///
53/// # Example
54/// ```
55/// use curuam::*;
56///
57/// let ip_addr: Ipv4 = Handle::from([192, 168, 1, 1]);
58///
59/// let ip_octets: [u8; IPV4_LEN] = ip_addr.to(); // Basicly IPV4_LEN is count of octets of ipv4 (4)
60///
61/// assert_eq!(ip_octets, [192, 168, 1, 1])
62/// ```
63pub struct Ipv4 {
64    octets: [u8; IPV4_LEN],
65}
66
67/// struct for representing ipv6 addresses
68///
69/// # Example
70/// ```
71/// use curuam::*;
72///
73/// let ip_addr: Ipv6 = Handle::from([0; IPV6_LEN]); // Bassicly IPV6_LEN is count of octets of ipv6 (16)
74///
75/// let ip_octets: [u8; IPV6_LEN] = ip_addr.to();
76///
77/// assert_eq!(ip_octets, [0; IPV6_LEN])
78/// ```
79pub struct Ipv6 {
80    octets: [u8; IPV6_LEN],
81}
82
83/// struct for representing mac addresses
84///
85/// # Example
86/// ```
87/// use curuam::*;
88///
89/// let mac_addr: Mac = Handle::from([0xff; MAC_LEN]);
90///
91/// let mac_octets: [u8; MAC_LEN] = mac_addr.to();
92///
93/// assert_eq!(mac_octets, [0xff; MAC_LEN])
94/// ```
95pub struct Mac {
96    mac_addr: [u8; MAC_LEN],
97}
98
99/// wrapper around type's pointer simple to box or arc smart pointer
100///
101/// # Example
102/// ```
103/// use curuam::*;
104///
105/// let a = 1;
106///
107/// let a_wrapper = Wrapper::new(&a);
108///
109/// assert_eq!(*a_wrapper.reference(), a)
110/// ```
111pub struct Wrapper<T: ?Sized> {
112    pointer: *const T,
113}
114
115/// arp header
116#[repr(C)]
117pub struct ArpHeader {
118    pub hardware_type: u16,
119    pub protocol_type: u16,
120    pub hardware_len: u8,
121    pub protocol_len: u8,
122    pub opcode: u16,
123    pub sender_mac: [u8; MAC_LEN],
124    pub sender_ip: [u8; IPV4_LEN],
125    pub target_mac: [u8; MAC_LEN],
126    pub target_ip: [u8; IPV4_LEN],
127}
128
129/// icmp header
130#[repr(C)]
131pub struct IcmpHeader {
132    pub type_: u8,
133    pub code: u8,
134    pub check: u16,
135    pub id: u16,
136    pub sq: u16,
137}
138
139/// eth header
140#[repr(C)]
141pub struct EthHeader {
142    pub dest: [u8; MAC_LEN],
143    pub source: [u8; MAC_LEN],
144    pub proto: u16,
145}
146
147/// ipv4 header
148#[repr(C)]
149pub struct Ipv4Header {
150    pub verihl: u8,
151    pub tos: u8,
152    pub tot_len: u16,
153    pub id: u16,
154    pub frag: u16,
155    pub ttl: u8,
156    pub protocol: u8,
157    pub check: u16,
158    pub saddr: [u8; IPV4_LEN],
159    pub daddr: [u8; IPV4_LEN],
160}
161
162/// ipv6 header 
163#[repr(C)]
164pub struct Ipv6Header {
165    pub verlab: u32,
166    pub payload: u16,
167    pub next: u8,
168    pub hop: u8,
169    pub src: [u8; IPV6_LEN],
170    pub dst: [u8; IPV6_LEN]
171}
172
173impl Prime {
174    pub fn is_prime(u: u128) -> bool {
175        if u <= 1 {
176            return false
177        }
178
179        for i in 2..u {
180            if u % i == 0 {
181                return false;
182            }
183        }
184
185        true
186    }
187    pub fn range(start: u128, end: u128) -> Vec<u128> {
188        let mut primes: Vec<u128> = Vec::new();
189        
190        for u in start..end {
191            if Self::is_prime(u) {
192                primes.push(u)
193            } 
194        }
195
196        primes
197    }
198}
199
200impl<T: ?Sized> Wrapper<T> {
201    pub fn new(pointer: *const T) -> Self {
202        Self { pointer }
203    }
204    pub fn reference(&self) -> &T {
205        unsafe { &*self.pointer }
206    }
207    pub fn mut_reference(&self) -> &mut T {
208        unsafe { &mut *(self.pointer as *mut T) }
209    }
210}
211
212unsafe impl<T: ?Sized> Send for Wrapper<T> {}
213
214impl Clone for Mac {
215    fn clone(&self) -> Self {
216        Self {
217            mac_addr: self.mac_addr.clone(),
218        }
219    }
220}
221
222impl Handle<[u8; MAC_LEN]> for Mac {
223    fn from(mac_addr: [u8; MAC_LEN]) -> Self {
224        Self { mac_addr }
225    }
226    fn to(&self) -> [u8; MAC_LEN] {
227        self.mac_addr.clone()
228    }
229}
230
231impl std::fmt::Display for Mac {
232    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233        write!(
234            f,
235            "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
236            self.mac_addr[0],
237            self.mac_addr[1],
238            self.mac_addr[2],
239            self.mac_addr[3],
240            self.mac_addr[4],
241            self.mac_addr[5]
242        )
243    }
244}
245
246impl Clone for Ipv4 {
247    fn clone(&self) -> Self {
248        Self {
249            octets: self.octets.clone(),
250        }
251    }
252}
253
254impl Handle<[u8; IPV4_LEN]> for Ipv4 {
255    fn from(ip_addr: [u8; IPV4_LEN]) -> Self {
256        Self { octets: ip_addr }
257    }
258    fn to(&self) -> [u8; IPV4_LEN] {
259        self.octets.clone()
260    }
261}
262
263
264impl std::fmt::Display for Ipv4 {
265    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266        write!(
267            f,
268            "{}.{}.{}.{}",
269            self.octets[0], self.octets[1], self.octets[2], self.octets[3],
270        )
271    }
272}
273
274impl Handle<u32> for Ipv4 {
275    fn from(value: u32) -> Self {
276        let o1: u8 = (value & 0xff) as u8;
277        let o2: u8 = ((value >> 8) & 0xff) as u8;
278        let o3: u8 = ((value >> 16) & 0xff) as u8;
279        let o4: u8 = ((value >> 24) & 0xff) as u8;
280
281        Handle::from([o4, o3, o2, o1])
282    }
283    fn to(&self) -> u32 {
284        ((self.octets[0] as u32) << 24)
285            + ((self.octets[1] as u32) << 16)
286            + ((self.octets[2] as u32) << 8)
287            + ((self.octets[3] as u32) << 0)
288    }
289}
290
291impl Clone for Ipv6 {
292    fn clone(&self) -> Self {
293        Self { octets: self.octets.clone() }
294    }
295}
296
297impl Handle<[u8; IPV6_LEN]> for Ipv6 {
298    fn from(octets: [u8; IPV6_LEN]) -> Self {
299        Self { octets }
300    }
301    fn to(&self) -> [u8; IPV6_LEN] {
302        self.octets.clone()
303    }
304}
305
306impl std::fmt::Display for Ipv6 {
307    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308        write!(
309            f,
310            "{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}",
311            self.octets[0],
312            self.octets[1],
313            self.octets[2],
314            self.octets[3],
315            self.octets[4],
316            self.octets[5],
317            self.octets[6],
318            self.octets[7],
319            self.octets[8],
320            self.octets[9],
321            self.octets[10],
322            self.octets[11],
323            self.octets[12],
324            self.octets[13],
325            self.octets[14],
326            self.octets[15]
327        )
328    }
329}
330
331/// function for building to the exponent
332///
333/// # Example
334/// ```
335/// use curuam::*;
336///
337/// let a = 3;
338/// let b = power(a as f64, 2); // 1*3*3
339///
340/// assert_eq!(b, 9f64)
341/// ```
342pub fn power(f: f64, power: u16) -> f64 {
343    power_with_start(1f64, f, power)
344}
345
346fn power_with_start(start: f64, f: f64, power: u16) -> f64 {
347    let mut out: f64 = start;
348
349    for _ in 0..power {
350        out *= f
351    }
352
353    out
354}
355
356/// c memcpy clone
357///
358/// # Example
359///
360/// ```
361/// use curuam::*;
362///
363/// let a: [i128; 4] = [1210, 3271231, 478654, 239]; // Just random numbers
364/// let mut b: [i128; 4] = [0; 4];
365/// let mut c: [i128; 4] = [0; 4];
366///
367/// memcpy(&mut b, &a, std::mem::size_of::<[i128; 4]>());
368/// memcpy(c.as_mut_ptr(), a.as_ptr(), std::mem::size_of::<[i128; 4]>());
369///
370/// assert_eq!(a, b);
371/// assert_eq!(a, c);
372/// assert_eq!(b, c)
373/// ```
374pub fn memcpy<TD, TS>(dest: *mut TD, src: *const TS, size: usize) -> *mut TD {
375    if dest as usize == 0 {
376        return 0 as *mut TD;
377    }
378
379    let byte_dest: *mut u8 = dest as *mut u8;
380    let byte_src: *const u8 = src as *const u8;
381
382    unsafe {
383        for i in 0..size {
384            *((byte_dest as usize + i) as *mut u8) = *((byte_src as usize + i) as *const u8)
385        }
386    }
387
388    dest
389}
390
391/// creates string from bytes
392///
393/// # Example
394/// ```
395/// use curuam::*;
396///
397/// let bytes = b"Hello, world";
398///
399/// assert_eq!(str_from_bytes(bytes).as_bytes(), bytes)
400/// ```
401pub fn str_from_bytes(bytes: &[u8]) -> String {
402    let mut string: String = String::new();
403
404    for byte in bytes {
405        string.push(byte.clone() as char)
406    }
407
408    string
409}
410
411/// creates string from char pointer
412///
413/// # Example
414/// ```
415/// use curuam::*;
416/// use std::ffi::CString;
417///
418/// let string = "Hello, world";
419/// let cstring = CString::new(string).expect("cstring init error");
420///
421/// assert_eq!(&str_from_cstr(cstring.as_ptr())[..], string)
422/// ```
423pub fn str_from_cstr(cstr: *const i8) -> String {
424    let mut string: String = String::new();
425
426    let mut i: usize = 0;
427    loop {
428        let byte: i8 = unsafe { *((cstr as usize + i) as *const i8) };
429        if byte == 0 {
430            break;
431        }
432
433        string.push(byte as u8 as char);
434
435        i += 1
436    }
437
438    string
439}
440
441pub fn str_from_cutf16(str: *const u16) -> String {
442
443    let mut message: String = String::new();
444    let mut i: usize = 0;
445
446    loop {
447        let value: u16 = unsafe {
448            *((str as usize + i) as *const u16)
449        };
450        if value == 0 {
451            break;
452        }
453
454        message.push(value as u8 as char);
455        i += 1;
456    }
457
458    message
459}
460
461pub type RandomNumber = u128;
462pub fn random_with_seed(seed: RandomNumber) -> RandomNumber {
463    const SEED_OFFSET: u8 = 8;
464
465    const MULTIPLIER: RandomNumber = 9;
466    const ADDER: RandomNumber = 5;
467    let mut seed: RandomNumber = seed;
468    let mut result: RandomNumber = 0;
469    let mut i: usize = 0;
470    
471    loop {
472        if (i*SEED_OFFSET as usize) >= RandomNumber::BITS as usize {
473            break
474        }
475
476        seed = ((seed*MULTIPLIER)+ADDER)%power(2f64, SEED_OFFSET as u16) as RandomNumber;
477        result += seed << 8*i;
478
479        i += 1;
480    }
481
482    !result
483}
484
485pub fn random_in_range(min: RandomNumber, max: RandomNumber) -> Result<RandomNumber, SystemTimeError> {
486    let unix_epoch: Duration = std::time::UNIX_EPOCH.elapsed()?;
487    Ok(random_with_seed(unix_epoch.as_nanos() as RandomNumber)%(max-min)+min)
488}
489
490pub fn checksum(header: *const u8, len: usize) -> u16 {
491    let mut sum: i32 = 0;
492    let mut left: usize = len;
493    let words: *const u16 = header as *const u16; 
494
495    let mut i: usize = 0;
496    while left > 1 {
497        sum += unsafe {
498            *((words as usize + i) as *const u16)
499        } as i32;
500
501        left -= 2;
502        i += 2
503    }
504
505    if left == 1 {            
506        sum += unsafe {
507            *((words as usize + i - 1) as *const u8)
508        } as i32;
509    }
510
511    sum = (sum >> 16) + (sum & 0xffff); 
512    sum += sum >> 16;
513
514    (!sum) as u16
515}