<commit_before>use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub struct Address {
    callsign: String,
    ssid: u8,
    c_bit: bool
}

impl Default for Address {
    fn default() -> Address {
        Address { callsign: "NOCALL".to_string(), ssid: 0, c_bit: false }
    }
}

impl fmt::Display for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ssid_str = match self.ssid {
            0 => "".to_string(),
            ssid => format!("-{}", ssid)
        };
        write!(f, "{}{}", self.callsign, ssid_str)
    }
}

#[derive(Debug)]
pub struct RouteEntry {
    repeater: Address,
    has_repeated: bool
}

#[derive(Debug)]
pub struct Ax25Frame {
    source: Address,
    destination: Address,
    /// The route the packet has taken/will take according to repeater entries in the address field
    route: Vec<RouteEntry>,
    /// AX.25 2.0-compliant stations will indicate in every frame whether it is a command
    /// or a response, as part of the address field.
    command_or_response: Option<CommandResponse>,
    content: FrameContent
}

impl Ax25Frame {
    /// Returns a UTF-8 string that is a "best effort" at displaying the information
    /// content of this frame. Returns None if there is no information field present.
    /// Most applications will need to work with the Vec<u8> info directly.
    pub fn info_string_lossy(&self) -> Option<String> {
        match self.content {
            FrameContent::Information { ref info, .. }
                => Some(String::from_utf8_lossy(&info).into_owned()),
            FrameContent::UnnumberedInformation { ref info, .. }
                => Some(String::from_utf8_lossy(&info).into_owned()),
            _ => None
        }
    }
}

impl fmt::Display for Ax25Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let info_display = match self.info_string_lossy() {
            Some(ref info) => info.clone(),
            None => "-".to_string()
        };
        write!(f, "Source\t\t{}\nDestination\t{}\n\
            Data\t\t\"{}\"",
            self.source, self.destination, info_display)
    }
}

#[derive(Debug, Default)]
pub struct ParseError {
    msg: String
}
impl ParseError {
    fn new() -> ParseError {
        ParseError { msg: "Parse error".to_string() }
    }
}
impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}
impl Error for ParseError {
    fn description(&self) -> &str {
        return &self.msg;
    }
}

// Mostly from AX.25 2.2 spec which has far more examples than 2.0
#[derive(Debug, PartialEq)]
pub enum ProtocolIdentifier {
    Layer3Impl,
    X25Plp,
    CompressedTcpIp,
    UncompressedTcpIp,
    SegmentationFragment,
    TexnetDatagram,
    LinkQuality,
    Appletalk,
    AppletalkArp,
    ArpaIp,
    ArpaAddress,
    Flexnet,
    NetRom,
    None,
    Escape,
    Unknown(u8)
}

#[derive(Debug, PartialEq)]
pub enum CommandResponse {
    Command,
    Response
}

#[derive(Debug, PartialEq)]
pub enum FrameContent {
    /// Information (I) frame
    Information {
        pid: ProtocolIdentifier,
        info: Vec<u8>,
        receive_sequence: u8,
        send_sequence: u8,
        poll: bool
    },

    /// RR Supervisory (S) frame
    ReceiveReady {
        receive_sequence: u8,
        poll_or_final: bool
    },
    /// RNR Supervisory (S) frame
    ReceiveNotReady {
        receive_sequence: u8,
        poll_or_final: bool
    },
    /// REJ Supervisory (S) frame
    Reject {
        receive_sequence: u8,
        poll_or_final: bool
    },

    /// SABM Unnumbered (U) frame
    SetAsynchronousBalancedMode {
        poll: bool
    },
    /// DISC Unnumbered (U) frame
    Disconnect {
        poll: bool
    },
    /// DM Unnumbered (U) frame
    DisconnectedMode {
        final_bit: bool // 'final' is a rust keyword
    },
    /// UA Unnumbered (U) frame
    UnnumberedAcknowledge {
        final_bit: bool
    },
    /// FRMR Unnumbered (U) frame. Flags correspond to names in the AX.25 specification.
    FrameReject {
        final_bit: bool,
        /// A raw copy of the control field in the frame that was rejected
        rejected_control_field_raw: u8,
        /// The attached control field contained an invalid Receive Sequence Number
        z: bool,
        /// The information field of a received frame exceeded the maximum allowable length.
        y: bool,
        /// A U or S frame was received that contained an information field.
        x: bool,
        /// The received control field was invalid or not implemented.
        w: bool,
        receive_sequence: u8,
        send_sequence: u8,
        command_response: CommandResponse
    },
    /// UI Unnumbered Information frame
    UnnumberedInformation {
        pid: ProtocolIdentifier,
        info: Vec<u8>,
        poll_or_final: bool
    }
}

fn parse_address(bytes: &[u8]) -> Result<Address, Box<Error>> {
    let mut dest_utf8: Vec<u8> = bytes[0..6].iter()
        .rev()
        .map(|&c| c >> 1)
        .skip_while(|&c| c == b' ')
        .collect::<Vec<u8>>();
    dest_utf8.reverse();
    Ok(Address {
        callsign: String::from_utf8(dest_utf8)?,
        ssid: (bytes[6] >> 1) & 0x0f,
        c_bit: bytes[6] & 0b1000_0000 > 0
    })
}

fn get_pid_from_byte(byte: &u8) -> ProtocolIdentifier {
    match *byte {
        pid if pid & 0b00110000 == 0b00010000
            || pid & 0b00110000 == 0b00100000 => ProtocolIdentifier::Layer3Impl,
        0x01 => ProtocolIdentifier::X25Plp,
        0x06 => ProtocolIdentifier::CompressedTcpIp,
        0x07 => ProtocolIdentifier::UncompressedTcpIp,
        0x08 => ProtocolIdentifier::SegmentationFragment,
        0xC3 => ProtocolIdentifier::TexnetDatagram,
        0xC4 => ProtocolIdentifier::LinkQuality,
        0xCA => ProtocolIdentifier::Appletalk,
        0xCB => ProtocolIdentifier::AppletalkArp,
        0xCC => ProtocolIdentifier::ArpaIp,
        0xCD => ProtocolIdentifier::ArpaAddress,
        0xCE => ProtocolIdentifier::Flexnet,
        0xCF => ProtocolIdentifier::NetRom,
        0xF0 => ProtocolIdentifier::None,
        0xFF => ProtocolIdentifier::Escape,
        pid => ProtocolIdentifier::Unknown(pid)
    }
}

fn parse_i_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() < 2 {
        return Err(Box::new(ParseError { msg: "Missing PID field".to_string() }));
    }
    let c = bytes[0]; // control octet
    Ok(FrameContent::Information {
        receive_sequence: c & 0b1110_0000 >> 5,
        send_sequence: c & 0b0000_1110 >> 1,
        poll: c & 0b0001_0000 > 0,
        pid: get_pid_from_byte(&bytes[1]),
        info: bytes[2..].iter().cloned().collect() // could be empty vec
    })
}

