<commit_before>
use core::ops::Add;
use core::ops::Shl;
use core::ops::Shr;
use core::ops::Sub;
use core::ops::Rem;
// use core::ops::Rem;
// use core::ops::Range;
//use core::iter::Step;
use core::iter::Iterator;
use core::cmp::Ordering;
use core::cmp::Ord;
use core::convert::From;
// use core::fmt::Debug;

use num::bigint::BigUint;
use num::bigint::ToBigUint;
// use num_integer::Integer;

use ip_bits::IpBits;
use prefix::Prefix;
use regex::Regex;
// use std::f64;
use std::fmt;

use num_traits::identities::Zero;
use num_traits::identities::One;
use num_traits::FromPrimitive;

use num_traits::cast::ToPrimitive;

use ip_bits::IpVersion;


pub struct IPAddress {
    pub ip_bits: &'static IpBits,
    pub host_address: BigUint,
    pub prefix: Prefix,
    pub mapped: Option<Box<IPAddress>>,
    pub vt_is_private: fn(&IPAddress) -> bool,
    pub vt_is_loopback: fn(&IPAddress) -> bool,
    pub vt_to_ipv6: fn(&IPAddress) -> IPAddress
}

impl fmt::Debug for IPAddress {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "IPAddress: {}", self.to_string())
    }
}


impl Clone for IPAddress {
    fn clone(&self) -> IPAddress {
        IPAddress {
            ip_bits: self.ip_bits.clone(),
            host_address: self.host_address.clone(),
            prefix: self.prefix.clone(),
            mapped: self.mapped.clone(),
            vt_is_private: self.vt_is_private,
            vt_is_loopback: self.vt_is_loopback,
            vt_to_ipv6: self.vt_to_ipv6
        }
    }
}


impl Ord for IPAddress {
    fn cmp(&self, oth: & IPAddress) -> Ordering {
            if self.ip_bits.version != oth.ip_bits.version {
                if self.ip_bits.version == IpVersion::V6 {
                    return Ordering::Greater;
                }
                return Ordering::Less;
            }
            //let adr_diff = self.host_address - oth.host_address;
            if self.host_address < oth.host_address  {
                return Ordering::Less;
            } else if self.host_address > oth.host_address {
                return Ordering::Greater;
            }
            return self.prefix.cmp(&oth.prefix);
    }
}

impl PartialOrd for IPAddress {
    fn partial_cmp(&self, other: &IPAddress) -> Option<Ordering> {
        Some(self.cmp(other))
    }

}

impl PartialEq for IPAddress {
    fn eq(&self, other: &Self) -> bool {
        return self.ip_bits.version == other.ip_bits.version &&
            self.prefix == other.prefix &&
            self.host_address == other.host_address &&
            self.mapped.eq(&other.mapped)
    }
    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for IPAddress {}


impl IPAddress {
    /// Parse the argument string to create a new
    /// IPv4, IPv6 or Mapped IP object
    ///
    ///   ip  = IPAddress.parse "172.16.10.1/24"
    ///  ip6 = IPAddress.parse "2001:db8::8:800:200c:417a/64"
    ///  ip_mapped = IPAddress.parse "::ffff:172.16.10.1/128"
    ///
    /// All the object created will be instances of the
    /// correct class:
    ///
    ///  ip.class
    ///   //=> IPAddress::IPv4
    /// ip6.class
    ///   //=> IPAddress::IPv6
    /// ip_mapped.class
    ///   //=> IPAddress::IPv6::Mapped
    ///
    pub fn parse<S: Into<String>>(_str: S) -> Result<IPAddress, String> {
        let str = _str.into();
        let re_mapped = Regex::new(r":.+\.").unwrap();
        let re_ipv4 = Regex::new(r"\.").unwrap();
        let re_ipv6 = Regex::new(r":").unwrap();
        if re_mapped.is_match(&str) {
            // println!("mapped:{}", &str);
            return ::ipv6_mapped::new(str);
        } else {
            if re_ipv4.is_match(&str) {
                // println!("ipv4:{}", &str);
                return ::ipv4::new(str);
            } else if re_ipv6.is_match(&str) {
                // println!("ipv6:{}", &str);
                return ::ipv6::new(str);
            }
        }
        return Err(format!("Unknown IP Address {}", str));
    }

