<commit_before>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::fmt;
use std::slice;

use ::Result;
use ::Error;

use octets;
use crypto;
use rand;
use stream;

const FORM_BIT: u8 = 0x80;
const KEY_PHASE_BIT: u8 = 0x40;
const DEMUX_BIT: u8 = 0x08;

const TYPE_MASK: u8 = 0x7f;

const MAX_CID_LEN: u8 = 18;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Type {
    Initial,
    Retry,
    Handshake,
    ZeroRTT,
    VersionNegotiation,
    Application,
}

pub fn has_long_header(b: u8) -> bool {
    b & FORM_BIT != 0
}

#[derive(Clone)]
pub struct Header {
    pub ty: Type,
    pub version: u32,
    pub flags: u8,
    pub dcid: Vec<u8>,
    pub scid: Vec<u8>,
    pub token: Option<Vec<u8>>,
}

impl Header {
    pub fn decode_long(buf: &mut [u8]) -> Result<Header> {
        let mut b = octets::Bytes::new(buf);
        Header::long_from_bytes(&mut b)
    }

    pub fn decode_short(buf: &mut [u8], dcil: usize) -> Result<Header> {
        let mut b = octets::Bytes::new(buf);
        Header::short_from_bytes(&mut b, dcil)
    }

    pub fn long_from_bytes(b: &mut octets::Bytes) -> Result<Header> {
        let first = b.get_u8()?;

        if !has_long_header(first) {
            return Err(Error::WrongForm);
        }

        let version = b.get_u32()?;

        let ty = if version == 0 {
            Type::VersionNegotiation
        } else {
            match first & TYPE_MASK {
                0x7f => Type::Initial,
                0x7e => Type::Retry,
                0x7d => Type::Handshake,
                0x7c => Type::ZeroRTT,
                _    => return Err(Error::UnknownPacket),
            }
        };

        let (dcil, scil) = match b.get_u8() {
            Ok(v) => {
                let mut dcil = v >> 4;
                let mut scil = v & 0xf;

                if dcil > MAX_CID_LEN || scil > MAX_CID_LEN {
                    return Err(Error::InvalidPacket);
                }

                if dcil > 0 {
                    dcil += 3;
                }

                if scil > 0 {
                    scil += 3;
                }

                (dcil, scil)
            },

            Err(_) => return Err(Error::BufferTooShort),
        };

        let dcid = b.get_bytes(dcil as usize)?.to_vec();
        let scid = b.get_bytes(scil as usize)?.to_vec();

        // End of invariants.

        let mut token: Option<Vec<u8>> = None;

        match ty {
            Type::Initial => {
                token = Some(b.get_bytes_with_varint_length()?.to_vec());
            },

            Type::Retry => {
                panic!("Retry not supported");
            },

            Type::VersionNegotiation => {
                panic!("Version negotiation not supported");
            },

            _ => (),
        };

        Ok(Header {
            ty,
            flags: first & FORM_BIT,
            version,
            dcid,
            scid,
            token,
        })
    }

    pub fn long_to_bytes(hdr: &Header, out: &mut octets::Bytes) -> Result<()> {
        let ty: u8 = match hdr.ty {
                Type::Initial   => 0x7f,
                Type::Retry     => 0x7e,
                Type::Handshake => 0x7d,
                Type::ZeroRTT   => 0x7c,
                // TODO: unify handling of version negotiation
                _               => return Err(Error::UnknownPacket),
        };

        let first = FORM_BIT | ty;

        out.put_u8(first)?;

        out.put_u32(hdr.version)?;

        let mut cil: u8 = 0;

        if hdr.dcid.len() > 0 {
            cil |= ((hdr.dcid.len() - 3) as u8) << 4;
        }

        if hdr.scid.len() > 0 {
            cil |= ((hdr.scid.len() - 3) as u8) & 0xf;
        }

        out.put_u8(cil)?;

        out.put_bytes(&hdr.dcid)?;
        out.put_bytes(&hdr.scid)?;

        // Only Initial packet have a token.
        if hdr.ty == Type::Initial {
            match hdr.token {
                Some(ref v) => {
                    out.put_bytes(v)?;
                },

                None => {
                    // No token, so lemgth = 0.
                    out.put_varint(0)?;
                }
            }
        }

        Ok(())
    }

    pub fn short_from_bytes(b: &mut octets::Bytes, dcil: usize) -> Result<Header> {
        let first = b.get_u8()?;

        if has_long_header(first) {
            return Err(Error::WrongForm);
        }

        let dcid = b.get_bytes(dcil)?;

        Ok(Header {
            ty: Type::Application,
            flags: first & FORM_BIT,
            version: 0,
            dcid: dcid.to_vec(),
            scid: Vec::new(),
            token: None,
        })
    }