fn parse_s_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // These all have the same general layout
    // There should be no PID or info following this control byte
    let c = bytes[0];
    let n_r = c & 0b1110_0000 >> 5;
    let poll_or_final = c & 0b0001_0000 > 0;

    match c & 0b0000_1111 {
        0b0000_0001 => Ok(FrameContent::ReceiveReady {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        0b0000_0101 => Ok(FrameContent::ReceiveNotReady {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        0b0000_1001 => Ok(FrameContent::Reject {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        _ => Err(Box::new(ParseError { msg: "Unrecognised S field type".to_string() }))
    }
}

fn parse_u_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // The only moving part in control for U frames is the P/F bit
    // Two special cases to handle:
    // FRMR is followed by a 3-byte information field that must be parsed specially
    // UI is followed by PID and variable length information field
    let c = bytes[0];
    let poll_or_final = c & 0b0001_0000 > 0;

    // Ignore the P/F bit for identifying the command or response
    match c & 0b1110_1111 {
        0b0010_1111 => Ok(FrameContent::SetAsynchronousBalancedMode { poll: poll_or_final }),
        0b0100_0011 => Ok(FrameContent::Disconnect { poll: poll_or_final }),
        0b0000_1111 => Ok(FrameContent::DisconnectedMode { final_bit: poll_or_final }),
        0b0110_0011 => Ok(FrameContent::UnnumberedAcknowledge { final_bit: poll_or_final }),
        0b1000_0111 => parse_frmr_frame(bytes),
        0b0000_0011 => parse_ui_frame(bytes),
        _ => Err(Box::new(ParseError { msg: "Unrecognised U field type".to_string() }))
    }
}

fn parse_ui_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() < 2 {
        return Err(Box::new(ParseError { msg: "Missing PID field".to_string() }));
    }
    // Control, then PID, then Info
    Ok(FrameContent::UnnumberedInformation {
        poll_or_final: bytes[0] & 0b0001_0000 > 0,
        pid: get_pid_from_byte(&bytes[1]),
        info: bytes[2..].iter().cloned().collect()
    })
}

fn parse_frmr_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // Expect 24 bits following the control
    if bytes.len() != 4 {
        return Err(Box::new(ParseError { msg: "Wrong size for FRMR info".to_string() }));
    }
    Ok(FrameContent::FrameReject {
        final_bit: bytes[0] & 0b0001_0000 > 0,
        rejected_control_field_raw: bytes[3],
        z: bytes[1] & 0b0000_1000 > 0,
        y: bytes[1] & 0b0000_0100 > 0,
        x: bytes[1] & 0b0000_0010 > 0,
        w: bytes[1] & 0b0000_0001 > 0,
        receive_sequence: bytes[2] & 0b1110_0000 >> 5,
        command_response: match bytes[2] & 0b0001_0000 > 0 {
            true => CommandResponse::Response,
            false => CommandResponse::Command
        },
        send_sequence: bytes[2] & 0b0000_1110 >> 1
    })
}

/// Parse the content of the frame starting from the control field
fn parse_content(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() == 0 {
        return Err(Box::new(ParseError { msg: "Zero content length".to_string() }));
    }
    match bytes[0] {
        c if c & 0x01 == 0x00 => parse_i_frame(bytes),
        c if c & 0x03 == 0x01 => parse_s_frame(bytes),
        c if c & 0x03 == 0x03 => parse_u_frame(bytes),
        _ => Err(Box::new(ParseError { msg: "Unrecognised control field".to_string() }))
    }
}

pub fn parse_from_raw(bytes: Vec<u8>) -> Result<Ax25Frame, Box<Error>> {
    // Skip over leading null bytes
    let addr_start = bytes.iter().position(|&c| c != 0).ok_or(ParseError::new())?;
    let addr_end = bytes.iter().position(|&c| c & 0x01 == 0x01).ok_or(ParseError::new())?;
    let control = addr_end + 1;
    if addr_end - addr_start + 1 < 14 { // +1 because the "terminator" is actually within the last byte
        return Err(Box::new(ParseError { msg: format!("Address field too short: {} {}", addr_start, addr_end) }));
    }
    if control >= bytes.len() {
        return Err(Box::new(ParseError { msg: format!("Packet is unreasonably short: {} bytes", bytes.len() )}));
    }

    let dest = parse_address(&bytes[addr_start..addr_start+7])?;
    let src = parse_address(&bytes[addr_start+7..addr_start+14])?;
    let content = parse_content(&bytes[control..])?;
    let command_or_response = match (dest.c_bit, src.c_bit) {
        (true, false) => Some(CommandResponse::Command),
        (false, true) => Some(CommandResponse::Response),
        _ => None
    };

    Ok(Ax25Frame {
        source: src,
        destination: dest,
        route: Vec::new(),
        content: content,
        command_or_response: command_or_response
    })
}

#[test]
fn pid_test() {
    assert_eq!(get_pid_from_byte(&0x01), ProtocolIdentifier::X25Plp);
    assert_eq!(get_pid_from_byte(&0xCA), ProtocolIdentifier::Appletalk);
    assert_eq!(get_pid_from_byte(&0xFF), ProtocolIdentifier::Escape);
    assert_eq!(get_pid_from_byte(&0x45), ProtocolIdentifier::Unknown(0x45));
    assert_eq!(get_pid_from_byte(&0x10), ProtocolIdentifier::Layer3Impl);
    assert_eq!(get_pid_from_byte(&0x20), ProtocolIdentifier::Layer3Impl);
    assert_eq!(get_pid_from_byte(&0xA5), ProtocolIdentifier::Layer3Impl);
}<commit_msg>Add support for parsing route<commit_after>use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub struct Address {
    callsign: String,
    ssid: u8,
    c_bit: bool
}

impl Default for Address {
    fn default() -> Address {
        Address { callsign: "NOCALL".to_string(), ssid: 0, c_bit: false }
    }
}

impl fmt::Display for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ssid_str = match self.ssid {
            0 => "".to_string(),
            ssid => format!("-{}", ssid)
        };
        write!(f, "{}{}", self.callsign, ssid_str)
    }
}

#[derive(Debug)]
pub struct RouteEntry {
    repeater: Address,
    has_repeated: bool
}

#[derive(Debug)]
pub struct Ax25Frame {
    source: Address,
    destination: Address,
    /// The route the packet has taken/will take according to repeater entries in the address field
    route: Vec<RouteEntry>,
    /// AX.25 2.0-compliant stations will indicate in every frame whether it is a command
    /// or a response, as part of the address field.
    command_or_response: Option<CommandResponse>,
    content: FrameContent
}

impl Ax25Frame {
    /// Returns a UTF-8 string that is a "best effort" at displaying the information
    /// content of this frame. Returns None if there is no information field present.
    /// Most applications will need to work with the Vec<u8> info directly.
    pub fn info_string_lossy(&self) -> Option<String> {
        match self.content {
            FrameContent::Information { ref info, .. }
                => Some(String::from_utf8_lossy(&info).into_owned()),
            FrameContent::UnnumberedInformation { ref info, .. }
                => Some(String::from_utf8_lossy(&info).into_owned()),
            _ => None
        }
    }
}

impl fmt::Display for Ax25Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let info_display = match self.info_string_lossy() {
            Some(ref info) => info.clone(),
            None => "-".to_string()
        };
        write!(f, "Source\t\t{}\nDestination\t{}\n\
            Data\t\t\"{}\"",
            self.source, self.destination, info_display)
    }
}

#[derive(Debug, Default)]
pub struct ParseError {
    msg: String
}
impl ParseError {
    fn new() -> ParseError {
        ParseError { msg: "Parse error".to_string() }
    }
}
impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}
impl Error for ParseError {
    fn description(&self) -> &str {
        return &self.msg;
    }
}

// Mostly from AX.25 2.2 spec which has far more examples than 2.0
#[derive(Debug, PartialEq)]
pub enum ProtocolIdentifier {
    Layer3Impl,
    X25Plp,
    CompressedTcpIp,
    UncompressedTcpIp,
    SegmentationFragment,
    TexnetDatagram,
    LinkQuality,
    Appletalk,
    AppletalkArp,
    ArpaIp,
    ArpaAddress,
    Flexnet,
    NetRom,
    None,
    Escape,
    Unknown(u8)
}

#[derive(Debug, PartialEq)]
pub enum CommandResponse {
    Command,
    Response
}

#[derive(Debug, PartialEq)]
pub enum FrameContent {
    /// Information (I) frame
    Information {
        pid: ProtocolIdentifier,
        info: Vec<u8>,
        receive_sequence: u8,
        send_sequence: u8,
        poll: bool
    },

    /// RR Supervisory (S) frame
    ReceiveReady {
        receive_sequence: u8,
        poll_or_final: bool
    },
    /// RNR Supervisory (S) frame
    ReceiveNotReady {
        receive_sequence: u8,
        poll_or_final: bool
    },
    /// REJ Supervisory (S) frame
    Reject {
        receive_sequence: u8,
        poll_or_final: bool
    },

    /// SABM Unnumbered (U) frame
    SetAsynchronousBalancedMode {
        poll: bool
    },
    /// DISC Unnumbered (U) frame
    Disconnect {
        poll: bool
    },
    /// DM Unnumbered (U) frame
    DisconnectedMode {
        final_bit: bool // 'final' is a rust keyword
    },
    /// UA Unnumbered (U) frame
    UnnumberedAcknowledge {
        final_bit: bool
    },
    /// FRMR Unnumbered (U) frame. Flags correspond to names in the AX.25 specification.
    FrameReject {
        final_bit: bool,
        /// A raw copy of the control field in the frame that was rejected
        rejected_control_field_raw: u8,
        /// The attached control field contained an invalid Receive Sequence Number
        z: bool,
        /// The information field of a received frame exceeded the maximum allowable length.
        y: bool,
        /// A U or S frame was received that contained an information field.
        x: bool,
        /// The received control field was invalid or not implemented.
        w: bool,
        receive_sequence: u8,
        send_sequence: u8,
        command_response: CommandResponse
    },
    /// UI Unnumbered Information frame
    UnnumberedInformation {
        pid: ProtocolIdentifier,
        info: Vec<u8>,
        poll_or_final: bool
    }
}

fn parse_address(bytes: &[u8]) -> Result<Address, Box<Error>> {
    let mut dest_utf8: Vec<u8> = bytes[0..6].iter()
        .rev()
        .map(|&c| c >> 1)
        .skip_while(|&c| c == b' ')
        .collect::<Vec<u8>>();
    dest_utf8.reverse();
    Ok(Address {
        callsign: String::from_utf8(dest_utf8)?,
        ssid: (bytes[6] >> 1) & 0x0f,
        c_bit: bytes[6] & 0b1000_0000 > 0
    })
}

fn get_pid_from_byte(byte: &u8) -> ProtocolIdentifier {
    match *byte {
        pid if pid & 0b00110000 == 0b00010000
            || pid & 0b00110000 == 0b00100000 => ProtocolIdentifier::Layer3Impl,
        0x01 => ProtocolIdentifier::X25Plp,
        0x06 => ProtocolIdentifier::CompressedTcpIp,
        0x07 => ProtocolIdentifier::UncompressedTcpIp,
        0x08 => ProtocolIdentifier::SegmentationFragment,
        0xC3 => ProtocolIdentifier::TexnetDatagram,
        0xC4 => ProtocolIdentifier::LinkQuality,
        0xCA => ProtocolIdentifier::Appletalk,
        0xCB => ProtocolIdentifier::AppletalkArp,
        0xCC => ProtocolIdentifier::ArpaIp,
        0xCD => ProtocolIdentifier::ArpaAddress,
        0xCE => ProtocolIdentifier::Flexnet,
        0xCF => ProtocolIdentifier::NetRom,
        0xF0 => ProtocolIdentifier::None,
        0xFF => ProtocolIdentifier::Escape,
        pid => ProtocolIdentifier::Unknown(pid)
    }
}

fn parse_i_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() < 2 {
        return Err(Box::new(ParseError { msg: "Missing PID field".to_string() }));
    }
    let c = bytes[0]; // control octet
    Ok(FrameContent::Information {
        receive_sequence: c & 0b1110_0000 >> 5,
        send_sequence: c & 0b0000_1110 >> 1,
        poll: c & 0b0001_0000 > 0,
        pid: get_pid_from_byte(&bytes[1]),
        info: bytes[2..].iter().cloned().collect() // could be empty vec
    })
}