    pub fn split_at_slash(str: &String) -> (String, Option<String>) {
        let slash : Vec<&str> = str.trim().split("/").collect();
        let mut addr = String::new();
        if slash.get(0).is_some() {
            addr.push_str(slash.get(0).unwrap().to_string().trim());
        }
        if slash.get(1).is_some() {
            return (addr, Some(String::from(slash.get(1).unwrap().to_string().trim())));
        } else {
            return (addr, None);
        }
    }
    #[allow(dead_code)]
    pub fn from(&self, addr: &BigUint, prefix: &Prefix) -> IPAddress {
        return IPAddress {
            ip_bits: self.ip_bits.clone(),
            host_address: addr.clone(),
            prefix: prefix.clone(),
            mapped: self.mapped.clone(),<commit_msg>lazy static for regex<commit_after>
use core::ops::Add;
use core::ops::Shl;
use core::ops::Shr;
use core::ops::Sub;
use core::ops::Rem;
// use core::ops::Rem;
// use core::ops::Range;
//use core::iter::Step;
use core::iter::Iterator;
use core::cmp::Ordering;
use core::cmp::Ord;
use core::convert::From;
// use core::fmt::Debug;

use num::bigint::BigUint;
use num::bigint::ToBigUint;
// use num_integer::Integer;

use ip_bits::IpBits;
use prefix::Prefix;
use regex::Regex;
// use std::f64;
use std::fmt;

use num_traits::identities::Zero;
use num_traits::identities::One;
use num_traits::FromPrimitive;

use num_traits::cast::ToPrimitive;

use ip_bits::IpVersion;


pub struct IPAddress {
    pub ip_bits: &'static IpBits,
    pub host_address: BigUint,
    pub prefix: Prefix,
    pub mapped: Option<Box<IPAddress>>,
    pub vt_is_private: fn(&IPAddress) -> bool,
    pub vt_is_loopback: fn(&IPAddress) -> bool,
    pub vt_to_ipv6: fn(&IPAddress) -> IPAddress
}

impl fmt::Debug for IPAddress {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "IPAddress: {}", self.to_string())
    }
}

lazy_static! {
        static ref RE_MAPPED : Regex = Regex::new(r":.+\.").unwrap();
        static ref RE_IPV4 : Regex = Regex::new(r"\.").unwrap();
        static ref RE_IPV6 : Regex = Regex::new(r":").unwrap();
}


impl Clone for IPAddress {
    fn clone(&self) -> IPAddress {
        IPAddress {
            ip_bits: self.ip_bits.clone(),
            host_address: self.host_address.clone(),
            prefix: self.prefix.clone(),
            mapped: self.mapped.clone(),
            vt_is_private: self.vt_is_private,
            vt_is_loopback: self.vt_is_loopback,
            vt_to_ipv6: self.vt_to_ipv6
        }
    }
}


impl Ord for IPAddress {
    fn cmp(&self, oth: & IPAddress) -> Ordering {
            if self.ip_bits.version != oth.ip_bits.version {
                if self.ip_bits.version == IpVersion::V6 {
                    return Ordering::Greater;
                }
                return Ordering::Less;
            }
            //let adr_diff = self.host_address - oth.host_address;
            if self.host_address < oth.host_address  {
                return Ordering::Less;
            } else if self.host_address > oth.host_address {
                return Ordering::Greater;
            }
            return self.prefix.cmp(&oth.prefix);
    }
}

impl PartialOrd for IPAddress {
    fn partial_cmp(&self, other: &IPAddress) -> Option<Ordering> {
        Some(self.cmp(other))
    }

}

impl PartialEq for IPAddress {
    fn eq(&self, other: &Self) -> bool {
        return self.ip_bits.version == other.ip_bits.version &&
            self.prefix == other.prefix &&
            self.host_address == other.host_address &&
            self.mapped.eq(&other.mapped)
    }
    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for IPAddress {}


impl IPAddress {
    /// Parse the argument string to create a new
    /// IPv4, IPv6 or Mapped IP object
    ///
    ///   ip  = IPAddress.parse "172.16.10.1/24"
    ///  ip6 = IPAddress.parse "2001:db8::8:800:200c:417a/64"
    ///  ip_mapped = IPAddress.parse "::ffff:172.16.10.1/128"
    ///
    /// All the object created will be instances of the
    /// correct class:
    ///
    ///  ip.class
    ///   //=> IPAddress::IPv4
    /// ip6.class
    ///   //=> IPAddress::IPv6
    /// ip_mapped.class
    ///   //=> IPAddress::IPv6::Mapped
    ///
    pub fn parse<S: Into<String>>(_str: S) -> Result<IPAddress, String> {
        let str = _str.into();
        if RE_MAPPED.is_match(&str) {
            // println!("mapped:{}", &str);
            return ::ipv6_mapped::new(str);
        } else {
            if RE_IPV4.is_match(&str) {
                // println!("ipv4:{}", &str);
                return ::ipv4::new(str);
            } else if RE_IPV6.is_match(&str) {
                // println!("ipv6:{}", &str);
                return ::ipv6::new(str);
            }
        }
        return Err(format!("Unknown IP Address {}", str));
    }

    pub fn split_at_slash(str: &String) -> (String, Option<String>) {
        let slash : Vec<&str> = str.trim().split("/").collect();
        let mut addr = String::new();
        if slash.get(0).is_some() {
            addr.push_str(slash.get(0).unwrap().to_string().trim());
        }
        if slash.get(1).is_some() {
            return (addr, Some(String::from(slash.get(1).unwrap().to_string().trim())));
        } else {
            return (addr, None);
        }
    }
    #[allow(dead_code)]
    pub fn from(&self, addr: &BigUint, prefix: &Prefix) -> IPAddress {
        return IPAddress {
            ip_bits: self.ip_bits.clone(),
            host_address: addr.clone(),
            prefix: prefix.clone(),
            mapped: self.mapped.clone(),
{'fraction_non_alphanumeric': 0.16160984256073402, 'fraction_numerical': 0.01334584506307997, 'mean_word_length': 2.1625453346521595, 'pattern_counts': {'":': 6, '<': 21, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5178268', 'n_tokens_mistral': 3265, 'n_tokens_neox': 3206, 'n_words': 649}