    pub fn short_to_bytes(hdr: &Header, out: &mut octets::Bytes) -> Result<()> {
        let mut first = rand::rand_u8();

        // Unset form bit for short header.
        first &= !FORM_BIT;

        // TODO: support key update
        first &= !KEY_PHASE_BIT;

        // "The third bit (0x20) of octet 0 is set to 1."
        first |= 0x20;

        // "The fourth bit (0x10) of octet 0 is set to 1."
        first |= 0x10;

        // Clear Google QUIC demultiplexing bit
        first &= !DEMUX_BIT;

        out.put_u8(first)?;
        out.put_bytes(&hdr.dcid)?;

        Ok(())
    }
}

impl fmt::Debug for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.ty)?;

        if self.ty != Type::Application {
            write!(f, " vers={:x}", self.version)?;
        }

        let vec: Vec<String> = self.dcid.iter()
                                        .map(|b| format!("{:02x}", b))
                                        .collect();

        write!(f, " dcid={}", vec.join(""))?;

        if self.ty != Type::Application {
            let vec: Vec<String> = self.scid.iter()
                                            .map(|b| format!("{:02x}", b))
                                            .collect();

            write!(f, " scid={}", vec.join(""))?;
        }

        Ok(())
    }
}

pub fn pkt_num_len(pn: u64) -> Result<usize> {
    let len = if pn < 128 {
        1
    } else if pn < 16384 {
        2
    } else if pn < 1_073_741_824 {
        4
    } else {
        return Err(Error::InvalidPacket);
    };

    Ok(len)
}

pub fn decrypt_pkt_num(b: &mut octets::Bytes, aead: &crypto::Open)
                                                    -> Result<(u64,usize)> {
    let max_pn_len = if b.cap() < aead.nonce_len() + 4 + 4 {
        b.cap() - aead.nonce_len() - 4
    } else {
        4
    };

    let mut pn_and_sample = b.peek_bytes(max_pn_len + aead.nonce_len() + 4)?;

    let (mut ciphertext, sample) = pn_and_sample.split_at(max_pn_len).unwrap();

    let ciphertext = ciphertext.as_mut();

    // Decrypt first byte of pkt num into separate buffer to get length.
    let mut first: u8 = ciphertext[0];

    aead.xor_keystream(sample.as_ref(), slice::from_mut(&mut first))?;

    let len = if first >> 7 == 0 {
        1
    } else {
        // Map most significant 2 bits to actual pkt num length.
        match first >> 6 {
            2 => 2,
            3 => 4,
            _ => return Err(Error::InvalidPacket),
        }
    };

    // Decrypt full pkt num in-place.
    aead.xor_keystream(sample.as_ref(), &mut ciphertext[..len])?;

    let mut plaintext = Vec::with_capacity(len);
    plaintext.extend_from_slice(&ciphertext[..len]);

    // Mask the 2 most significant bits to remove the encoded length.
    if len > 1 {
        plaintext[0] &= 0x3f;
    }

    let mut b = octets::Bytes::new(&mut plaintext);

    // Extract packet number corresponding to the decoded length.
    let out = match len {
        1 => u64::from(b.get_u8()?),
        2 => u64::from(b.get_u16()?),
        4 => u64::from(b.get_u32()?),
        _ => return Err(Error::InvalidPacket),
    };

    // TODO: implement packet number truncation
    Ok((out as u64, len))
}

pub fn encode_pkt_num(pn: u64, b: &mut octets::Bytes) -> Result<()> {
    let len = pkt_num_len(pn)?;

    match len {
        1 => {
            let mut buf = b.put_u8(pn as u8)?;
            buf[0] &= !0x80;
        },

        2 => {
            let mut buf = b.put_u16(pn as u16)?;
            buf[0] &= !0xc0;
            buf[0] |= 0x80;
        },

        4 => {
            let mut buf = b.put_u32(pn as u32)?;
            buf[0] |= 0xc0;
        },

        _ => return Err(Error::InvalidPacket),
    };

    Ok(())
}

pub fn decrypt_pkt(payload: &mut [u8], pn: u64, ad: &[u8], aead: &crypto::Open)
                                                            -> Result<usize> {
    aead.open_with_u64_counter(pn, ad, payload)
}

pub fn encrypt_pkt(payload: &mut [u8], pn: u64, ad: &[u8], aead: &crypto::Seal)
                                                            -> Result<usize> {
    aead.seal_with_u64_counter(pn, ad, payload)
}

pub fn negotiate_version(hdr: &Header, out: &mut [u8]) -> Result<usize> {
    let mut b = octets::Bytes::new(out);

    let first = rand::rand_u8() | FORM_BIT;

    b.put_u8(first)?;
    b.put_u32(0)?;

    // Invert client's scid and dcid.
    let mut cil: u8 = 0;
    if hdr.scid.len() > 0 {
        cil |= ((hdr.scid.len() - 3) as u8) << 4;
    }

    if hdr.dcid.len() > 0 {
        cil |= ((hdr.dcid.len() - 3) as u8) & 0xf;
    }

    b.put_u8(cil)?;
    b.put_bytes(&hdr.scid)?;
    b.put_bytes(&hdr.dcid)?;
    b.put_u32(::VERSION_DRAFT15)?;

    Ok(b.off())
}