fn parse_s_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // These all have the same general layout
    // There should be no PID or info following this control byte
    let c = bytes[0];
    let n_r = c & 0b1110_0000 >> 5;
    let poll_or_final = c & 0b0001_0000 > 0;

    match c & 0b0000_1111 {
        0b0000_0001 => Ok(FrameContent::ReceiveReady {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        0b0000_0101 => Ok(FrameContent::ReceiveNotReady {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        0b0000_1001 => Ok(FrameContent::Reject {
            receive_sequence: n_r,
            poll_or_final: poll_or_final
        }),
        _ => Err(Box::new(ParseError { msg: "Unrecognised S field type".to_string() }))
    }
}

fn parse_u_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // The only moving part in control for U frames is the P/F bit
    // Two special cases to handle:
    // FRMR is followed by a 3-byte information field that must be parsed specially
    // UI is followed by PID and variable length information field
    let c = bytes[0];
    let poll_or_final = c & 0b0001_0000 > 0;

    // Ignore the P/F bit for identifying the command or response
    match c & 0b1110_1111 {
        0b0010_1111 => Ok(FrameContent::SetAsynchronousBalancedMode { poll: poll_or_final }),
        0b0100_0011 => Ok(FrameContent::Disconnect { poll: poll_or_final }),
        0b0000_1111 => Ok(FrameContent::DisconnectedMode { final_bit: poll_or_final }),
        0b0110_0011 => Ok(FrameContent::UnnumberedAcknowledge { final_bit: poll_or_final }),
        0b1000_0111 => parse_frmr_frame(bytes),
        0b0000_0011 => parse_ui_frame(bytes),
        _ => Err(Box::new(ParseError { msg: "Unrecognised U field type".to_string() }))
    }
}

fn parse_ui_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() < 2 {
        return Err(Box::new(ParseError { msg: "Missing PID field".to_string() }));
    }
    // Control, then PID, then Info
    Ok(FrameContent::UnnumberedInformation {
        poll_or_final: bytes[0] & 0b0001_0000 > 0,
        pid: get_pid_from_byte(&bytes[1]),
        info: bytes[2..].iter().cloned().collect()
    })
}

fn parse_frmr_frame(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    // Expect 24 bits following the control
    if bytes.len() != 4 {
        return Err(Box::new(ParseError { msg: "Wrong size for FRMR info".to_string() }));
    }
    Ok(FrameContent::FrameReject {
        final_bit: bytes[0] & 0b0001_0000 > 0,
        rejected_control_field_raw: bytes[3],
        z: bytes[1] & 0b0000_1000 > 0,
        y: bytes[1] & 0b0000_0100 > 0,
        x: bytes[1] & 0b0000_0010 > 0,
        w: bytes[1] & 0b0000_0001 > 0,
        receive_sequence: bytes[2] & 0b1110_0000 >> 5,
        command_response: match bytes[2] & 0b0001_0000 > 0 {
            true => CommandResponse::Response,
            false => CommandResponse::Command
        },
        send_sequence: bytes[2] & 0b0000_1110 >> 1
    })
}

/// Parse the content of the frame starting from the control field
fn parse_content(bytes: &[u8]) -> Result<FrameContent, Box<Error>> {
    if bytes.len() == 0 {
        return Err(Box::new(ParseError { msg: "Zero content length".to_string() }));
    }
    match bytes[0] {
        c if c & 0x01 == 0x00 => parse_i_frame(bytes),
        c if c & 0x03 == 0x01 => parse_s_frame(bytes),
        c if c & 0x03 == 0x03 => parse_u_frame(bytes),
        _ => Err(Box::new(ParseError { msg: "Unrecognised control field".to_string() }))
    }
}

pub fn parse_from_raw(bytes: Vec<u8>) -> Result<Ax25Frame, Box<Error>> {
    // Skip over leading null bytes
    let addr_start = bytes.iter().position(|&c| c != 0).ok_or(ParseError::new())?;
    let addr_end = bytes.iter().position(|&c| c & 0x01 == 0x01).ok_or(ParseError::new())?;
    let control = addr_end + 1;
    if addr_end - addr_start + 1 < 14 { // +1 because the "terminator" is actually within the last byte
        return Err(Box::new(ParseError { msg: format!("Address field too short: {} {}", addr_start, addr_end) }));
    }
    if control >= bytes.len() {
        return Err(Box::new(ParseError { msg: format!("Packet is unreasonably short: {} bytes", bytes.len() )}));
    }

    let dest = parse_address(&bytes[addr_start..addr_start+7])?;
    let src = parse_address(&bytes[addr_start+7..addr_start+14])?;
    let rpt_count = (addr_end + 1 - addr_start - 14) / 7;
    let mut route: Vec<RouteEntry> = Vec::new();
    for i in 0..rpt_count {
        let repeater = parse_address(&bytes[addr_start + 14 + i * 7 .. addr_start + 14 + (i+1) * 7])?;
        let entry = RouteEntry {
            has_repeated: repeater.c_bit, // The "C" bit in an address happens to be the repeated bit for a repeater
            repeater: repeater,
        };
        route.push(entry);
    }

    let content = parse_content(&bytes[control..])?;
    let command_or_response = match (dest.c_bit, src.c_bit) {
        (true, false) => Some(CommandResponse::Command),
        (false, true) => Some(CommandResponse::Response),
        _ => None
    };

    Ok(Ax25Frame {
        source: src,
        destination: dest,
        route: route,
        content: content,
        command_or_response: command_or_response
    })
}

#[test]
fn pid_test() {
    assert_eq!(get_pid_from_byte(&0x01), ProtocolIdentifier::X25Plp);
    assert_eq!(get_pid_from_byte(&0xCA), ProtocolIdentifier::Appletalk);
    assert_eq!(get_pid_from_byte(&0xFF), ProtocolIdentifier::Escape);
    assert_eq!(get_pid_from_byte(&0x45), ProtocolIdentifier::Unknown(0x45));
    assert_eq!(get_pid_from_byte(&0x10), ProtocolIdentifier::Layer3Impl);
    assert_eq!(get_pid_from_byte(&0x20), ProtocolIdentifier::Layer3Impl);
    assert_eq!(get_pid_from_byte(&0xA5), ProtocolIdentifier::Layer3Impl);
}<|endoftext|>


<commit_before>mod predicates;
mod scoring;
mod types;

use predicates::*;
use scoring::*;
use types::*;

use crate::common::Text;
use rayon::prelude::*;
use std::collections::VecDeque;

pub use types::{Candidate, Query};

// =======================================================================
// Let's try to implement fuzzaldrin-plus algorithm
// @see: https://github.com/jeancroy/fuzz-aldrin-plus/blob/84eac1d73bacbbd11978e6960f4aa89f8396c540/src/scorer.coffee#L83
// =======================================================================

// Max number missed consecutive hit = ceil(MISS_COEFF * query.len()) + 5
const MISS_COEFF: f32 = 0.75;

pub fn search(q: &str, pool: &VecDeque<Text>) -> Vec<Candidate> {
    let mut matches: Vec<Candidate>;
    let query: Query = q.into();

    if query.is_empty() {
        matches = pool.par_iter().map(|txt| txt.into()).collect();
    } else {
        matches = pool
            .par_iter()
            .map(|c| compute_match(&query, &c))
            .filter(|c| c.is_some())
            .map(|c| c.unwrap())
            .collect();

        matches.par_sort_unstable_by(|a, b| b.cmp(a));
    }

    matches
}

// NOTE: The only part missing (I think) from the original algorithm
// is the path score bonus
fn compute_match(query: &Query, subject: &Text) -> Option<Candidate> {
    if query.is_empty() {
        return None;
    }

    // -----------------------------------------------------------------
    // Check if the query is inside the subject
    if !is_match(query, subject) {
        return None;
    }

    // -----------------------------------------------------------------
    // Acronym sequence
    let acronym = score_acronyms(query, subject);

    // The whole query is an acronym, let's return that
    if acronym.count == query.len() {
        let score = score_quality(query.len(), subject.len(), acronym.score, acronym.position);
        let matches = acronym.matches;

        return Some(Candidate::new(subject, score, matches));
    }

    // -----------------------------------------------------------------
    // Exact Match
    if let Some(result) = score_exact_match(query, subject) {
        let score = result.score;
        let matches = result.matches;

        return Some(Candidate::new(subject, score, matches));
    }

    // -----------------------------------------------------------------
    // Individual characters
    // (Smith Waterman algorithm)

    // Init
    let mut score;
    let mut score_row = vec![0.0_f32; query.len()];
    let mut consecutive_row = vec![0.0_f32; query.len()];
    let scored_size = score_size(query.len(), subject.len());

    // backtrace Matrix
    let mut trace = TraceMatrix::new(subject.len(), query.len());

    let miss_budget = (MISS_COEFF * query.len() as f32).ceil() + 5.0;
    let mut miss_left = miss_budget;
    let mut should_rebuild = true;

    let mut subject_iter = subject.lowercase_iter().enumerate();
    'subject_loop: while let Some((subject_index, subject_grapheme)) = subject_iter.next() {
        if !query.contains(subject_grapheme) {
            if should_rebuild {
                consecutive_row = vec![0.0_f32; query.len()];
                should_rebuild = false;
            }

            continue 'subject_loop;
        }

        score = 0.0;
        let mut score_diag = 0.0;
        let mut consecutive_diag = 0.0;
        let mut record_miss = true;
        should_rebuild = true;

        let mut query_iter = query.lowercase_iter().enumerate();
        while let Some((query_index, query_grapheme)) = query_iter.next() {
            let score_up = score_row[query_index];
            if score_up >= score {
                score = score_up;
                trace.up_at(query_index, subject_index);
            } else {
                trace.left_at(query_index, subject_index);
            }

            let mut consecutive_score = 0.0;

            if query_grapheme == subject_grapheme {
                let is_start = is_start_of_word(subject, subject_index);

                if consecutive_diag > 0.0 {
                    consecutive_score = consecutive_diag;
                } else {
                    consecutive_score =
                        score_consecutives(query, subject, query_index, subject_index, is_start);
                }

                let score_char =
                    score_character(subject_index, is_start, acronym.score, consecutive_score);
                let align = score_diag + score_char;

                if align > score {
                    score = align;
                    trace.diagonal_at(query_index, subject_index);
                    miss_left = miss_budget;
                } else {
                    consecutive_score = 0.0;

                    if record_miss {
                        miss_left -= 1.0;

                        if miss_left <= 0.0 {
                            let final_score =
                                score.max(score_row[query.last_index()]) * scored_size;
                            if final_score <= 0.0 {
                                return None;
                            } else {
                                let matches = trace.traceback(query_index, subject_index);

                                return Some(Candidate::new(subject, final_score, matches));
                            }
                        }
                    }

                    record_miss = false;
                }
            }

            score_diag = score_up;
            consecutive_diag = consecutive_row[query_index];
            consecutive_row[query_index] = consecutive_score;
            score_row[query_index] = score;

            if score <= 0.0 {
                trace.stop_at(query_index, subject_index);
            }
        }
    }

    let final_score = score_row[query.last_index()] * scored_size;
    if final_score == 0.0 {
        None
    } else {
        let matches = trace.traceback(query.last_index(), subject.last_index());

        Some(Candidate::new(subject, final_score, matches))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::common::TextBuilder;

    #[test]
    fn matches_test() {
        let cases: Vec<(Query, &str, Vec<usize>)> = vec![
            // Exact acronym
            ("fft".into(), "FirstFactoryTest".into(), vec![0, 5, 12]),
            // Extra acronym letters
            ("fft".into(), "FirstFactoryTest.ts".into(), vec![0, 5, 12]),
            // Exact match
            ("core".into(), "0core0app.rb".into(), vec![1, 2, 3, 4]),
            // Exact match, second position is better
            (
                "core".into(),
                "0core0app_core.rb".into(),
                vec![10, 11, 12, 13],
            ),
            // Consecutive letters
            ("core".into(), "controller".into(), vec![0, 1, 4, 8]),
        ];

        for (query, string, expected) in cases {
            let subject = TextBuilder::build(string);
            let result = compute_match(&query, &subject);
            assert!(result.is_some());

            let result = result.unwrap();
            assert_eq!(
                result.matches, expected,
                "Expected {} to have matches {:?} inside {:?}",
                query, expected, subject,
            );
        }
    }

    #[test]
    fn compute_match_on_different_queries_test() {
        let cases: Vec<(Query, Query, &str)> = vec![
            // Acronym wins
            ("psh".into(), "push".into(), "Plus: Stage Hunk".into()),
            // Exact world wins
            ("Hello".into(), "he".into(), "Hello World".into()),
            // More consecutive chars wins
            ("ello".into(), "hllo".into(), "Hello World".into()),
        ];

        for (a, b, string) in cases {
            let subject = TextBuilder::build(string);
            let result_a = compute_match(&a, &subject);
            let result_b = compute_match(&b, &subject);

            assert!(result_a.is_some());
            assert!(result_b.is_some());

            let result_a = result_a.unwrap();
            let result_b = result_b.unwrap();

            assert!(
                result_a.score() > result_b.score(),
                "Expected {} to have a higher score than {} inside {:?}",
                a,
                b,
                subject,
            );
        }
    }
}
<commit_msg>Minor comment changes in fuzzy mod<commit_after>mod predicates;
mod scoring;
mod types;

use predicates::*;
use scoring::*;
use types::*;

use crate::common::Text;
use rayon::prelude::*;
use std::collections::VecDeque;

pub use types::{Candidate, Query};

// Max number missed consecutive hit = ceil(MISS_COEFF * query.len()) + 5
const MISS_COEFF: f32 = 0.75;

/// Search for candidates to match a query
///
/// * If the query is empty it just returns the same pool of candidates
/// * Otherwise it will try to compute the best match for each candidate
///   and then sort them from higher score to lower
pub fn search(q: &str, pool: &VecDeque<Text>) -> Vec<Candidate> {
    let mut matches: Vec<Candidate>;
    let query: Query = q.into();

    if query.is_empty() {
        matches = pool.par_iter().map(|txt| txt.into()).collect();
    } else {
        matches = pool
            .par_iter()
            .map(|c| compute_match(&query, &c))
            .filter(|c| c.is_some())
            .map(|c| c.unwrap())
            .collect();

        matches.par_sort_unstable_by(|a, b| b.cmp(a));
    }

    matches
}

/// Custom port of the fuzzaldrin-plus algorithm used in Atom editor.
///
/// This function will return a Candidate with the computed score and
/// matches
///
/// NOTE: The only part missing (I think) from the original algorithm
///   is the path score bonus
///
/// Links:
///   * https://github.com/jeancroy/fuzz-aldrin-plus/blob/84eac1d73bacbbd11978e6960f4aa89f8396c540/src/scorer.coffee#L83
///   * https://github.com/jeancroy/fuzz-aldrin-plus/blob/84eac1d73bacbbd11978e6960f4aa89f8396c540/src/matcher.coffee#L172
fn compute_match(query: &Query, subject: &Text) -> Option<Candidate> {
    if query.is_empty() {
        return None;
    }

    // -----------------------------------------------------------------
    // Check if the query is inside the subject
    if !is_match(query, subject) {
        return None;
    }

    // -----------------------------------------------------------------
    // Acronym sequence
    let acronym = score_acronyms(query, subject);

    // The whole query is an acronym, let's return that
    if acronym.count == query.len() {
        let score = score_quality(query.len(), subject.len(), acronym.score, acronym.position);
        let matches = acronym.matches;

        return Some(Candidate::new(subject, score, matches));
    }

    // -----------------------------------------------------------------
    // Exact Match
    if let Some(result) = score_exact_match(query, subject) {
        let score = result.score;
        let matches = result.matches;

        return Some(Candidate::new(subject, score, matches));
    }

    // -----------------------------------------------------------------
    // Individual characters
    // (Smith Waterman algorithm)

    // Init
    let mut score;
    let mut score_row = vec![0.0_f32; query.len()];
    let mut consecutive_row = vec![0.0_f32; query.len()];
    let scored_size = score_size(query.len(), subject.len());

    let miss_budget = (MISS_COEFF * query.len() as f32).ceil() + 5.0;
    let mut miss_left = miss_budget;
    let mut should_rebuild = true;

    // Trace Matrix, this is used to recover best matches positions
    let mut trace = TraceMatrix::new(subject.len(), query.len());

    let mut subject_iter = subject.lowercase_iter().enumerate();
    'subject_loop: while let Some((subject_index, subject_grapheme)) = subject_iter.next() {
        if !query.contains(subject_grapheme) {
            if should_rebuild {
                consecutive_row = vec![0.0_f32; query.len()];
                should_rebuild = false;
            }

            continue 'subject_loop;
        }

        score = 0.0;
        let mut score_diag = 0.0;
        let mut consecutive_diag = 0.0;
        let mut record_miss = true;
        should_rebuild = true;

        let mut query_iter = query.lowercase_iter().enumerate();
        while let Some((query_index, query_grapheme)) = query_iter.next() {
            let mut consecutive_score = 0.0;

            let score_up = score_row[query_index];
            if score_up >= score {
                score = score_up;
                trace.up_at(query_index, subject_index);
            } else {
                trace.left_at(query_index, subject_index);
            }

            if query_grapheme == subject_grapheme {
                let is_start = is_start_of_word(subject, subject_index);

                if consecutive_diag > 0.0 {
                    consecutive_score = consecutive_diag;
                } else {
                    consecutive_score =
                        score_consecutives(query, subject, query_index, subject_index, is_start);
                }

                let score_char =
                    score_character(subject_index, is_start, acronym.score, consecutive_score);
                let align = score_diag + score_char;

                if align > score {
                    score = align;
                    trace.diagonal_at(query_index, subject_index);
                    miss_left = miss_budget;
                } else {
                    consecutive_score = 0.0;

                    if record_miss {
                        miss_left -= 1.0;

                        if miss_left <= 0.0 {
                            let final_score =
                                score.max(score_row[query.last_index()]) * scored_size;
                            if final_score <= 0.0 {
                                return None;
                            } else {
                                let matches = trace.traceback(query_index, subject_index);

                                return Some(Candidate::new(subject, final_score, matches));
                            }
                        }
                    }

                    record_miss = false;
                }
            }

            score_diag = score_up;
            consecutive_diag = consecutive_row[query_index];
            consecutive_row[query_index] = consecutive_score;
            score_row[query_index] = score;

            if score <= 0.0 {
                trace.stop_at(query_index, subject_index);
            }
        }
    }

    let final_score = score_row[query.last_index()] * scored_size;
    if final_score == 0.0 {
        None
    } else {
        let matches = trace.traceback(query.last_index(), subject.last_index());

        Some(Candidate::new(subject, final_score, matches))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::common::TextBuilder;

    #[test]
    fn matches_test() {
        let cases: Vec<(Query, &str, Vec<usize>)> = vec![
            // Exact acronym
            ("fft".into(), "FirstFactoryTest", vec![0, 5, 12]),
            // Extra acronym letters
            ("fft".into(), "FirstFactoryTest.ts", vec![0, 5, 12]),
            // Exact match
            ("core".into(), "0core0app.rb", vec![1, 2, 3, 4]),
            // Exact match, second position is better
            (
                "core".into(),
                "0core0app_core.rb".into(),
                vec![10, 11, 12, 13],
            ),
            // Consecutive letters
            ("core".into(), "controller".into(), vec![0, 1, 4, 8]),
        ];

        for (query, string, expected) in cases {
            let subject = TextBuilder::build(string);
            let result = compute_match(&query, &subject);
            assert!(result.is_some());

            let result = result.unwrap();
            assert_eq!(
                result.matches, expected,
                "Expected {} to have matches {:?} inside {}",
                query, expected, subject,
            );
        }
    }

    #[test]
    fn compute_match_on_different_queries_test() {
        let cases: Vec<(Query, Query, &str)> = vec![
            // Acronym wins
            ("psh".into(), "push".into(), "Plus: Stage Hunk"),
            // Exact world wins
            ("Hello".into(), "he".into(), "Hello World"),
            // More consecutive chars wins
            ("ello".into(), "hllo".into(), "Hello World"),
        ];

        for (a, b, string) in cases {
            let subject = TextBuilder::build(string);
            let result_a = compute_match(&a, &subject);
            let result_b = compute_match(&b, &subject);

            assert!(result_a.is_some());
            assert!(result_b.is_some());

            let result_a = result_a.unwrap();
            let result_b = result_b.unwrap();

            assert!(
                result_a.score() > result_b.score(),
                "Expected {} to have a higher score than {} inside {}",
                a,
                b,
                subject,
            );
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Eq;
use std::collections::HashMap;
use std::hash::Hash;

pub struct Graph<N, ND, ED> {
    nodes: HashMap<N, ND>,
    edges: HashMap<N, HashMap<N, ED>>,
}

impl<N, ND, ED> Graph<N, ND, ED>
    where N: Copy + Eq + Hash,
          ED: Copy
{
    pub fn new() -> Graph<N, ND, ED> {
        Graph {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    pub fn add_node(&mut self, node: N, data: ND) {
        self.nodes.insert(node, data); // Insert node, if it already exists data will be updated.

        if !self.nodes.contains_key(&node) {
            self.edges.insert(node, HashMap::new());
        }
    }

    pub fn node_data(&self, node: N) -> Option<&ND> {
        self.nodes.get(&node)
    }

    pub fn add_edge(&mut self, u: N, v: N, data: ED) {
        // Add nodes.
        // if !self.nodes.contains_key(&u) {
        //     self.nodes.insert(u, data);
        //     self.edges.insert(u, HashMap::new());
        // }
        // if !self.nodes.contains_key(&v) {
        //     self.nodes.insert(v, data);
        //     self.edges.insert(v, HashMap::new());
        // }

        // TODO: If not adding nodes when adding an edge, still check for nodes existance.

        // Add edges.
        self.edges
            .entry(u)
            .or_insert(HashMap::new())
            .insert(v, data);
        self.edges
            .entry(v)
            .or_insert(HashMap::new())
            .insert(u, data);
    }
}

#[cfg(test)]
mod tests {
    use super::Graph;

    #[test]
    fn test_add_node() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node1", 2);
        graph.add_node("node3", 3);

        assert!(graph.nodes["node1"] == 2);
        assert!(graph.nodes["node3"] == 3);
    }

    #[test]
    fn test_node_data() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node2", 2);

        assert!(*graph.node_data("node1").unwrap() == 1);
        assert!(*graph.node_data("node2").unwrap() == 2);
        assert!(graph.node_data("no_node") == None);
    }

    #[test]
    fn test_add_edge() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node1", 2);
        graph.add_node("node3", 3);

        graph.add_edge("node1", "node2", 1);
        graph.add_edge("node1", "node2", 2);
        graph.add_edge("node2", "node3", 3);

        assert!(graph.edges["node1"]["node2"] == 2);
        assert!(graph.edges["node2"]["node3"] == 3);
    }
}
<commit_msg>Implement node iterators.<commit_after>use std::cmp::Eq;
use std::collections::HashMap;
use std::collections::hash_map::{Iter, Keys};
use std::hash::Hash;

pub struct Graph<N, ND, ED> {
    nodes: HashMap<N, ND>,
    edges: HashMap<N, HashMap<N, ED>>,
}

impl<N, ND, ED> Graph<N, ND, ED>
    where N: Copy + Eq + Hash,
          ED: Copy
{
    pub fn new() -> Graph<N, ND, ED> {
        Graph {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    pub fn add_node(&mut self, node: N, data: ND) {
        self.nodes.insert(node, data); // Insert node, if it already exists data will be updated.

        if !self.nodes.contains_key(&node) {
            self.edges.insert(node, HashMap::new());
        }
    }

    pub fn node_data(&self, node: N) -> Option<&ND> {
        self.nodes.get(&node)
    }

    pub fn nodes(&self) -> Keys<N, ND> {
        self.nodes.keys()
    }

    pub fn nodes_data(&self) -> Iter<N, ND> {
        self.nodes.iter()
    }

    pub fn add_edge(&mut self, u: N, v: N, data: ED) {
        // if !self.nodes.contains_key(&u) {
        //     // TODO: Cant add edge if node doesnt exist.
        // }
        // if !self.nodes.contains_key(&v) {
        //     // TODO: Cant add edge if node doesnt exist.
        // }

        // Add edges.
        self.edges
            .entry(u)
            .or_insert(HashMap::new())
            .insert(v, data);
        self.edges
            .entry(v)
            .or_insert(HashMap::new())
            .insert(u, data);
    }
}

#[cfg(test)]
mod tests {
    use super::Graph;

    #[test]
    fn test_add_node() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node1", 2);
        graph.add_node("node3", 3);

        assert!(graph.nodes["node1"] == 2);
        assert!(graph.nodes["node3"] == 3);
    }

    #[test]
    fn test_node_data() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node2", 2);

        assert!(*graph.node_data("node1").unwrap() == 1);
        assert!(*graph.node_data("node2").unwrap() == 2);
        assert!(graph.node_data("no_node") == None);
    }

    #[test]
    fn test_nodes() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node2", 2);
        graph.add_node("node3", 3);

        let nodes: Vec<_> = graph.nodes().cloned().collect();

        assert!(nodes.contains(&"node1"));
        assert!(nodes.contains(&"node2"));
        assert!(nodes.contains(&"node3"));
    }

    #[test]
    fn test_nodes_data() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node2", 2);
        graph.add_node("node3", 3);

        let nodes_data: Vec<_> = graph.nodes_data().collect();

        assert!(nodes_data.contains(&(&"node1", &1)));
        assert!(nodes_data.contains(&(&"node2", &2)));
        assert!(nodes_data.contains(&(&"node3", &3)));
    }

    #[test]
    fn test_add_edge() {
        let mut graph: Graph<&str, u32, u32> = Graph::new();

        graph.add_node("node1", 1);
        graph.add_node("node1", 2);
        graph.add_node("node3", 3);

        graph.add_edge("node1", "node2", 1);
        graph.add_edge("node1", "node2", 2);
        graph.add_edge("node2", "node3", 3);

        assert!(graph.edges["node1"]["node2"] == 2);
        assert!(graph.edges["node2"]["node3"] == 3);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::{self, Write};

use config::Config;
use dep::ResolvedDep;
use error::CliResult;

pub type Nd = usize;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub struct Ed(pub Nd, pub Nd);

impl Ed {
    pub fn label<W: Write>(&self, w: &mut W, dg: &DepGraph) -> io::Result<()> {
        use dep::DepKind::{Optional, Dev, Build};
        let parent = dg.get(self.0).unwrap().kind();
        let child = dg.get(self.1).unwrap().kind();

        match (parent, child) {
            (Build, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.build_lines),
            (Build, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Build, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Dev, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Dev, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Dev, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            _               => writeln!(w, "[label=\"\"];")
        }
    }
}

impl fmt::Display for Ed {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let &Ed(il, ir) = self;
        write!(f, "N{} -> N{}", il, ir)
    }
}

#[derive(Debug)]
pub struct DepGraph<'c, 'o>
    where 'o: 'c
{
    pub nodes: Vec<ResolvedDep>,
    pub edges: Vec<Ed>,
    cfg: &'c Config<'o>,
}

impl<'c, 'o> DepGraph<'c, 'o> {
    pub fn new(cfg: &'c Config<'o>) -> Self {
        DepGraph {
            nodes: vec![],
            edges: vec![],
            cfg: cfg,
        }
    }

    pub fn add_child(&mut self, parent: usize, dep_name: &str, dep_ver: &str) -> usize {
        let idr = self.find_or_add(dep_name, dep_ver);
        self.edges.push(Ed(parent, idr));
        idr
    }

    pub fn get(&self, id: usize) -> Option<&ResolvedDep> {
        if id < self.nodes.len() {
            return Some(&self.nodes[id]);
        }
        None
    }

    pub fn remove(&mut self, id: usize) {
        debugln!("remove; index={}", id);
        self.nodes.remove(id);
        // Remove edges of the removed node.
        self.edges = self.edges.iter()
            .filter(|e| !(e.0 == id || e.1 == id))
            .cloned()
            .collect();
        self.shift_edges_after_node(id);
    }

    fn shift_edges_after_node(&mut self, id: usize) {
        enum Side {
            Left,
            Right,
        }
        let mut to_upd = vec![];
        for c in id..self.nodes.len() {
            for (eid, &Ed(idl, idr)) in self.edges.iter().enumerate() {
                if idl == c { to_upd.push((eid, Side::Left, c-1)); }
                if idr == c { to_upd.push((eid, Side::Right, c-1)); }
            }
        }
        for (eid, side, new) in to_upd {
            match side {
                Side::Left => self.edges[eid].0 = new,
                Side::Right => self.edges[eid].1 = new,
            }
        }
    }

    pub fn remove_orphans(&mut self) {
        let len = self.nodes.len();
        self.edges.retain(|&Ed(idl,idr)| idl < len && idr < len);
        debugln!("remove_orphans; nodes={:?}", self.nodes);
        loop {
            let mut removed = false;
            let mut used = vec![false; self.nodes.len()];
            used[0] = true;
            for &Ed(_, idr) in &self.edges {
                debugln!("remove_orphans; idr={}", idr);
                used[idr] = true;
            }
            debugln!("remove_orphans; unsued_nodes={:?}", used);

            for (id, &u) in used.iter().enumerate() {
                if !u {
                    debugln!("remove_orphans; removing={}", id);
                    self.nodes.remove(id);

                    // Remove edges originating from the removed node
                    self.edges.retain(|&Ed(origin,_)| origin != id);
                    // Adjust edges to match the new node indexes
                    for edge in self.edges.iter_mut() {
                        if edge.0 > id {
                            edge.0 -= 1;
                        }
                        if edge.1 > id {
                            edge.1 -= 1;
                        }
                    }
                    removed = true;
                    break;
                }
            }
            if !removed {
                break;
            }
        }
    }

    fn remove_self_pointing(&mut self) {
        loop {
            let mut found = false;
            let mut self_p = vec![false; self.edges.len()];
            for (eid ,&Ed(idl, idr)) in self.edges.iter().enumerate() {
                if idl == idr {
                    found = true;
                    self_p[eid] = true;
                    break;
                }
            }
            debugln!("remove_self_pointing; self_pointing={:?}", self_p);

            for (id, &u) in self_p.iter().enumerate() {
                if u {
                    debugln!("remove_self_pointing; removing={}", id);
                    self.edges.remove(id);
                    break;
                }
            }
            if !found {
                break;
            }
        }
    }

    pub fn find_or_add(&mut self, name: &str, ver: &str) -> usize {
        for (i, d) in self.nodes.iter().enumerate() {
            if d.name == name && d.ver == ver {
                return i;
            }
        }
        self.nodes.push(ResolvedDep::new(name.to_owned(), ver.to_owned()));
        self.nodes.len() - 1
    }

    pub fn render_to<W: Write>(mut self, output: &mut W) -> CliResult<()> {
        debugln!("exec=render_to;");
        self.edges.sort();
        self.edges.dedup();
        self.remove_orphans();
        self.remove_self_pointing();
        debugln!("dg={:#?}", self);
        try!(writeln!(output, "{}", "digraph dependencies {"));
        for (i, dep) in self.nodes.iter().enumerate() {
            try!(write!(output, "\tN{}", i));
            try!(dep.label(output, self.cfg));
        }
        for ed in &self.edges {
            try!(write!(output, "\t{}", ed));
            try!(ed.label(output, &self));
        }
        try!(writeln!(output, "{}", "}"));
        Ok(())
    }

}
<commit_msg>Fix typo<commit_after>use std::fmt;
use std::io::{self, Write};

use config::Config;
use dep::ResolvedDep;
use error::CliResult;

pub type Nd = usize;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub struct Ed(pub Nd, pub Nd);

impl Ed {
    pub fn label<W: Write>(&self, w: &mut W, dg: &DepGraph) -> io::Result<()> {
        use dep::DepKind::{Optional, Dev, Build};
        let parent = dg.get(self.0).unwrap().kind();
        let child = dg.get(self.1).unwrap().kind();

        match (parent, child) {
            (Build, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.build_lines),
            (Build, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Build, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Optional, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.optional_lines),
            (Dev, Build) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Dev, Dev) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            (Dev, Optional) => writeln!(w, "[label=\"\"{}];", dg.cfg.dev_lines),
            _               => writeln!(w, "[label=\"\"];")
        }
    }
}

impl fmt::Display for Ed {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let &Ed(il, ir) = self;
        write!(f, "N{} -> N{}", il, ir)
    }
}

#[derive(Debug)]
pub struct DepGraph<'c, 'o>
    where 'o: 'c
{
    pub nodes: Vec<ResolvedDep>,
    pub edges: Vec<Ed>,
    cfg: &'c Config<'o>,
}

impl<'c, 'o> DepGraph<'c, 'o> {
    pub fn new(cfg: &'c Config<'o>) -> Self {
        DepGraph {
            nodes: vec![],
            edges: vec![],
            cfg: cfg,
        }
    }

    pub fn add_child(&mut self, parent: usize, dep_name: &str, dep_ver: &str) -> usize {
        let idr = self.find_or_add(dep_name, dep_ver);
        self.edges.push(Ed(parent, idr));
        idr
    }

    pub fn get(&self, id: usize) -> Option<&ResolvedDep> {
        if id < self.nodes.len() {
            return Some(&self.nodes[id]);
        }
        None
    }

    pub fn remove(&mut self, id: usize) {
        debugln!("remove; index={}", id);
        self.nodes.remove(id);
        // Remove edges of the removed node.
        self.edges = self.edges.iter()
            .filter(|e| !(e.0 == id || e.1 == id))
            .cloned()
            .collect();
        self.shift_edges_after_node(id);
    }

    fn shift_edges_after_node(&mut self, id: usize) {
        enum Side {
            Left,
            Right,
        }
        let mut to_upd = vec![];
        for c in id..self.nodes.len() {
            for (eid, &Ed(idl, idr)) in self.edges.iter().enumerate() {
                if idl == c { to_upd.push((eid, Side::Left, c-1)); }
                if idr == c { to_upd.push((eid, Side::Right, c-1)); }
            }
        }
        for (eid, side, new) in to_upd {
            match side {
                Side::Left => self.edges[eid].0 = new,
                Side::Right => self.edges[eid].1 = new,
            }
        }
    }

    pub fn remove_orphans(&mut self) {
        let len = self.nodes.len();
        self.edges.retain(|&Ed(idl,idr)| idl < len && idr < len);
        debugln!("remove_orphans; nodes={:?}", self.nodes);
        loop {
            let mut removed = false;
            let mut used = vec![false; self.nodes.len()];
            used[0] = true;
            for &Ed(_, idr) in &self.edges {
                debugln!("remove_orphans; idr={}", idr);
                used[idr] = true;
            }
            debugln!("remove_orphans; unused_nodes={:?}", used);

            for (id, &u) in used.iter().enumerate() {
                if !u {
                    debugln!("remove_orphans; removing={}", id);
                    self.nodes.remove(id);

                    // Remove edges originating from the removed node
                    self.edges.retain(|&Ed(origin,_)| origin != id);
                    // Adjust edges to match the new node indexes
                    for edge in self.edges.iter_mut() {
                        if edge.0 > id {
                            edge.0 -= 1;
                        }
                        if edge.1 > id {
                            edge.1 -= 1;
                        }
                    }
                    removed = true;
                    break;
                }
            }
            if !removed {
                break;
            }
        }
    }

    fn remove_self_pointing(&mut self) {
        loop {
            let mut found = false;
            let mut self_p = vec![false; self.edges.len()];
            for (eid ,&Ed(idl, idr)) in self.edges.iter().enumerate() {
                if idl == idr {
                    found = true;
                    self_p[eid] = true;
                    break;
                }
            }
            debugln!("remove_self_pointing; self_pointing={:?}", self_p);

            for (id, &u) in self_p.iter().enumerate() {
                if u {
                    debugln!("remove_self_pointing; removing={}", id);
                    self.edges.remove(id);
                    break;
                }
            }
            if !found {
                break;
            }
        }
    }

    pub fn find_or_add(&mut self, name: &str, ver: &str) -> usize {
        for (i, d) in self.nodes.iter().enumerate() {
            if d.name == name && d.ver == ver {
                return i;
            }
        }
        self.nodes.push(ResolvedDep::new(name.to_owned(), ver.to_owned()));
        self.nodes.len() - 1
    }

    pub fn render_to<W: Write>(mut self, output: &mut W) -> CliResult<()> {
        debugln!("exec=render_to;");
        self.edges.sort();
        self.edges.dedup();
        self.remove_orphans();
        self.remove_self_pointing();
        debugln!("dg={:#?}", self);
        try!(writeln!(output, "{}", "digraph dependencies {"));
        for (i, dep) in self.nodes.iter().enumerate() {
            try!(write!(output, "\tN{}", i));
            try!(dep.label(output, self.cfg));
        }
        for ed in &self.edges {
            try!(write!(output, "\t{}", ed));
            try!(ed.label(output, &self));
        }
        try!(writeln!(output, "{}", "}"));
        Ok(())
    }

}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::cell::UnsafeCell;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Skip;
use std::slice::Iter;
use chrono::{NaiveDateTime, Duration};
use {Result, Error, Stop, Connection};

fn departure_ord(d1: &Departure, d2: &Departure) -> Ordering { d1.time.cmp(&d2.time) }

pub struct Graph<'a> {
    nodes: HashMap<String, UnsafeCell<StopNode<'a>>>,
}

pub struct StopNode<'g> {
    pub stop: &'g Stop,
    connections: Vec<Departure<'g>>
}

pub struct Departure<'g> {
    pub destination: &'g StopNode<'g>,
    pub time: NaiveDateTime,
    pub duration: Duration
}

impl<'g> StopNode<'g> {
    pub fn departures_after(&'g self, time: &NaiveDateTime) -> Skip<Iter<'g, Departure>> {
        let i = match self.connections.binary_search_by(|d| d.time.cmp(time)) {
            Ok(i) => i,
            Err(i) => i
        };
        self.connections.iter().skip(i)
    }
}

impl<'a> Graph<'a> {
    pub fn new() -> Graph<'a> {
        Graph::with_capacity(0)
    }

    pub fn with_capacity(capacity: usize) -> Graph<'a> {
        Graph { nodes: HashMap::with_capacity(capacity) }
    }

    pub fn construct(&'a mut self, stops: &'a Vec<Stop>, cnx: &Vec<Connection>)
        -> Result<()>
    {
        // construct the nodes
        for i in 0..stops.len() {
            let node = StopNode {
                stop: &stops[i],
                connections: Vec::new()
            };
            self.nodes.insert(stops[i].id.to_owned(), UnsafeCell::new(node));
        }

        // construct the edges and add them to the nodes
        for c in cnx.iter() {
            let to = self.nodes.get(&c.to)
                .ok_or(Error::Data(format!("Destination stop not found: {}", c.to)));
            let from = self.nodes.get(&c.from)
                .ok_or(Error::Data(format!("Origin stop not found: {}", c.from)));

            let edge = Departure {
                destination: unsafe { &*try!(to).get() },
                time: c.departs,
                duration: c.duration
            };

            unsafe { (*try!(from).get()).connections.push(edge); }
        }

        // sort the edges by departure time for quick retrieval
        for (_, node) in self.nodes.iter_mut() {
           unsafe { (*node.get()).connections.sort_by(departure_ord); }
        }

        Ok(())
    }

    pub fn get_stop<Q: ?Sized>(&'a self, id: &Q) -> Option<&'a StopNode>
            where String: Borrow<Q>, Q: Hash + Eq {
        unsafe { self.nodes.get(id).map(|n| &*n.get()) }
    }
}
<commit_msg>Allow augmentation of StopNodes<commit_after>use std::borrow::Borrow;
use std::cell::UnsafeCell;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Skip;
use std::slice::Iter;
use chrono::{NaiveDateTime, Duration};
use {Result, Error, Stop, Connection};