pub struct PktNumSpace {
    pub pkt_type: Type,

    pub expected_pkt_num: u64,

    pub last_pkt_num: u64,

    pub need_ack: Vec<u64>,

    pub crypto_level: crypto::Level,

    pub crypto_open: Option<crypto::Open>,
    pub crypto_seal: Option<crypto::Seal>,

    pub crypto_stream: stream::Stream,
}

impl PktNumSpace {
    pub fn new(ty: Type, crypto_level: crypto::Level) -> PktNumSpace {
        PktNumSpace {
            pkt_type: ty,

            expected_pkt_num: 0,

            last_pkt_num: 0,

            need_ack: Vec::new(),

            crypto_level,

            crypto_open: None,
            crypto_seal: None,

            crypto_stream: stream::Stream::new(),
        }
    }

    pub fn cipher(&self) -> crypto::Algorithm {
        match self.crypto_open {
            Some(ref v) => v.algorithm(),
            None => crypto::Algorithm::Null,
        }
    }

    pub fn overhead(&self) -> usize {
        self.crypto_seal.as_ref().unwrap().tag_len()
    }
}

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

    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn decrypt_initial() {
        decrypt_initial_helper("test_data/initial_ngtcp2.txt");
        decrypt_initial_helper("test_data/initial_quicly.txt");
    }

    fn decrypt_initial_helper(file_name: &'static str) {
        let mut file = File::open(file_name).unwrap();

        let mut buf = Vec::new();
        file.read_to_end(&mut buf).unwrap();

        let mut b = octets::Bytes::new(&mut buf);

        let hdr = Header::long_from_bytes(&mut b).unwrap();

        let payload_len = b.get_varint().unwrap() as usize;

        let (aead_open, _) =
            crypto::derive_initial_key_material(&hdr.dcid, true).unwrap();

        let (pn, pn_len) = decrypt_pkt_num(&mut b, &aead_open).unwrap();
        b.skip(pn_len).unwrap();

        let payload_offset = b.off();

        let (header, mut payload) = b.split_at(payload_offset).unwrap();

        decrypt_pkt(payload.slice(payload_len - pn_len).unwrap(),
                    pn, header.as_ref(), &aead_open).unwrap();
    }
}
<commit_msg>packet: simplify connection ID formatting in Debug<commit_after>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::fmt;
use std::slice;

use ::Result;
use ::Error;

use octets;
use crypto;
use rand;
use stream;

const FORM_BIT: u8 = 0x80;
const KEY_PHASE_BIT: u8 = 0x40;
const DEMUX_BIT: u8 = 0x08;

const TYPE_MASK: u8 = 0x7f;

const MAX_CID_LEN: u8 = 18;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Type {
    Initial,
    Retry,
    Handshake,
    ZeroRTT,
    VersionNegotiation,
    Application,
}

pub fn has_long_header(b: u8) -> bool {
    b & FORM_BIT != 0
}

#[derive(Clone)]
pub struct Header {
    pub ty: Type,
    pub version: u32,
    pub flags: u8,
    pub dcid: Vec<u8>,
    pub scid: Vec<u8>,
    pub token: Option<Vec<u8>>,
}

impl Header {
    pub fn decode_long(buf: &mut [u8]) -> Result<Header> {
        let mut b = octets::Bytes::new(buf);
        Header::long_from_bytes(&mut b)
    }

    pub fn decode_short(buf: &mut [u8], dcil: usize) -> Result<Header> {
        let mut b = octets::Bytes::new(buf);
        Header::short_from_bytes(&mut b, dcil)
    }

    pub fn long_from_bytes(b: &mut octets::Bytes) -> Result<Header> {
        let first = b.get_u8()?;

        if !has_long_header(first) {
            return Err(Error::WrongForm);
        }

        let version = b.get_u32()?;

        let ty = if version == 0 {
            Type::VersionNegotiation
        } else {
            match first & TYPE_MASK {
                0x7f => Type::Initial,
                0x7e => Type::Retry,
                0x7d => Type::Handshake,
                0x7c => Type::ZeroRTT,
                _    => return Err(Error::UnknownPacket),
            }
        };

        let (dcil, scil) = match b.get_u8() {
            Ok(v) => {
                let mut dcil = v >> 4;
                let mut scil = v & 0xf;

                if dcil > MAX_CID_LEN || scil > MAX_CID_LEN {
                    return Err(Error::InvalidPacket);
                }

                if dcil > 0 {
                    dcil += 3;
                }

                if scil > 0 {
                    scil += 3;
                }

                (dcil, scil)
            },

            Err(_) => return Err(Error::BufferTooShort),
        };

        let dcid = b.get_bytes(dcil as usize)?.to_vec();
        let scid = b.get_bytes(scil as usize)?.to_vec();

        // End of invariants.

        let mut token: Option<Vec<u8>> = None;

        match ty {
            Type::Initial => {
                token = Some(b.get_bytes_with_varint_length()?.to_vec());
            },

            Type::Retry => {
                panic!("Retry not supported");
            },

            Type::VersionNegotiation => {
                panic!("Version negotiation not supported");
            },

            _ => (),
        };

        Ok(Header {
            ty,
            flags: first & FORM_BIT,
            version,
            dcid,
            scid,
            token,
        })
    }