fn departure_ord<T>(d1: &Departure<T>, d2: &Departure<T>) -> Ordering { d1.time.cmp(&d2.time) }

pub struct Graph<'a, T: 'a> {
    nodes: HashMap<String, UnsafeCell<StopNode<'a, T>>>,
}

pub struct StopNode<'g, T: 'g> {
    pub stop: &'g Stop,
    connections: Vec<Departure<'g, T>>,
    data: Option<T>
}

pub struct Departure<'g, T: 'g> {
    pub destination: &'g StopNode<'g, T>,
    pub time: NaiveDateTime,
    pub duration: Duration
}

impl<'g, T> StopNode<'g, T> {
    pub fn departures_after(&'g self, time: &NaiveDateTime) -> Skip<Iter<'g, Departure<T>>> {
        let i = match self.connections.binary_search_by(|d| d.time.cmp(time)) {
            Ok(i) => i,
            Err(i) => i
        };
        self.connections.iter().skip(i)
    }

    pub fn augment(&'g mut self, data: T) {
        self.data = Some(data)
    }

    pub fn get_augment(&'g self) -> &Option<T> {
        &self.data
    }
}

impl<'a, T> Graph<'a, T> {
    pub fn new() -> Graph<'a, T> {
        Graph::with_capacity(0)
    }

    pub fn with_capacity(capacity: usize) -> Graph<'a, T> {
        Graph { nodes: HashMap::with_capacity(capacity) }
    }

    pub fn construct(&'a mut self, stops: &'a Vec<Stop>, cnx: &Vec<Connection>)
        -> Result<()>
    {
        // construct the nodes
        for i in 0..stops.len() {
            let node = StopNode {
                stop: &stops[i],
                connections: Vec::new(),
                data: None
            };
            self.nodes.insert(stops[i].id.to_owned(), UnsafeCell::new(node));
        }

        // construct the edges and add them to the nodes
        for c in cnx.iter() {
            let to = self.nodes.get(&c.to)
                .ok_or(Error::Data(format!("Destination stop not found: {}", c.to)));
            let from = self.nodes.get(&c.from)
                .ok_or(Error::Data(format!("Origin stop not found: {}", c.from)));

            let edge = Departure {
                destination: unsafe { &*try!(to).get() },
                time: c.departs,
                duration: c.duration
            };

            unsafe { (*try!(from).get()).connections.push(edge); }
        }

        // sort the edges by departure time for quick retrieval
        for (_, node) in self.nodes.iter_mut() {
           unsafe { (*node.get()).connections.sort_by(departure_ord); }
        }

        Ok(())
    }

    pub fn get_stop<Q: ?Sized>(&'a self, id: &Q) -> Option<&'a StopNode>
            where String: Borrow<Q>, Q: Hash + Eq {
        unsafe { self.nodes.get(id).map(|n| &*n.get()) }
    }
}
<|endoftext|>