    pub fn long_to_bytes(hdr: &Header, out: &mut octets::Bytes) -> Result<()> {
        let ty: u8 = match hdr.ty {
                Type::Initial   => 0x7f,
                Type::Retry     => 0x7e,
                Type::Handshake => 0x7d,
                Type::ZeroRTT   => 0x7c,
                // TODO: unify handling of version negotiation
                _               => return Err(Error::UnknownPacket),
        };

        let first = FORM_BIT | ty;

        out.put_u8(first)?;

        out.put_u32(hdr.version)?;

        let mut cil: u8 = 0;

        if hdr.dcid.len() > 0 {
            cil |= ((hdr.dcid.len() - 3) as u8) << 4;
        }

        if hdr.scid.len() > 0 {
            cil |= ((hdr.scid.len() - 3) as u8) & 0xf;
        }

        out.put_u8(cil)?;

        out.put_bytes(&hdr.dcid)?;
        out.put_bytes(&hdr.scid)?;

        // Only Initial packet have a token.
        if hdr.ty == Type::Initial {
            match hdr.token {
                Some(ref v) => {
                    out.put_bytes(v)?;
                },

                None => {
                    // No token, so lemgth = 0.
                    out.put_varint(0)?;
                }
            }
        }

        Ok(())
    }

    pub fn short_from_bytes(b: &mut octets::Bytes, dcil: usize) -> Result<Header> {
        let first = b.get_u8()?;

        if has_long_header(first) {
            return Err(Error::WrongForm);
        }

        let dcid = b.get_bytes(dcil)?;

        Ok(Header {
            ty: Type::Application,
            flags: first & FORM_BIT,
            version: 0,
            dcid: dcid.to_vec(),
            scid: Vec::new(),
            token: None,
        })
    }

    pub fn short_to_bytes(hdr: &Header, out: &mut octets::Bytes) -> Result<()> {
        let mut first = rand::rand_u8();

        // Unset form bit for short header.
        first &= !FORM_BIT;

        // TODO: support key update
        first &= !KEY_PHASE_BIT;

        // "The third bit (0x20) of octet 0 is set to 1."
        first |= 0x20;

        // "The fourth bit (0x10) of octet 0 is set to 1."
        first |= 0x10;

        // Clear Google QUIC demultiplexing bit
        first &= !DEMUX_BIT;

        out.put_u8(first)?;
        out.put_bytes(&hdr.dcid)?;

        Ok(())
    }
}

impl fmt::Debug for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.ty)?;

        if self.ty != Type::Application {
            write!(f, " vers={:x}", self.version)?;
        }

        write!(f, " dcid=")?;
        for b in &self.dcid {
            write!(f, "{:02x}", b)?;
        }

        if self.ty != Type::Application {
            write!(f, " scid=")?;
            for b in &self.scid {
                write!(f, "{:02x}", b)?;
            }
        }

        Ok(())
    }
}

pub fn pkt_num_len(pn: u64) -> Result<usize> {
    let len = if pn < 128 {
        1
    } else if pn < 16384 {
        2
    } else if pn < 1_073_741_824 {
        4
    } else {
        return Err(Error::InvalidPacket);
    };

    Ok(len)
}

pub fn decrypt_pkt_num(b: &mut octets::Bytes, aead: &crypto::Open)
                                                    -> Result<(u64,usize)> {
    let max_pn_len = if b.cap() < aead.nonce_len() + 4 + 4 {
        b.cap() - aead.nonce_len() - 4
    } else {
        4
    };

    let mut pn_and_sample = b.peek_bytes(max_pn_len + aead.nonce_len() + 4)?;

    let (mut ciphertext, sample) = pn_and_sample.split_at(max_pn_len).unwrap();

    let ciphertext = ciphertext.as_mut();

    // Decrypt first byte of pkt num into separate buffer to get length.
    let mut first: u8 = ciphertext[0];

    aead.xor_keystream(sample.as_ref(), slice::from_mut(&mut first))?;

    let len = if first >> 7 == 0 {
        1
    } else {
        // Map most significant 2 bits to actual pkt num length.
        match first >> 6 {
            2 => 2,
            3 => 4,
            _ => return Err(Error::InvalidPacket),
        }
    };

    // Decrypt full pkt num in-place.
    aead.xor_keystream(sample.as_ref(), &mut ciphertext[..len])?;

    let mut plaintext = Vec::with_capacity(len);
    plaintext.extend_from_slice(&ciphertext[..len]);

    // Mask the 2 most significant bits to remove the encoded length.
    if len > 1 {
        plaintext[0] &= 0x3f;
    }

    let mut b = octets::Bytes::new(&mut plaintext);

    // Extract packet number corresponding to the decoded length.
    let out = match len {
        1 => u64::from(b.get_u8()?),
        2 => u64::from(b.get_u16()?),
        4 => u64::from(b.get_u32()?),
        _ => return Err(Error::InvalidPacket),
    };

    // TODO: implement packet number truncation
    Ok((out as u64, len))
}