<commit_before>use std;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum IpNet {
    V4(Ipv4Net),
    V6(Ipv6Net),
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv4Net {
    addr: Ipv4Addr,
    prefix_len: u8,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv6Net {
    addr: Ipv6Addr,
    prefix_len: u8,
}

// For the time being deref method calls to the IpAddr implemenations.

/*impl std::ops::Deref for IpNet {
    type Target = IpAddr;
    fn deref(&self) -> &Self::Target {
        match *self {
            IpNet::V4(ref a) => a.addr,
            IpNet::V6(ref a) => a.addr,
        }
    }
}*/

impl std::ops::Deref for Ipv4Net {
    type Target = Ipv4Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl std::ops::Deref for Ipv6Net {
    type Target = Ipv6Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl IpNet {
    pub fn supernet(&self) -> IpNet {
        match *self {
            IpNet::V4(ref a) => IpNet::V4(a.supernet()),
            IpNet::V6(ref a) => IpNet::V6(a.supernet()),
        }
    }

    pub fn contains(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
            (_, _) => false,
        }
    }

    pub fn sibling(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.sibling(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.sibling(b),
            (_, _) => false,
        }
    }
}

impl Ipv4Net {
    pub fn new(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
        // TODO: Should error if prefix_len > 32 as prefix_len <= 32 is
        // assumed in subsequent methods.
        Ipv4Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn netmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len > 0 {
                0xffffffff << 32 - self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn hostmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len < 32 {
                0xffffffff >> self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn network(&self) -> Ipv4Addr {
        // BitAnd is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) & u32::from(self.netmask()))
    }

    pub fn broadcast(&self) -> Ipv4Addr {
        // BitOr is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) | u32::from(self.hostmask()))
    }

    pub fn supernet(&self) -> Ipv4Net {
        Ipv4Net::new(Ipv4Addr::from(self.octets()), self.prefix_len - 1)
    }

    pub fn contains(&self, other: &Ipv4Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv4Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

impl Ipv6Net {
    pub fn new(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
        // TODO: Should error if prefix_len > 128 as prefix_len <= 128
        // is assumed in subsequent methods.
        Ipv6Net { addr: ip, prefix_len: prefix_len, }
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn netmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len > 0 { 0xffff_ffff_ffff_ffff << 64u8.saturating_sub(self.prefix_len) } else { 0x0 };
        let b: u64 = if self.prefix_len > 64 { 0xffff_ffff_ffff_ffff << 128 - self.prefix_len } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn hostmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len < 64 { 0xffff_ffff_ffff_ffff >> self.prefix_len } else { 0x0 };
        let b: u64 = if self.prefix_len < 128 { 0xffff_ffff_ffff_ffff >> self.prefix_len.saturating_sub(64) } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn network(&self) -> Ipv6Addr {
        // BitAnd is not implemented for Ipv6Addr.
        let ip = self.segments();
        let m = self.netmask().segments();

        Ipv6Addr::new(
            ip[0] & m[0], ip[1] & m[1], ip[2] & m[2], ip[3] & m[3],
            ip[4] & m[4], ip[5] & m[5], ip[6] & m[6], ip[7] & m[7]
        )
    }

    // TODO: Technically there is no such thing as a broadcast. Perhaps
    // we should change the network() and broadcast() methods to be
    // first() and last() or similar.
    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn broadcast(&self) -> Ipv6Addr {
        // BitOr is not implemented for Ipv4Addr.
        let ip = self.segments();
        let m = self.hostmask().segments();

        Ipv6Addr::new(
            ip[0] | m[0], ip[1] | m[1], ip[2] | m[2], ip[3] | m[3],
            ip[4] | m[4], ip[5] | m[5], ip[6] | m[6], ip[7] | m[7]
        )
    }

    pub fn supernet(&self) -> Ipv6Net {
        Ipv6Net::new(Ipv6Addr::from(self.segments()), self.prefix_len - 1)
    }

    pub fn contains(&self, other: &Ipv6Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv6Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

impl fmt::Display for IpNet {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNet::V4(ref a) => a.fmt(fmt),
            IpNet::V6(ref a) => a.fmt(fmt),
        }
    }
}

impl fmt::Display for Ipv4Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}

impl fmt::Display for Ipv6Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}

#[cfg(test)]
mod tests {
    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
    use std::option::Option::{Some, None};
    use std::str::FromStr;
    use ipnet::{IpNet, Ipv4Net, Ipv6Net};

    #[test]
    fn test_ipv4_net() {
        // TODO: Test the boundaries (/0, /32, /64, /128). Or iterate
        // over every bit.
        assert_eq!(
            IpNet::from_str("10.0.0.0/8").unwrap(),
            IpNet::V4(Ipv4Net { addr: Ipv4Addr::from_str("10.0.0.0").unwrap(), prefix_len: 8 })
        );
        assert_eq!(
            Ipv4Net::from_str("172.16.0.0/12").unwrap(),
            Ipv4Net { addr: Ipv4Addr::from_str("172.16.0.0").unwrap(), prefix_len: 12 }
        );
        assert_eq!(
            Ipv4Net::from_str("172.16.0.0/12").unwrap().netmask(),
            Ipv4Addr::from_str("255.240.0.0").unwrap()
        );
        assert_eq!(
            Ipv4Net::from_str("172.16.0.0/12").unwrap().hostmask(),
            Ipv4Addr::from_str("0.15.255.255").unwrap()
        );
        assert_eq!(
            Ipv4Net::from_str("172.16.0.0/12").unwrap().network(),
            Ipv4Addr::from_str("172.16.0.0").unwrap()
        );
        assert_eq!(
            Ipv4Net::from_str("172.16.0.0/12").unwrap().broadcast(),
            Ipv4Addr::from_str("172.31.255.255").unwrap()
        );
    }
}
<commit_msg>Adding subnets() methods.<commit_after>use std;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum IpNet {
    V4(Ipv4Net),
    V6(Ipv6Net),
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv4Net {
    addr: Ipv4Addr,
    prefix_len: u8,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv6Net {
    addr: Ipv6Addr,
    prefix_len: u8,
}

// For the time being deref method calls to the IpAddr implemenations.

/*impl std::ops::Deref for IpNet {
    type Target = IpAddr;
    fn deref(&self) -> &Self::Target {
        match *self {
            IpNet::V4(ref a) => a.addr,
            IpNet::V6(ref a) => a.addr,
        }
    }
}*/

impl std::ops::Deref for Ipv4Net {
    type Target = Ipv4Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl std::ops::Deref for Ipv6Net {
    type Target = Ipv6Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl IpNet {
    pub fn supernet(&self) -> IpNet {
        match *self {
            IpNet::V4(ref a) => IpNet::V4(a.supernet()),
            IpNet::V6(ref a) => IpNet::V6(a.supernet()),
        }
    }

    pub fn contains(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
            (_, _) => false,
        }
    }

    pub fn sibling(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.sibling(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.sibling(b),
            (_, _) => false,
        }
    }
}

impl Ipv4Net {
    pub fn new(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
        // TODO: Should error if prefix_len > 32 as prefix_len <= 32 is
        // assumed in subsequent methods.
        Ipv4Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn netmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len > 0 {
                0xffffffff << 32 - self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn hostmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len < 32 {
                0xffffffff >> self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn network(&self) -> Ipv4Addr {
        // BitAnd is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) & u32::from(self.netmask()))
    }

    pub fn broadcast(&self) -> Ipv4Addr {
        // BitOr is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) | u32::from(self.hostmask()))
    }

    pub fn supernet(&self) -> Ipv4Net {
        Ipv4Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Should the parameter be depth, as in the number of
    // divisions to make, or new_prefix_len (self explanatory), or
    // num_subnets? I suspect in use the later two will be more useful.
    // TODO: Should this be an iterator?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv4Net> {
        // TODO: Need to test bounds of new_prefix_len and error.
        // Or perhaps just set to 32 in that case.
        // TODO: std::ops::Add missing for Ipv4Addr
        let rng = 2u32.pow(32 - new_prefix_len as u32);
        let mut net = u32::from(self.network());
        let end = u32::from(self.broadcast());
        let mut res: Vec<Ipv4Net> = Vec::new();

        while net < end {
            res.push(Ipv4Net::new(Ipv4Addr::from(net), new_prefix_len));
            net += rng;
        }
        res

    }

    pub fn contains(&self, other: &Ipv4Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv4Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

impl Ipv6Net {
    pub fn new(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
        // TODO: Should error if prefix_len > 128 as prefix_len <= 128
        // is assumed in subsequent methods.
        Ipv6Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn addr(&self) -> Ipv6Addr {
        self.addr
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn netmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len > 0 { 0xffff_ffff_ffff_ffff << 64u8.saturating_sub(self.prefix_len) } else { 0x0 };
        let b: u64 = if self.prefix_len > 64 { 0xffff_ffff_ffff_ffff << 128 - self.prefix_len } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn hostmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len < 64 { 0xffff_ffff_ffff_ffff >> self.prefix_len } else { 0x0 };
        let b: u64 = if self.prefix_len < 128 { 0xffff_ffff_ffff_ffff >> self.prefix_len.saturating_sub(64) } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn network(&self) -> Ipv6Addr {
        // BitAnd is not implemented for Ipv6Addr.
        let ip = self.segments();
        let m = self.netmask().segments();

        Ipv6Addr::new(
            ip[0] & m[0], ip[1] & m[1], ip[2] & m[2], ip[3] & m[3],
            ip[4] & m[4], ip[5] & m[5], ip[6] & m[6], ip[7] & m[7]
        )
    }

    // TODO: Technically there is no such thing as a broadcast. Perhaps
    // we should change the network() and broadcast() methods to be
    // first() and last() or similar.
    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn broadcast(&self) -> Ipv6Addr {
        // BitOr is not implemented for Ipv4Addr.
        let ip = self.segments();
        let m = self.hostmask().segments();

        Ipv6Addr::new(
            ip[0] | m[0], ip[1] | m[1], ip[2] | m[2], ip[3] | m[3],
            ip[4] | m[4], ip[5] | m[5], ip[6] | m[6], ip[7] | m[7]
        )
    }

    pub fn supernet(&self) -> Ipv6Net {
        Ipv6Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Is there a nicer way to do this? Using u128 types would be
    // nice but they're not marked as stable yet. Should this return an
    // iterator instead of a vector?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv6Net> {
        // TODO: Need to implement a proper error handling scheme.
        if new_prefix_len <= self.prefix_len {
            return Vec::new();
        }

        let mut network = ipv6_addr_into_double_u64(self.network());
        let mut broadcast = ipv6_addr_into_double_u64(self.broadcast());

        let mask = ipv6_addr_into_double_u64(Ipv6Net::new(self.addr.clone(), new_prefix_len).hostmask());
        let mut res: Vec<Ipv6Net> = Vec::new();

        while network < broadcast {
            res.push(Ipv6Net::new(ipv6_addr_from_double_u64(network), new_prefix_len));

            network[0] |= mask[0];
            network[1] |= mask[1];

            let (lo, ov) = network[1].overflowing_add(1);
            network[1] = lo;

            if ov {
                network[0] += 1;
            }
        }

        res
    }

    pub fn contains(&self, other: &Ipv6Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv6Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_from_double_u64(segments: [u64; 2]) -> Ipv6Addr {
    let (hi, lo) = (segments[0], segments[1]);
    Ipv6Addr::new(
        (hi >> 48) as u16, (hi >> 32) as u16, (hi >> 16) as u16, hi as u16,
        (lo >> 48) as u16, (lo >> 32) as u16, (lo >> 16) as u16, lo as u16
    )
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_into_double_u64(ip: Ipv6Addr) -> [u64; 2] {
    let ip = ip.octets();
    [
        ((ip[0] as u64) << 56) + ((ip[1] as u64) << 48) +
        ((ip[2] as u64) << 40) + ((ip[3] as u64) << 32) +
        ((ip[4] as u64) << 24) + ((ip[5] as u64) << 16) +
        ((ip[6] as u64) << 8) + (ip[7] as u64),
        ((ip[8] as u64) << 56) + ((ip[9] as u64) << 48) +
        ((ip[10] as u64) << 40) + ((ip[11] as u64) << 32) +
        ((ip[12] as u64) << 24) + ((ip[13] as u64) << 16) +
        ((ip[14] as u64) << 8) + (ip[15] as u64),
    ]
}

impl fmt::Display for IpNet {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNet::V4(ref a) => a.fmt(fmt),
            IpNet::V6(ref a) => a.fmt(fmt),
        }
    }
}

impl fmt::Display for Ipv4Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}

impl fmt::Display for Ipv6Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}
<|endoftext|>


<commit_before>use super::*;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Crate {
    pub shebang: Option<String>,
    pub attrs: Vec<Attribute>,
    pub items: Vec<Item>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::inner_attr;
    use item::parsing::items;

    named!(pub krate -> Crate, do_parse!(
        attrs: many0!(inner_attr) >>
        items: items >>
        (Crate {
            shebang: None,
            attrs: attrs,
            items: items,
        })
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Crate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in self.attrs.inner() {
                attr.to_tokens(tokens);
            }
            for item in &self.items {
                item.to_tokens(tokens);
            }
        }
    }
}
<commit_msg>Parse shebang<commit_after>use super::*;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Crate {
    pub shebang: Option<String>,
    pub attrs: Vec<Attribute>,
    pub items: Vec<Item>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::inner_attr;
    use item::parsing::items;

    named!(pub krate -> Crate, do_parse!(
        shebang: option!(shebang) >>
        attrs: many0!(inner_attr) >>
        items: items >>
        (Crate {
            shebang: shebang,
            attrs: attrs,
            items: items,
        })
    ));

    named!(shebang -> String, do_parse!(
        tag!("#!") >>
        not!(peek!(tag!("["))) >>
        content: take_until!("\n") >>
        (format!("#!{}", content))
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Crate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if let Some(ref shebang) = self.shebang {
                tokens.append(&format!("{}\n", shebang));
            }
            for attr in self.attrs.inner() {
                attr.to_tokens(tokens);
            }
            for item in &self.items {
                item.to_tokens(tokens);
            }
        }
    }
}
<|endoftext|>