pub fn encode_pkt_num(pn: u64, b: &mut octets::Bytes) -> Result<()> {
    let len = pkt_num_len(pn)?;

    match len {
        1 => {
            let mut buf = b.put_u8(pn as u8)?;
            buf[0] &= !0x80;
        },

        2 => {
            let mut buf = b.put_u16(pn as u16)?;
            buf[0] &= !0xc0;
            buf[0] |= 0x80;
        },

        4 => {
            let mut buf = b.put_u32(pn as u32)?;
            buf[0] |= 0xc0;
        },

        _ => return Err(Error::InvalidPacket),
    };

    Ok(())
}

pub fn decrypt_pkt(payload: &mut [u8], pn: u64, ad: &[u8], aead: &crypto::Open)
                                                            -> Result<usize> {
    aead.open_with_u64_counter(pn, ad, payload)
}

pub fn encrypt_pkt(payload: &mut [u8], pn: u64, ad: &[u8], aead: &crypto::Seal)
                                                            -> Result<usize> {
    aead.seal_with_u64_counter(pn, ad, payload)
}

pub fn negotiate_version(hdr: &Header, out: &mut [u8]) -> Result<usize> {
    let mut b = octets::Bytes::new(out);

    let first = rand::rand_u8() | FORM_BIT;

    b.put_u8(first)?;
    b.put_u32(0)?;

    // Invert client's scid and dcid.
    let mut cil: u8 = 0;
    if hdr.scid.len() > 0 {
        cil |= ((hdr.scid.len() - 3) as u8) << 4;
    }

    if hdr.dcid.len() > 0 {
        cil |= ((hdr.dcid.len() - 3) as u8) & 0xf;
    }

    b.put_u8(cil)?;
    b.put_bytes(&hdr.scid)?;
    b.put_bytes(&hdr.dcid)?;
    b.put_u32(::VERSION_DRAFT15)?;

    Ok(b.off())
}

pub struct PktNumSpace {
    pub pkt_type: Type,

    pub expected_pkt_num: u64,

    pub last_pkt_num: u64,

    pub need_ack: Vec<u64>,

    pub crypto_level: crypto::Level,

    pub crypto_open: Option<crypto::Open>,
    pub crypto_seal: Option<crypto::Seal>,

    pub crypto_stream: stream::Stream,
}

impl PktNumSpace {
    pub fn new(ty: Type, crypto_level: crypto::Level) -> PktNumSpace {
        PktNumSpace {
            pkt_type: ty,

            expected_pkt_num: 0,

            last_pkt_num: 0,

            need_ack: Vec::new(),

            crypto_level,

            crypto_open: None,
            crypto_seal: None,

            crypto_stream: stream::Stream::new(),
        }
    }

    pub fn cipher(&self) -> crypto::Algorithm {
        match self.crypto_open {
            Some(ref v) => v.algorithm(),
            None => crypto::Algorithm::Null,
        }
    }

    pub fn overhead(&self) -> usize {
        self.crypto_seal.as_ref().unwrap().tag_len()
    }
}

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

    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn decrypt_initial() {
        decrypt_initial_helper("test_data/initial_ngtcp2.txt");
        decrypt_initial_helper("test_data/initial_quicly.txt");
    }

    fn decrypt_initial_helper(file_name: &'static str) {
        let mut file = File::open(file_name).unwrap();

        let mut buf = Vec::new();
        file.read_to_end(&mut buf).unwrap();

        let mut b = octets::Bytes::new(&mut buf);

        let hdr = Header::long_from_bytes(&mut b).unwrap();

        let payload_len = b.get_varint().unwrap() as usize;

        let (aead_open, _) =
            crypto::derive_initial_key_material(&hdr.dcid, true).unwrap();

        let (pn, pn_len) = decrypt_pkt_num(&mut b, &aead_open).unwrap();
        b.skip(pn_len).unwrap();

        let payload_offset = b.off();

        let (header, mut payload) = b.split_at(payload_offset).unwrap();

        decrypt_pkt(payload.slice(payload_len - pn_len).unwrap(),
                    pn, header.as_ref(), &aead_open).unwrap();
    }
}
<|endoftext|>


<commit_before>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser` module cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    // read_ip_addr is not used.
    //fn read_ip_addr(&mut self) -> Option<IpAddr> {
    //    let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr().map(IpAddr::V4);
    //    let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr().map(IpAddr::V6);
    //    self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
    //}

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len)
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len)
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<commit_msg>Removing TODO item and commented code<commit_after>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser` module cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len)
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len)
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<|endoftext|>


<commit_before>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser` module cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len).unwrap()
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len).unwrap()
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<commit_msg>fix warning about missing 'dyn' keyword<commit_after>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser` module cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len).unwrap()
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len).unwrap()
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<|endoftext|>


<commit_before>use oak_runtime::parse_state::*;
use oak_runtime::parse_state::ParseResult::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::Stmt;

grammar! bailey {
    use ast::Ident;
    use ast::Literal;
    use ast::Expr;
    use ast::Stmt;
    use ast::BinOp;
    use ast::Decl;
    use ast::MethodDecl;
    use ast::ClassDecl;
    use ast::Block;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = newlines (stmt_or_decl terminator)*

    stmt_or_decl
        = stmt
        / decl > decl_to_stmt

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw ident class_body > class_decl

    class_body
        = lbracket (newlines method_decl)* rbracket

    method_decl
        = def_kw ident lparen param_list rparen block > method_decl

    block
        = newlines lbracket stmt_list rbracket spacing > block

    stmt_list
        = empty_stmt_list
        / stmt (terminator stmt)* > stmt_list

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr > expr_to_stmt

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = newlines ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = var bind_op expr > assign_stmt

    expr
        = newlines cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal > lit_to_exp
        / constant
        / var
        / array
        / map
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_param_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list
    empty_stmt_list = &rbracket > empty_stmt_list
    empty_param_list = &rbracket > empty_param_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    var = !digit !keyword ident_char+ spacing > var
    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit

    array_elem = expr > array_elem
    array = lsqbracket array_elem (comma array_elem)* rsqbracket > array

    map_entry =  (expr colon expr) > map_entry
    map = lbracket map_entry (comma map_entry)* rbracket > map

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \r\t"]
    spacing = spacing_char* -> ()
    newline = "\n" spacing -> ()
    semicolon = ";" spacing -> ()
    newlines = newline* spacing -> ()
    terminator = (newline / semicolon) newlines -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" newlines -> ()
    rparen = newlines ")" -> ()
    lbracket = "{" newlines -> ()
    rbracket = newlines "}" -> ()
    lsqbracket = "[" newlines
    rsqbracket = newlines "]"
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn decl_to_stmt(decl: Decl) -> Stmt {
        Stmt::Decl(Box::new(decl))
    }

    fn expr_to_stmt(expr: Expr) -> Stmt {
        Stmt::Expr(Box::new(expr))
    }

    fn lit_to_exp(literal: Literal) -> Expr {
        Expr::Literal(Box::new(literal))
    }

    fn int_lit(raw_text: Vec<char>) -> Literal {
        Literal::Integer(to_number(raw_text))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> Literal {
        integer.push('.');
        Literal::Float(to_float(combine(integer, fractional)))
    }

    fn string_lit(raw_text: Vec<char>) -> Literal {
        Literal::Str(to_string(raw_text))
    }

    fn array(first: Box<Expr>, rest: Vec<Box<Expr>>) -> Expr {
        Expr::Array(combine_one_with_many(first, rest))
    }

    fn array_elem(expr: Expr) -> Box<Expr> {
        Box::new(expr)
    }

    fn map(first: (Box<Expr>, Box<Expr>), rest: Vec<(Box<Expr>, Box<Expr>)>) -> Expr {
        Expr::Map(combine_one_with_many(first, rest))
    }

    fn map_entry(key: Expr, val: Expr) -> (Box<Expr>, Box<Expr>) {
        (Box::new(key), Box::new(val))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> Expr {
        Expr::Const(Ident(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> Ident {
        Ident(to_string(raw_text))
    }

    fn var(raw_text: Vec<char>) -> Expr {
        Expr::Var(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: Ident, args: Vec<Expr>) -> Expr {
        Expr::Message(None, func, args)
    }

    fn method_call(recv: Expr, call: Vec<(Ident, Vec<Expr>)>) -> Expr {
        call.into_iter().fold(recv, { |accu, (method, args)|
            Expr::Message(Some(Box::new(accu)), method, args)
        })
    }

    fn assign_stmt(var: Expr, expr: Expr) -> Stmt {
        Stmt::Assign(Box::new(var), Box::new(expr))
    }

    fn class_decl(class: Ident, methods: Vec<Decl>) -> Decl {
        Decl::ClassDecl(Box::new(ClassDecl(class, methods)))
    }

    fn method_decl(meth: Ident, params: Vec<Ident>, block: Block) -> Decl {
        Decl::MethodDecl(Box::new(MethodDecl(meth, params, Box::new(block))))
    }

    fn block(stmts: Vec<Stmt>) -> Block {
        Block { stmts: stmts }
    }

    fn program(first: Stmt, mut rest: Vec<Stmt>) -> Vec<Stmt> {
        combine_one_with_many(first, rest)
    }

    fn if_stmt(cond: Expr, true_blk: Block, false_blk: Option<Block>) -> Stmt {
        match false_blk {
            Some(blk) => Stmt::If(Box::new(cond), Box::new(true_blk), Some(Box::new(blk))),
            None => Stmt::If(Box::new(cond), Box::new(true_blk), None)
        }
    }

    fn while_stmt(cond: Expr, blk: Block) -> Stmt {
        Stmt::While(Box::new(cond), Box::new(blk))
    }

    fn arg_list(first: Expr, mut rest: Vec<Expr>) -> Vec<Expr> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: Ident, mut rest: Vec<Ident>) -> Vec<Ident> {
        combine_one_with_many(first, rest)
    }

    fn empty_param_list() -> Vec<Ident> {
        vec![]
    }

    fn stmt_list(first: Stmt, mut rest: Vec<Stmt>) -> Vec<Stmt> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<Expr> {
        vec![]
    }

    fn empty_stmt_list() -> Vec<Stmt> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> i64 {
        i64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: Expr, rest: Vec<(BinOp, Expr)>) -> Expr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Expr::Binary(op, Box::new(accu), Box::new(expr)))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<Stmt>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<Stmt>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<Stmt>, String> {
        let state = bailey::parse_program(code.into_state());

        match state.into_result() {
            Success(data) => Ok(data.clone()),
            Partial(data, expectation) => {
                Err(format!("Partial match: {:?} because: {:?}", data, expectation))
            }
            Failure(expectation) => {
                Err(format!("Error: {:?}", expectation))
            }
        }
    }
}

<commit_msg>Fixed empty parameter list.<commit_after>use oak_runtime::parse_state::*;
use oak_runtime::parse_state::ParseResult::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::Stmt;

grammar! bailey {
    use ast::Ident;
    use ast::Literal;
    use ast::Expr;
    use ast::Stmt;
    use ast::BinOp;
    use ast::Decl;
    use ast::MethodDecl;
    use ast::ClassDecl;
    use ast::Block;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = newlines (stmt_or_decl terminator)*

    stmt_or_decl
        = stmt
        / decl > decl_to_stmt

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw ident class_body > class_decl

    class_body
        = lbracket (newlines method_decl)* rbracket

    method_decl
        = def_kw ident lparen param_list rparen block > method_decl

    block
        = newlines lbracket stmt_list rbracket spacing > block

    stmt_list
        = empty_stmt_list
        / stmt (terminator stmt)* > stmt_list

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr > expr_to_stmt

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = newlines ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = var bind_op expr > assign_stmt

    expr
        = newlines cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal > lit_to_exp
        / constant
        / var
        / array
        / map
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_param_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list
    empty_param_list = &rparen > empty_param_list
    empty_stmt_list = &rbracket > empty_stmt_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    var = !digit !keyword ident_char+ spacing > var
    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit

    array_elem = expr > array_elem
    array = lsqbracket array_elem (comma array_elem)* rsqbracket > array

    map_entry =  (expr colon expr) > map_entry
    map = lbracket map_entry (comma map_entry)* rbracket > map

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \r\t"]
    spacing = spacing_char* -> ()
    newline = "\n" spacing -> ()
    semicolon = ";" spacing -> ()
    newlines = newline* spacing -> ()
    terminator = (newline / semicolon) newlines -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" newlines -> ()
    rparen = newlines ")" -> ()
    lbracket = "{" newlines -> ()
    rbracket = newlines "}" -> ()
    lsqbracket = "[" newlines
    rsqbracket = newlines "]"
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn decl_to_stmt(decl: Decl) -> Stmt {
        Stmt::Decl(Box::new(decl))
    }

    fn expr_to_stmt(expr: Expr) -> Stmt {
        Stmt::Expr(Box::new(expr))
    }

    fn lit_to_exp(literal: Literal) -> Expr {
        Expr::Literal(Box::new(literal))
    }

    fn int_lit(raw_text: Vec<char>) -> Literal {
        Literal::Integer(to_number(raw_text))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> Literal {
        integer.push('.');
        Literal::Float(to_float(combine(integer, fractional)))
    }

    fn string_lit(raw_text: Vec<char>) -> Literal {
        Literal::Str(to_string(raw_text))
    }

    fn array(first: Box<Expr>, rest: Vec<Box<Expr>>) -> Expr {
        Expr::Array(combine_one_with_many(first, rest))
    }

    fn array_elem(expr: Expr) -> Box<Expr> {
        Box::new(expr)
    }

    fn map(first: (Box<Expr>, Box<Expr>), rest: Vec<(Box<Expr>, Box<Expr>)>) -> Expr {
        Expr::Map(combine_one_with_many(first, rest))
    }

    fn map_entry(key: Expr, val: Expr) -> (Box<Expr>, Box<Expr>) {
        (Box::new(key), Box::new(val))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> Expr {
        Expr::Const(Ident(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> Ident {
        Ident(to_string(raw_text))
    }

    fn var(raw_text: Vec<char>) -> Expr {
        Expr::Var(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: Ident, args: Vec<Expr>) -> Expr {
        Expr::Message(None, func, args)
    }

    fn method_call(recv: Expr, call: Vec<(Ident, Vec<Expr>)>) -> Expr {
        call.into_iter().fold(recv, { |accu, (method, args)|
            Expr::Message(Some(Box::new(accu)), method, args)
        })
    }

    fn assign_stmt(var: Expr, expr: Expr) -> Stmt {
        Stmt::Assign(Box::new(var), Box::new(expr))
    }

    fn class_decl(class: Ident, methods: Vec<Decl>) -> Decl {
        Decl::ClassDecl(Box::new(ClassDecl(class, methods)))
    }

    fn method_decl(meth: Ident, params: Vec<Ident>, block: Block) -> Decl {
        Decl::MethodDecl(Box::new(MethodDecl(meth, params, Box::new(block))))
    }

    fn block(stmts: Vec<Stmt>) -> Block {
        Block { stmts: stmts }
    }

    fn program(first: Stmt, mut rest: Vec<Stmt>) -> Vec<Stmt> {
        combine_one_with_many(first, rest)
    }

    fn if_stmt(cond: Expr, true_blk: Block, false_blk: Option<Block>) -> Stmt {
        match false_blk {
            Some(blk) => Stmt::If(Box::new(cond), Box::new(true_blk), Some(Box::new(blk))),
            None => Stmt::If(Box::new(cond), Box::new(true_blk), None)
        }
    }

    fn while_stmt(cond: Expr, blk: Block) -> Stmt {
        Stmt::While(Box::new(cond), Box::new(blk))
    }

    fn arg_list(first: Expr, mut rest: Vec<Expr>) -> Vec<Expr> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: Ident, mut rest: Vec<Ident>) -> Vec<Ident> {
        combine_one_with_many(first, rest)
    }

    fn empty_param_list() -> Vec<Ident> {
        vec![]
    }

    fn stmt_list(first: Stmt, mut rest: Vec<Stmt>) -> Vec<Stmt> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<Expr> {
        vec![]
    }

    fn empty_stmt_list() -> Vec<Stmt> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> i64 {
        i64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: Expr, rest: Vec<(BinOp, Expr)>) -> Expr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Expr::Binary(op, Box::new(accu), Box::new(expr)))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<Stmt>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<Stmt>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<Stmt>, String> {
        let state = bailey::parse_program(code.into_state());

        match state.into_result() {
            Success(data) => Ok(data.clone()),
            Partial(data, expectation) => {
                Err(format!("Partial match: {:?} because: {:?}", data, expectation))
            }
            Failure(expectation) => {
                Err(format!("Error: {:?}", expectation))
            }
        }
    }
}

<|endoftext|>


<commit_before>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args_list = pairs
                                .next()
                                .unwrap()
                                .into_inner()
                                .into_iter()
                                .map(|r| Box::new(format!("{}", r.into_span().as_str())))
                                .collect();

            let body = Box::new(
                            parse_expression(pairs.next().unwrap()));

            Expression::FuncLiteral(name, args_list, body)
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args = pairs
                        .into_iter()
                        .map(|r| Box::new(parse_expression(r)))
                        .collect();

            Expression::FuncCall(name, args)
        }

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(format!("{}", input.into_span().as_str())
            ),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just convert the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: &str) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::main, input) {
        Ok(mut pair) => Ok(parse_expression(
            pair.nth(0).unwrap().into_inner().nth(0).unwrap(),
        )),

        Err(e) => Err(format!("{}", e)),
    }
}
<commit_msg>Remove format! and replace with to_string<commit_after>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args_list = pairs
                                .next()
                                .unwrap()
                                .into_inner()
                                .into_iter()
                                .map(|r| Box::new(r.into_span().as_str().to_string()))
                                .collect();

            let body = Box::new(
                            parse_expression(pairs.next().unwrap()));

            Expression::FuncLiteral(name, args_list, body)
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args = pairs
                        .into_iter()
                        .map(|r| Box::new(parse_expression(r)))
                        .collect();

            Expression::FuncCall(name, args)
        }

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(input.into_span().as_str().to_string()),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just convert the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: &str) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::main, input) {
        Ok(mut pair) => Ok(parse_expression(
            pair.nth(0).unwrap().into_inner().nth(0).unwrap(),
        )),

        Err(e) => Err(format!("{}", e)),
    }
}
<|endoftext|>