<commit_before>
extern crate regex;

use std::collections::VecDeque;

use std::io;
use std::io::prelude::*;

use regex::Regex;

#[derive(Debug)]
struct Range((usize, usize), (usize, usize));

#[derive(Debug)]
enum OperationType {
    On,
    Off,
    Toggle,
}

#[derive(Debug)]
struct Operation {
    op_type: OperationType,
    range: Range,
}

fn main() {

    let mut oper_list = VecDeque::new();

    {
        let re = Regex::new("^(turn on|turn off|toggle) ([0-9]+),([0-9]+) through \
                             ([0-9]+),([0-9]+)$")
                     .unwrap();
        let stdin = io::stdin();

        for uline in stdin.lock().lines() {
            let line = &uline.unwrap();

            let capture = re.captures(line).unwrap();

            let start_point = (capture.at(2).unwrap().parse::<usize>().unwrap(),
                               capture.at(3).unwrap().parse::<usize>().unwrap());

            let end_point = (capture.at(4).unwrap().parse::<usize>().unwrap(),
                             capture.at(5).unwrap().parse::<usize>().unwrap());

            let op;
            let op_str = capture.at(1).unwrap();
            let op_range = Range(start_point, end_point);

            match op_str {
                "turn on" => {
                    op = Operation {
                        op_type: OperationType::On,
                        range: op_range,
                    }
                }
                "turn off" => {
                    op = Operation {
                        op_type: OperationType::Off,
                        range: op_range,
                    }
                }
                "toggle" => {
                    op = Operation {
                        op_type: OperationType::Toggle,
                        range: op_range,
                    }
                }
                _ => panic!("Unknown operation: {:?}", op_str),
            }

            oper_list.push_back(op);
        }
    }

    let mut light_matrix = [[false; 1000]; 1000];

    for oper in oper_list.iter() {
        println!("{:?}", oper);

        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => light_matrix[x][y] = true,
                    OperationType::Off => light_matrix[x][y] = false,
                    OperationType::Toggle => light_matrix[x][y] = !light_matrix[x][y],
                }
            }
        }
    }

    let sum = light_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            if light_state {
                acc + 1
            } else {
                acc
            }
        })
    });

    print!("Number of light lit after all operations: {}", sum);
}
<commit_msg>Second part of day 6. Brightness calculation.<commit_after>
extern crate regex;

use std::collections::VecDeque;

use std::io;
use std::io::prelude::*;

use regex::Regex;

#[derive(Debug)]
struct Range((usize, usize), (usize, usize));

#[derive(Debug)]
enum OperationType {
    On,
    Off,
    Toggle,
}

#[derive(Debug)]
struct Operation {
    op_type: OperationType,
    range: Range,
}

fn main() {

    let mut oper_list = VecDeque::new();

    {
        let re = Regex::new("^(turn on|turn off|toggle) ([0-9]+),([0-9]+) through \
                             ([0-9]+),([0-9]+)$")
                     .unwrap();
        let stdin = io::stdin();

        for uline in stdin.lock().lines() {
            let line = &uline.unwrap();

            let capture = re.captures(line).unwrap();

            let start_point = (capture.at(2).unwrap().parse::<usize>().unwrap(),
                               capture.at(3).unwrap().parse::<usize>().unwrap());

            let end_point = (capture.at(4).unwrap().parse::<usize>().unwrap(),
                             capture.at(5).unwrap().parse::<usize>().unwrap());

            let op;
            let op_str = capture.at(1).unwrap();
            let op_range = Range(start_point, end_point);

            match op_str {
                "turn on" => {
                    op = Operation {
                        op_type: OperationType::On,
                        range: op_range,
                    }
                }
                "turn off" => {
                    op = Operation {
                        op_type: OperationType::Off,
                        range: op_range,
                    }
                }
                "toggle" => {
                    op = Operation {
                        op_type: OperationType::Toggle,
                        range: op_range,
                    }
                }
                _ => panic!("Unknown operation: {:?}", op_str),
            }

            oper_list.push_back(op);
        }
    }

    let mut light_matrix = [[false; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => light_matrix[x][y] = true,
                    OperationType::Off => light_matrix[x][y] = false,
                    OperationType::Toggle => light_matrix[x][y] = !light_matrix[x][y],
                }
            }
        }
    }

    let sum = light_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            if light_state {
                acc + 1
            } else {
                acc
            }
        })
    });

    println!("Number of light lit after all operations: {}", sum);

    let mut brt_matrix = [[0 as u32; 1000]; 1000];

    for oper in oper_list.iter() {
        // + 1 because the ranges are inclusive
        for x in ((oper.range.0).0)..((oper.range.1).0 + 1) {

            for y in ((oper.range.0).1)..((oper.range.1).1 + 1) {

                match oper.op_type {
                    OperationType::On => brt_matrix[x][y] += 1,
                    OperationType::Off => if brt_matrix[x][y] != 0 { brt_matrix[x][y] -= 1 },
                    OperationType::Toggle => brt_matrix[x][y] += 2,
                }
            }
        }
    }

    let brt_sum = brt_matrix.iter().fold(0, |total_acc, &row| {
        total_acc +
        row.iter().fold(0, |acc, &light_state| {
            acc + light_state
        })
    });

    println!("Total brightness after all operations: {}", brt_sum);
}
<|endoftext|>


<commit_before>use core::mapped_file::MappedFile;
use core::mapped_file::FileHandle;

//
pub type Id = u64;
pub type Offset = u64;
pub type PageSize = usize;

//
#[derive(Debug)]
pub enum OpenMode {
    ReadOnly = 0,
    ReadWrite = 1,
}

/// The **Buffer** represents a linear array of bytes.

/// it can be in memory only or backed by an on disk file.

/// The editor will **Modes** use this api to read/modify the content
/// of the file at the byte level
#[derive(Debug)]
pub struct Buffer<'a> {
    pub id: Id,
    /// the name of the file where the data will be synced
    pub file_name: String,
    /// the current size of the buffer
    pub size: usize,
    /// the number of changes (since last save TODO)
    pub nr_changes: u64,
    mode: OpenMode,
    pub data: FileHandle<'a>,
}

impl<'a> Buffer<'a> {
    /// Creates a new `Buffer`.
    ///
    /// file_name param[in] path to the file we want to load in the buffer,
    /// use "/dev/null" to create empty buffer
    /// this function allocate a buffer
    /// if file_name is null the content will be stored in heap
    /// if file_name is non null the the content will be read from the file
    /// if document_name is null , file_name will be used to give a name to the buffer
    /// mode = 0 : read only , mode 1 : read_write
    /// the allocated_bid pointer will be filled on successfull open operation
    pub fn new(file_name: String, mode: OpenMode) -> Option<Buffer<'a>> {
        // TODO: check permission
        // TODO: check file's type => ignore directory (for now)
        println!("-- mapping file {}", file_name);

        let page_size = 4096 * 256 * 2;
        let file = match MappedFile::new(file_name.clone(), page_size) {
            Some(file) => file,
            None => {
                eprintln!("cannot map file '{}'", file_name);
                return None;
            }
        };

        let size = file.as_ref().borrow().size() as usize;

        println!("'{}' opened size '{}'", file_name, size);

        Some(Buffer {
            id: 0,
            file_name: file_name.clone(),
            mode,
            size,
            nr_changes: 0,
            data: file,
        })
    }

    /// not implemented: close a previously opened buffer see buffer_open
    pub fn close(&mut self) -> bool {
        unimplemented!();
        false
    }

    /// returns the name of the file associated to the buffer
    pub fn get_file_name(&self) -> String {
        self.file_name.clone()
    }

    /// change the on disk target file
    pub fn set_file_name(&mut self, name: String) -> bool {
        self.file_name = name;
        true
    }

    /// returns the number of bytes a given buffer contains
    pub fn size(&self) -> usize {
        self.size
    }

    /// returns the number of changes sine the last save

    ///     0  => the no change since last save

    ///     >0 => the number of changes since last save

    pub fn nr_changes(&self) -> u64 {
        self.nr_changes
    }

    /// copy the content of the buffer up to 'nr_bytes' into the data Vec
    /// the read bytes are appended to the data Vec
    /// return XXX on error (use ioresult)
    pub fn read(&self, offset: u64, nr_bytes: usize, mut data: &mut Vec<u8>) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::read(&mut it, nr_bytes, &mut data)
    }

    /// insert the 'data' Vec content in the buffer up to 'nr_bytes'
    /// return the number of written bytes (TODO: use io::Result)
    pub fn insert(&mut self, offset: u64, nr_bytes: usize, data: &[u8]) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::insert(&mut it, &data);

        self.size += nr_bytes;
        self.nr_changes += 1;

        nr_bytes
    }

    /// remove up to 'nr_bytes' from the buffer starting at offset
    /// if removed_data is provided will call self.read(offset, nr_bytes, data)
    /// before remove the bytes
    pub fn remove(
        &mut self,
        offset: u64,
        nr_bytes: usize,
        removed_data: Option<&mut Vec<u8>>,
    ) -> usize {
        let start_offset = ::std::cmp::min(offset as usize, self.size);
        let end_offset = ::std::cmp::min(start_offset + nr_bytes, self.size);
        let nr_bytes_removed = (end_offset - start_offset) as usize;

        // copy removed data
        if let Some(v) = removed_data {
            self.read(offset, nr_bytes_removed, v);
        }

        let mut it = MappedFile::iter_from(&self.data, start_offset as u64);
        MappedFile::remove(&mut it, nr_bytes_removed);

        self.size -= nr_bytes_removed;
        self.nr_changes += 1;

        nr_bytes_removed
    }

    /// can be used to know the number of blocks that compose the buffer,
    /// api to be used by indexer etc...
    pub fn nr_pages(&self) -> u64 {
        1
    }

    /*
    /// returns the position and size of a given page
    pub fn get_page_info(&self, page_index: u64) -> (Offset, PageSize) {
        // if page_index > 0 {
        //    (0, self.size)
        // } else {
        //    (0, self.size)
        // }
        (0, self.size)
    }
*/

    //
    // TODO: This is currently broken, because fd swapping is not implemented yet in mapped_file
    //
    //
    pub fn sync_to_disk(&self, tmp_file_name: &str) -> ::std::io::Result<()> {
        use std::fs;
        use std::fs::File;
        use std::io::Write;

        let mut f = File::create(&tmp_file_name)?;

        let mut offset: u64 = 0;
        while offset != self.size as u64 {
            let nr_bytes = 4096 * 32;
            let mut data = Vec::with_capacity(nr_bytes);
            let read_size = self.read(offset, nr_bytes, &mut data);
            f.write(&data)?;
            offset += read_size as u64;
        }
        f.sync_all()?;
        fs::rename(&tmp_file_name, &self.file_name)?;
        Ok(())
    }
}

#[test]
fn test_buffer() {
    let mut bb = Buffer::new("/dev/null".to_owned(), OpenMode::ReadWrite).unwrap();

    let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    bb.insert(0, 10, &data);
    let mut rdata = Vec::new();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    let data = vec![0, 1, 2, 6, 7, 8, 9];
    let rm_expect = vec![3, 4, 5];

    let mut rm = vec![];
    let n = bb.remove(3, 3, Some(&mut rm));
    assert_eq!(n, 3);
    assert_eq!(rm, rm_expect);

    rdata.clear();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);

    println!("rm {:?}", rm);
    println!("rm_expect {:?}", rm_expect);
}
<commit_msg>remove warning<commit_after>use core::mapped_file::MappedFile;
use core::mapped_file::FileHandle;

//
pub type Id = u64;
pub type Offset = u64;
pub type PageSize = usize;

//
#[derive(Debug)]
pub enum OpenMode {
    ReadOnly = 0,
    ReadWrite = 1,
}

/// The **Buffer** represents a linear array of bytes.

/// it can be in memory only or backed by an on disk file.

/// The editor will **Modes** use this api to read/modify the content
/// of the file at the byte level
#[derive(Debug)]
pub struct Buffer<'a> {
    pub id: Id,
    /// the name of the file where the data will be synced
    pub file_name: String,
    /// the current size of the buffer
    pub size: usize,
    /// the number of changes (since last save TODO)
    pub nr_changes: u64,
    mode: OpenMode,
    pub data: FileHandle<'a>,
}

impl<'a> Buffer<'a> {
    /// Creates a new `Buffer`.
    ///
    /// file_name param[in] path to the file we want to load in the buffer,
    /// use "/dev/null" to create empty buffer
    /// this function allocate a buffer
    /// if file_name is null the content will be stored in heap
    /// if file_name is non null the the content will be read from the file
    /// if document_name is null , file_name will be used to give a name to the buffer
    /// mode = 0 : read only , mode 1 : read_write
    /// the allocated_bid pointer will be filled on successfull open operation
    pub fn new(file_name: String, mode: OpenMode) -> Option<Buffer<'a>> {
        // TODO: check permission
        // TODO: check file's type => ignore directory (for now)
        println!("-- mapping file {}", file_name);

        let page_size = 4096 * 256 * 2;
        let file = match MappedFile::new(file_name.clone(), page_size) {
            Some(file) => file,
            None => {
                eprintln!("cannot map file '{}'", file_name);
                return None;
            }
        };

        let size = file.as_ref().borrow().size() as usize;

        println!("'{}' opened size '{}'", file_name, size);

        Some(Buffer {
            id: 0,
            file_name: file_name.clone(),
            mode,
            size,
            nr_changes: 0,
            data: file,
        })
    }

    /// not implemented: close a previously opened buffer see buffer_open
    pub fn close(&mut self) -> bool {
        unimplemented!();
        // false
    }

    /// returns the name of the file associated to the buffer
    pub fn get_file_name(&self) -> String {
        self.file_name.clone()
    }

    /// change the on disk target file
    pub fn set_file_name(&mut self, name: String) -> bool {
        self.file_name = name;
        true
    }

    /// returns the number of bytes a given buffer contains
    pub fn size(&self) -> usize {
        self.size
    }

    /// returns the number of changes sine the last save

    ///     0  => the no change since last save

    ///     >0 => the number of changes since last save

    pub fn nr_changes(&self) -> u64 {
        self.nr_changes
    }

    /// copy the content of the buffer up to 'nr_bytes' into the data Vec
    /// the read bytes are appended to the data Vec
    /// return XXX on error (use ioresult)
    pub fn read(&self, offset: u64, nr_bytes: usize, mut data: &mut Vec<u8>) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::read(&mut it, nr_bytes, &mut data)
    }

    /// insert the 'data' Vec content in the buffer up to 'nr_bytes'
    /// return the number of written bytes (TODO: use io::Result)
    pub fn insert(&mut self, offset: u64, nr_bytes: usize, data: &[u8]) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::insert(&mut it, &data);

        self.size += nr_bytes;
        self.nr_changes += 1;

        nr_bytes
    }

    /// remove up to 'nr_bytes' from the buffer starting at offset
    /// if removed_data is provided will call self.read(offset, nr_bytes, data)
    /// before remove the bytes
    pub fn remove(
        &mut self,
        offset: u64,
        nr_bytes: usize,
        removed_data: Option<&mut Vec<u8>>,
    ) -> usize {
        let start_offset = ::std::cmp::min(offset as usize, self.size);
        let end_offset = ::std::cmp::min(start_offset + nr_bytes, self.size);
        let nr_bytes_removed = (end_offset - start_offset) as usize;

        // copy removed data
        if let Some(v) = removed_data {
            self.read(offset, nr_bytes_removed, v);
        }

        let mut it = MappedFile::iter_from(&self.data, start_offset as u64);
        MappedFile::remove(&mut it, nr_bytes_removed);

        self.size -= nr_bytes_removed;
        self.nr_changes += 1;

        nr_bytes_removed
    }

    /// can be used to know the number of blocks that compose the buffer,
    /// api to be used by indexer etc...
    pub fn nr_pages(&self) -> u64 {
        1
    }

    /*
    /// returns the position and size of a given page
    pub fn get_page_info(&self, page_index: u64) -> (Offset, PageSize) {
        // if page_index > 0 {
        //    (0, self.size)
        // } else {
        //    (0, self.size)
        // }
        (0, self.size)
    }
*/

    //
    // TODO: This is currently broken, because fd swapping is not implemented yet in mapped_file
    //
    //
    pub fn sync_to_disk(&self, tmp_file_name: &str) -> ::std::io::Result<()> {
        use std::fs;
        use std::fs::File;
        use std::io::Write;

        let mut f = File::create(&tmp_file_name)?;

        let mut offset: u64 = 0;
        while offset != self.size as u64 {
            let nr_bytes = 4096 * 32;
            let mut data = Vec::with_capacity(nr_bytes);
            let read_size = self.read(offset, nr_bytes, &mut data);
            f.write(&data)?;
            offset += read_size as u64;
        }
        f.sync_all()?;
        fs::rename(&tmp_file_name, &self.file_name)?;
        Ok(())
    }
}

#[test]
fn test_buffer() {
    let mut bb = Buffer::new("/dev/null".to_owned(), OpenMode::ReadWrite).unwrap();

    let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    bb.insert(0, 10, &data);
    let mut rdata = Vec::new();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    let data = vec![0, 1, 2, 6, 7, 8, 9];
    let rm_expect = vec![3, 4, 5];

    let mut rm = vec![];
    let n = bb.remove(3, 3, Some(&mut rm));
    assert_eq!(n, 3);
    assert_eq!(rm, rm_expect);

    rdata.clear();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);

    println!("rm {:?}", rm);
    println!("rm_expect {:?}", rm_expect);
}
<|endoftext|>


<commit_before>// http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
// not seriously audited.
// no bit-level support. sorry

const INIT_VAL: [u32; 8] = [
    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];

static K: [u32; 64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

macro_rules! be_u32 {
    // warning: $e is byte-oriented offset
    ($a:ident[$e:expr]) => ({
        let e = $e;
        let b0 = $a[e + 0] as u32;
        let b1 = $a[e + 1] as u32;
        let b2 = $a[e + 2] as u32;
        let b3 = $a[e + 3] as u32;
        (b0 << 8 * 3) | (b1 << 8 * 2) | (b2 << 8 * 1) | b3
    })
}

pub fn sha256(msg: &[u8]) -> [u8; 32] {
    fn rot(a: u32, b: usize) -> u32 {
        (a >> b) | (a << (32 - b))
    }

    let len = msg.len();
    let mut msg = msg.to_vec();

    msg.push(0x80);
    for _ in 0..((64 - 8 - 1 - len) & 63) {
        msg.push(0);
    }

    let bitlen = (len as u64) * 8; // FIXME: is overflow intended in spec?
    for i in (0..8).rev() {
        let b = (bitlen >> (8 * i)) as u8;
        msg.push(b);
    }

    debug_assert_eq!(msg.len() % (512 / 8), 0);

    let nblk = msg.len() / (512 / 8);

    let mut val = INIT_VAL;

    for i in (0..nblk) {
        let w = {
            let mut w = [0u32; 64];
            for j in 0..16 {
                let b0 = msg[i * 64 + j * 4 + 0] as u32;
                let b1 = msg[i * 64 + j * 4 + 1] as u32;
                let b2 = msg[i * 64 + j * 4 + 2] as u32;
                let b3 = msg[i * 64 + j * 4 + 3] as u32;
                w[j] = (b0 << 8 * 3) | (b1 << 8 * 2) | (b2 << 8 * 1) | b3;
            }

            for j in 16..64 {
                let wj15 = w[j - 15];
                let sig0 = rot(wj15, 7) ^ rot(wj15, 18) ^ (wj15 >> 3);

                let wj2 = w[j - 2];
                let sig1 = rot(wj2, 17) ^ rot(wj2, 19) ^ (wj2 >> 10);
                w[j] = sig1 + w[j - 7] + sig0 + w[j - 16];
            }

            w
        };

        let mut a: u32 = val[0];
        let mut b: u32 = val[1];
        let mut c: u32 = val[2];
        let mut d: u32 = val[3];
        let mut e: u32 = val[4];
        let mut f: u32 = val[5];
        let mut g: u32 = val[6];
        let mut h: u32 = val[7];

        for j in 0..64 {
            let ch = (e & f) ^ ((!e) & g);
            let maj = (a & b) ^ (a & c) ^ (b & c);

            let sig0 = rot(a, 2) ^ rot(a, 13) ^ rot(a, 22);
            let sig1 = rot(e, 6) ^ rot(e, 11) ^ rot(e, 25);

            let t1 = h + sig1 + ch + K[j] + w[j];
            let t2 = sig0 + maj;

            h = g;
            g = f;
            f = e;
            e = d + t1;
            d = c;
            c = b;
            b = a;
            a = t1 + t2;
        }

        val[0] += a;
        val[1] += b;
        val[2] += c;
        val[3] += d;
        val[4] += e;
        val[5] += f;
        val[6] += g;
        val[7] += h;

    }

    let mut ret = [0u8; 32];
    for i in 0..8 {
        ret[i * 4 + 0] = (val[i] >> 8 * 3) as u8;
        ret[i * 4 + 1] = (val[i] >> 8 * 2) as u8;
        ret[i * 4 + 2] = (val[i] >> 8 * 1) as u8;
        ret[i * 4 + 3] = val[i] as u8;
    }
    ret
}

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

    #[test]
    fn test_sha256() {
        static ANSWERS: &'static [(&'static [u8], &'static [u8])] = &[
            (b"",
             b"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\
               \x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"),
            (b"abc",
             b"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\
               \xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad"),
            (b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
             b"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\
               \xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"),
        ];

        for &(input, expected) in ANSWERS.iter() {
            let computed = sha256(input);
            assert_eq!(expected, &computed);
        }
    }
}
<commit_msg>sha2: Fix for overflow semantics change<commit_after>// http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
// not seriously audited.
// no bit-level support. sorry

use crypto::wrapping::*;

static K: [u32; 64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

pub fn sha256(msg: &[u8]) -> [u8; 32] {
    fn rot(a: w32, b: usize) -> w32 {
        (a >> b) | (a << (32 - b))
    }

    let len = msg.len();
    let mut msg = msg.to_vec(); // FIXME: do not allocate

    msg.push(0x80);
    let padding_len = (w64(64 - 8 - 1) - w64(len as u64)) & w64(63);
    for _ in 0..(padding_len.0) {
        msg.push(0);
    }

    let bitlen = (len as u64) * 8; // FIXME: disallow `len >= 2^64 / 8`
    for i in (0..8).rev() {
        let b = (w64(bitlen) >> (8 * i)).to_w8().0;
        msg.push(b);
    }

    debug_assert_eq!(msg.len() % (512 / 8), 0);

    let nblk = msg.len() / (512 / 8);

    let mut val: [w32; 8] = [
        w32(0x6a09e667), w32(0xbb67ae85), w32(0x3c6ef372), w32(0xa54ff53a),
        w32(0x510e527f), w32(0x9b05688c), w32(0x1f83d9ab), w32(0x5be0cd19),
    ];

    for i in 0..nblk {
        let w = {
            let mut w = [w32(0u32); 64];
            for j in 0..16 {
                let b0 = w8(msg[i * 64 + j * 4 + 0]).to_w32();
                let b1 = w8(msg[i * 64 + j * 4 + 1]).to_w32();
                let b2 = w8(msg[i * 64 + j * 4 + 2]).to_w32();
                let b3 = w8(msg[i * 64 + j * 4 + 3]).to_w32();
                w[j] = (b0 << 8 * 3) | (b1 << 8 * 2) | (b2 << 8 * 1) | b3;
            }

            for j in 16..64 {
                let wj15 = w[j - 15];
                let sig0 = rot(wj15, 7) ^ rot(wj15, 18) ^ (wj15 >> 3);

                let wj2 = w[j - 2];
                let sig1 = rot(wj2, 17) ^ rot(wj2, 19) ^ (wj2 >> 10);
                w[j] = sig1 + w[j - 7] + sig0 + w[j - 16];
            }

            w
        };

        let mut a: w32 = val[0];
        let mut b: w32 = val[1];
        let mut c: w32 = val[2];
        let mut d: w32 = val[3];
        let mut e: w32 = val[4];
        let mut f: w32 = val[5];
        let mut g: w32 = val[6];
        let mut h: w32 = val[7];

        for j in 0..64 {
            let ch = (e & f) ^ ((!e) & g);
            let maj = (a & b) ^ (a & c) ^ (b & c);

            let sig0 = rot(a, 2) ^ rot(a, 13) ^ rot(a, 22);
            let sig1 = rot(e, 6) ^ rot(e, 11) ^ rot(e, 25);

            let t1 = h + sig1 + ch + w32(K[j]) + w[j];
            let t2 = sig0 + maj;

            h = g;
            g = f;
            f = e;
            e = d + t1;
            d = c;
            c = b;
            b = a;
            a = t1 + t2;
        }

        val[0] = val[0] + a;
        val[1] = val[1] + b;
        val[2] = val[2] + c;
        val[3] = val[3] + d;
        val[4] = val[4] + e;
        val[5] = val[5] + f;
        val[6] = val[6] + g;
        val[7] = val[7] + h;
    }

    let mut ret = [0u8; 32];
    for i in 0..8 {
        ret[i * 4 + 0] = (val[i] >> 8 * 3).to_w8().0;
        ret[i * 4 + 1] = (val[i] >> 8 * 2).to_w8().0;
        ret[i * 4 + 2] = (val[i] >> 8 * 1).to_w8().0;
        ret[i * 4 + 3] = val[i].to_w8().0;
    }
    ret
}

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

    #[test]
    fn test_sha256() {
        static ANSWERS: &'static [(&'static [u8], &'static [u8])] = &[
            (b"",
             b"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\
               \x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"),
            (b"abc",
             b"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\
               \xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad"),
            (b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
             b"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\
               \xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"),
        ];

        for &(input, expected) in ANSWERS.iter() {
            let computed = sha256(input);
            assert_eq!(expected, &computed);
        }
    }
}
<|endoftext|>


<commit_before>// MIT License
//
// Copyright (c) 2020 Ben
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// © 2020 GitHub, Inc.
// Terms
// https://github.com/tempor1s/bktree-rs
use std::char;
use std::cmp::min;
use std::collections::HashMap;

/// BKTree structure that is used to store word like structures
/// and perform "fuzzy" search on them to implement "do you mean"
/// functionality on them. Can perform said search on any term that implements
/// the distance trait. The default implementation is Osa distance.
#[derive(Default)]
pub struct BKTree<K, V>
where
    K: Distance,
{
    root: Option<BKTreeNode<K, V>>,
}

impl<K, V> BKTree<K, V>
where
    K: Distance,
{
    /// Create a new BK Tree with an empty root.
    pub fn new() -> BKTree<K, V> {
        BKTree { root: None }
    }

    /// Create a new tree from the items in a Vector.
    /// Useful for inserting a lot of items from a file etc.
    /// Vector requires a Vec of tuples of K, V pairs where K implements Distance trait
    pub fn new_from_vec(items: Vec<(K, V)>) -> BKTree<K, V> {
        let mut tree = BKTree { root: None };

        for item in items {
            tree.insert(item.0, item.1);
        }

        return tree;
    }

    /// Add a new (key, value) pair into the BKTree.
    pub fn insert(&mut self, key: K, value: V) {
        // If the root exists, insert from there.
        if let Some(root) = &mut self.root {
            root.insert(key, value);
        } else {
            // otherwise, set the root to be a new BKTreeNode
            self.root = Some(BKTreeNode::new(key, value));
        }
    }

    /// Search for the closest Item to the key with a given tolerence. (Steps to get there)
    /// The return value is a tuple of 2 Vecs, where the first one has exact matches and the second
    /// are matches within the given tolerence.
    ///
    /// A match is approximate if the distance between key1 and key2 are less than the given tolerence.
    pub fn find(&self, key: &K, tolerence: usize) -> (Vec<&V>, Vec<&K>) {
        // if our root exists, search from the root
        return if let Some(root) = &self.root {
            root.find(&key, tolerence)
        } else {
            // if we can not find anything, return a tuple of empty vectors
            (vec![], vec![])
        };
    }
}

#[derive(Debug)]
struct BKTreeNode<K, V>
where
    K: Distance,
{
    key: K,
    value: V,
    children: HashMap<usize, BKTreeNode<K, V>>,
}

impl<K, V> BKTreeNode<K, V>
where
    K: Distance,
{
    /// Create a new BK Tree Node with the given (K, V) pair and empty HashMap of children
    fn new(key: K, value: V) -> Self {
        BKTreeNode {
            key,
            value,
            children: HashMap::new(),
        }
    }

    /// Insert a new (key, value) pair into this nodes children
    fn insert(&mut self, key: K, value: V) {
        // Get the distance between the current nodes key and the given key
        let distance = self.key.distance(&key);
        // If the child exists, traverse and insert from there.
        if let Some(child) = self.children.get_mut(&distance) {
            child.insert(key, value);
        } else {
            // otherwise, insert the current node into the children and with the given distance
            self.children.insert(distance, BKTreeNode::new(key, value));
        }
    }

    /// Find a key in the given childrens nodes
    fn find(&self, key: &K, leniency: usize) -> (Vec<&V>, Vec<&K>) {
        // Create a new tuple of empty vectors for exact and close matches
        let (mut exact, mut close) = (vec![], vec![]);
        // Get the distance between the current nodes key and then passed in key.
        let current_distance = self.key.distance(&key);
        // If the current distance is 0, it means its an exact match so push it to our "exact" matches
        if current_distance == 0 {
            exact.push(&self.value);
        // Otherwise, if the value is less than our leniency then add it to the close matches
        } else if current_distance <= leniency {
            close.push(&self.key);
        }

        // Saturing just means that the values will not overflow
        for i in
            current_distance.saturating_sub(leniency)..=current_distance.saturating_add(leniency)
        {
            // Because of how the tree works, we can traverse based off the leniency
            if let Some(child) = self.children.get(&i) {
                let mut result = child.find(key, leniency);
                exact.append(&mut result.0);
                close.append(&mut result.1);
            }
        }
        // return our vector of close and exact values
        return (exact, close);
    }
}

/// This trait is used by the BKTree to determine the distance between 2 objects
/// when fuzzy searching. An example of this for strings is the Levenshtein distance,
/// Damerau-Levenshtein distance, Optimal string alignment distance, or a custom implementation.
pub trait Distance {
    /// Used to determine the "distance" between two objects.
    fn distance(&self, other: &Self) -> usize;
}

// We want to implement distance for String, and OSA is a good way to do so.
// This allows us to create a BKTree using Strings
impl Distance for String {
    fn distance(&self, other: &Self) -> usize {
        osa_distance(self, other)
    }
}

impl Distance for &str {
    fn distance(&self, other: &Self) -> usize {
        osa_distance(self, other)
    }
}

// Manual implementation of this function. Did not want to include a seperate library.
// https://docs.rs/strsim/0.9.2/src/strsim/lib.rs.html#263-307
fn osa_distance(a: &str, b: &str) -> usize {
    let a_len = a.chars().count();
    let b_len = b.chars().count();

    if a == b {
        return 0;
    } else if a_len == 0 {
        return b_len;
    } else if b_len == 0 {
        return a_len;
    }

    let mut prev_two_distances = Vec::with_capacity(b_len + 1);
    let mut prev_distances = Vec::with_capacity(b_len + 1);
    let mut current_distances = Vec::with_capacity(b_len + 1);

    let mut prev_a_char = char::MAX;
    let mut prev_b_char = char::MAX;

    for i in 0..(b_len + 1) {
        prev_two_distances.push(i);
        prev_distances.push(i);
        current_distances.push(0);
    }

    for (i, a_char) in a.chars().enumerate() {
        current_distances[0] = i + 1;

        for (j, b_char) in b.chars().enumerate() {
            let cost = if a_char == b_char { 0 } else { 1 };
            current_distances[j + 1] = min(
                current_distances[j] + 1,
                min(prev_distances[j + 1] + 1, prev_distances[j] + cost),
            );

            if i > 0 && j > 0 && a_char != b_char && a_char == prev_b_char && b_char == prev_a_char
            {
                current_distances[j + 1] =
                    min(current_distances[j + 1], prev_two_distances[j - 1] + 1);
            }

            prev_b_char = b_char;
        }

        prev_two_distances.clone_from(&prev_distances);
        prev_distances.clone_from(&current_distances);
        prev_a_char = a_char;
    }

    current_distances[b_len]
}

use nalgebra::DVector;

// https://bergvca.github.io/2017/10/14/super-fast-string-matching.html
fn cos_sim(a: &DVector<f32>, b: &DVector<f32>) -> f32 {
    let dot_product = a.dot(&b);
    let norm_a = a.norm();
    let norm_b = b.norm();
    dot_product / (norm_a * norm_b)
}

fn cos_sim_as_str<'a>(first: &'a str, second: &'a str) -> f32 {
    let filled_first;
    let filled_second;
    let diff: i16 = first.chars().count() as i16 - second.chars().count() as i16;
    if diff == 0 {
        filled_first = first.to_string();
        filled_second = second.to_string();
    } else {
        if diff < 0 {
            filled_second = second.to_string();
            filled_first = first.to_string() + &" ".repeat(-diff as usize);
        } else {
            filled_first = first.to_string();
            filled_second = second.to_string() + &" ".repeat(diff as usize);
        }
    }

    let converter_string = |arr: &str| -> DVector<f32> {
        let new_vec: Vec<f32> = arr.chars().map(|a| (a as u32) as f32).collect();
        DVector::from_row_slice(&new_vec)
    };
    let vec_first = converter_string(&filled_first);
    let vec_second = converter_string(&filled_second);

    cos_sim(&vec_first, &vec_second)
}

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

    #[test]
    fn cosine_similarity_some_values() {
        assert_eq!(
            0.9099716,
            cos_sim_as_str("AMERICAN SCRAP PROCESSING INC", "SCRAP PROCESSING INC")
        );
        assert_eq!(
            0.9511214,
            cos_sim_as_str("ACP ACQUISITION CORP", "CP ACQUISITION CORP")
        );
        assert_eq!(
            0.9636469,
            cos_sim_as_str("ADAMANT TECHNOLOGIES", "NT TECHNOLOGIES, INC.")
        );
    }

    #[test]
    fn cosine_similarity_utf8() {
        assert_eq!(0.85936946, cos_sim_as_str("zehn", "fünfzehn"));
        assert_eq!(
            0.96889335,
            cos_sim_as_str(
                "Genesis - The Carpet Crawlers",
                "Genesys - The carpett craulers"
            )
        );
        assert_eq!(
            0.9465689,
            cos_sim_as_str(
                "Genesis - (The Lamb Lies Down on Broadway) The Carpet Crawlers",
                "Genesys - (The Lamb Lies Down on Broadway) The Chamber of 32 Doors"
            )
        );
    }
}
<commit_msg>[collection] trying of cosine but doesn't fit to data model, but test will be used<commit_after>// MIT License
//
// Copyright (c) 2020 Ben
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// © 2020 GitHub, Inc.
// Terms
// https://github.com/tempor1s/bktree-rs
use std::char;
use std::cmp::min;
use std::collections::{HashMap, HashSet};

/// BKTree structure that is used to store word like structures
/// and perform "fuzzy" search on them to implement "do you mean"
/// functionality on them. Can perform said search on any term that implements
/// the distance trait. The default implementation is Osa distance.
#[derive(Default)]
pub struct BKTree<K, V>
where
    K: Distance,
{
    root: Option<BKTreeNode<K, V>>,
}

impl<K, V> BKTree<K, V>
where
    K: Distance,
{
    /// Create a new BK Tree with an empty root.
    pub fn new() -> BKTree<K, V> {
        BKTree { root: None }
    }

    /// Create a new tree from the items in a Vector.
    /// Useful for inserting a lot of items from a file etc.
    /// Vector requires a Vec of tuples of K, V pairs where K implements Distance trait
    pub fn new_from_vec(items: Vec<(K, V)>) -> BKTree<K, V> {
        let mut tree = BKTree { root: None };

        for item in items {
            tree.insert(item.0, item.1);
        }

        return tree;
    }

    /// Add a new (key, value) pair into the BKTree.
    pub fn insert(&mut self, key: K, value: V) {
        // If the root exists, insert from there.
        if let Some(root) = &mut self.root {
            root.insert(key, value);
        } else {
            // otherwise, set the root to be a new BKTreeNode
            self.root = Some(BKTreeNode::new(key, value));
        }
    }

    /// Search for the closest Item to the key with a given tolerence. (Steps to get there)
    /// The return value is a tuple of 2 Vecs, where the first one has exact matches and the second
    /// are matches within the given tolerence.
    ///
    /// A match is approximate if the distance between key1 and key2 are less than the given tolerence.
    pub fn find(&self, key: &K, tolerence: usize) -> (Vec<&V>, Vec<&K>) {
        // if our root exists, search from the root
        return if let Some(root) = &self.root {
            root.find(&key, tolerence)
        } else {
            // if we can not find anything, return a tuple of empty vectors
            (vec![], vec![])
        };
    }
}

#[derive(Debug)]
struct BKTreeNode<K, V>
where
    K: Distance,
{
    key: K,
    value: V,
    children: HashMap<usize, BKTreeNode<K, V>>,
}

impl<K, V> BKTreeNode<K, V>
where
    K: Distance,
{
    /// Create a new BK Tree Node with the given (K, V) pair and empty HashMap of children
    fn new(key: K, value: V) -> Self {
        BKTreeNode {
            key,
            value,
            children: HashMap::new(),
        }
    }

    /// Insert a new (key, value) pair into this nodes children
    fn insert(&mut self, key: K, value: V) {
        // Get the distance between the current nodes key and the given key
        let distance = self.key.distance(&key);
        // If the child exists, traverse and insert from there.
        if let Some(child) = self.children.get_mut(&distance) {
            child.insert(key, value);
        } else {
            // otherwise, insert the current node into the children and with the given distance
            self.children.insert(distance, BKTreeNode::new(key, value));
        }
    }

    /// Find a key in the given childrens nodes
    fn find(&self, key: &K, leniency: usize) -> (Vec<&V>, Vec<&K>) {
        // Create a new tuple of empty vectors for exact and close matches
        let (mut exact, mut close) = (vec![], vec![]);
        // Get the distance between the current nodes key and then passed in key.
        let current_distance = self.key.distance(&key);
        // If the current distance is 0, it means its an exact match so push it to our "exact" matches
        if current_distance == 0 {
            exact.push(&self.value);
        // Otherwise, if the value is less than our leniency then add it to the close matches
        } else if current_distance <= leniency {
            close.push(&self.key);
        }

        // Saturing just means that the values will not overflow
        for i in
            current_distance.saturating_sub(leniency)..=current_distance.saturating_add(leniency)
        {
            // Because of how the tree works, we can traverse based off the leniency
            if let Some(child) = self.children.get(&i) {
                let mut result = child.find(key, leniency);
                exact.append(&mut result.0);
                close.append(&mut result.1);
            }
        }
        // return our vector of close and exact values
        return (exact, close);
    }
}

/// This trait is used by the BKTree to determine the distance between 2 objects
/// when fuzzy searching. An example of this for strings is the Levenshtein distance,
/// Damerau-Levenshtein distance, Optimal string alignment distance, or a custom implementation.
pub trait Distance {
    /// Used to determine the "distance" between two objects.
    fn distance(&self, other: &Self) -> usize;
}

// We want to implement distance for String, and OSA is a good way to do so.
// This allows us to create a BKTree using Strings
impl Distance for String {
    fn distance(&self, other: &Self) -> usize {
        osa_distance(self, other)
    }
}

impl Distance for &str {
    fn distance(&self, other: &Self) -> usize {
        osa_distance(self, other)
    }
}

// Manual implementation of this function. Did not want to include a seperate library.
// https://docs.rs/strsim/0.9.2/src/strsim/lib.rs.html#263-307
fn osa_distance(a: &str, b: &str) -> usize {
    let a_len = a.chars().count();
    let b_len = b.chars().count();

    if a == b {
        return 0;
    } else if a_len == 0 {
        return b_len;
    } else if b_len == 0 {
        return a_len;
    }

    let mut prev_two_distances = Vec::with_capacity(b_len + 1);
    let mut prev_distances = Vec::with_capacity(b_len + 1);
    let mut current_distances = Vec::with_capacity(b_len + 1);

    let mut prev_a_char = char::MAX;
    let mut prev_b_char = char::MAX;

    for i in 0..(b_len + 1) {
        prev_two_distances.push(i);
        prev_distances.push(i);
        current_distances.push(0);
    }

    for (i, a_char) in a.chars().enumerate() {
        current_distances[0] = i + 1;

        for (j, b_char) in b.chars().enumerate() {
            let cost = if a_char == b_char { 0 } else { 1 };
            current_distances[j + 1] = min(
                current_distances[j] + 1,
                min(prev_distances[j + 1] + 1, prev_distances[j] + cost),
            );

            if i > 0 && j > 0 && a_char != b_char && a_char == prev_b_char && b_char == prev_a_char
            {
                current_distances[j + 1] =
                    min(current_distances[j + 1], prev_two_distances[j - 1] + 1);
            }

            prev_b_char = b_char;
        }

        prev_two_distances.clone_from(&prev_distances);
        prev_distances.clone_from(&current_distances);
        prev_a_char = a_char;
    }

    current_distances[b_len]
}

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

    static TEST_DATA: [(&'static str, &'static str); 7] = [
        ("AMERICAN SCRAP PROCESSING INC", "SCRAP PROCESSING INC"), // 0
        ("ACP ACQUISITION CORP", "CP ACQUISITION CORP"),           // 1
        ("ADAMANT TECHNOLOGIES", "NT TECHNOLOGIES, INC."),         // 2
        ("zehn", "fünfzehn"),                                     // 3
        (
            // 4
            "Genesis - The Carpet Crawlers",
            "Genesys - The carpett craulers",
        ),
        (
            // 5
            "Genesis - (The Lamb Lies Down on Broadway) The Carpet Crawlers",
            "Genesys - (The Lamb Lies Down on Broadway) The Chamber of 32 Doors",
        ),
        (
            // 6
            "Genesis - (The Lamb Lies Down on Broadway) The Lamia",
            "Genesis - The Lamia",
        ),
    ];

    #[test]
    fn osa_1() {
        assert_eq!(0, osa_distance(TEST_DATA[0].0, TEST_DATA[0].0));
        assert_eq!(9, osa_distance(TEST_DATA[0].0, TEST_DATA[0].1));
        assert_eq!(1, osa_distance(TEST_DATA[1].0, TEST_DATA[1].1));
        assert_eq!(11, osa_distance(TEST_DATA[2].0, TEST_DATA[2].1));
        assert_eq!(4, osa_distance(TEST_DATA[3].0, TEST_DATA[3].1));
        assert_eq!(5, osa_distance(TEST_DATA[4].0, TEST_DATA[4].1));
        assert_eq!(14, osa_distance(TEST_DATA[5].0, TEST_DATA[5].1));
        assert_eq!(33, osa_distance(TEST_DATA[6].0, TEST_DATA[6].1));
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use crate::error::msg::SemError;
use crate::semck;
use crate::ty::SourceType;
use crate::vm::{Fct, FctParent, FileId, ImplId, NamespaceId, VM};

use dora_parser::ast;

pub fn check(vm: &VM) {
    for ximpl in vm.impls.iter() {
        let (impl_id, file_id, namespace_id, ast) = {
            let ximpl = ximpl.read();

            (
                ximpl.id,
                ximpl.file_id,
                ximpl.namespace_id,
                ximpl.ast.clone(),
            )
        };

        let mut implck = ImplCheck {
            vm,
            impl_id,
            file_id,
            namespace_id,
            ast: &ast,
        };

        implck.check();
    }
}

struct ImplCheck<'x> {
    vm: &'x VM,
    file_id: FileId,
    impl_id: ImplId,
    namespace_id: NamespaceId,
    ast: &'x ast::Impl,
}

impl<'x> ImplCheck<'x> {
    fn check(&mut self) {
        assert!(self.ast.trait_type.is_some());

        for method in &self.ast.methods {
            self.visit_method(method);
        }

        let mut ximpl = self.vm.impls[self.impl_id].write();

        if self.ast.type_params.is_some() {
            // We don't support type parameters for impl-blocks yet.
            self.vm
                .diag
                .lock()
                .report(self.file_id, self.ast.pos, SemError::Unimplemented);
            return;
        }

        if let Some(ref expr_trait_type) = self.ast.trait_type {
            if let Some(trait_ty) = semck::read_type_namespace(
                self.vm,
                self.file_id.into(),
                self.namespace_id,
                expr_trait_type,
            ) {
                match trait_ty {
                    SourceType::TraitObject(trait_id) => {
                        ximpl.trait_id = Some(trait_id);
                    }

                    _ => {
                        self.vm.diag.lock().report(
                            self.file_id,
                            self.ast.pos,
                            SemError::ExpectedTrait,
                        );
                    }
                }
            }
        } else {
            // We don't support extension blocks yet.
            self.vm
                .diag
                .lock()
                .report(self.file_id, self.ast.pos, SemError::Unimplemented);
            return;
        }

        if let Some(class_ty) = semck::read_type_namespace(
            self.vm,
            self.file_id.into(),
            self.namespace_id,
            &self.ast.class_type,
        ) {
            if class_ty.cls_id(self.vm).is_some() || class_ty.is_struct() {
                ximpl.ty = class_ty;
            } else {
                self.vm.diag.lock().report(
                    self.file_id,
                    self.ast.class_type.pos(),
                    SemError::ClassExpected,
                );
            }
        }

        if ximpl.trait_id.is_some() && !ximpl.ty.is_error() {
            let cls = self.vm.classes.idx(ximpl.cls_id(self.vm));
            let mut cls = cls.write();
            cls.traits.push(ximpl.trait_id());
            cls.impls.push(ximpl.id);
        }
    }

    fn visit_method(&mut self, method: &Arc<ast::Function>) {
        if method.block.is_none() && !method.internal {
            self.vm
                .diag
                .lock()
                .report(self.file_id.into(), method.pos, SemError::MissingFctBody);
        }

        let parent = FctParent::Impl(self.impl_id);

        let fct = Fct::new(self.file_id.into(), self.namespace_id, method, parent);
        let fctid = self.vm.add_fct(fct);

        let mut ximpl = self.vm.impls[self.impl_id].write();
        ximpl.methods.push(fctid);
    }
}

#[cfg(test)]
mod tests {
    use crate::error::msg::SemError;
    use crate::semck::tests::*;

    #[test]
    fn impl_method_without_body() {
        err(
            "
            trait Foo {
                fun foo(): Int32;
            }
            class Bar {}
            impl Foo for Bar { fun foo(): Int32;}",
            pos(6, 32),
            SemError::MissingFctBody,
        );
    }

    #[test]
    fn impl_method_defined_twice() {
        err(
            "
            trait Foo {
                fun foo(): Int32;
            }
            class Bar {}
            impl Foo for Bar {
                fun foo(): Int32 { return 0; }
                fun foo(): Int32 { return 1; }
            }",
            pos(8, 17),
            SemError::MethodExists("foo".into(), pos(7, 17)),
        );
    }

    #[test]
    fn impl_for_unknown_trait() {
        err(
            "class A {} impl Foo for A {}",
            pos(1, 17),
            SemError::UnknownIdentifier("Foo".into()),
        );
    }

    #[test]
    fn impl_for_unknown_class() {
        err(
            "trait Foo {} impl Foo for A {}",
            pos(1, 27),
            SemError::UnknownIdentifier("A".into()),
        );

        err(
            "trait Foo {} trait A {} impl Foo for A {}",
            pos(1, 38),
            SemError::ClassExpected,
        );
    }

    #[test]
    fn impl_definitions() {
        ok("trait Foo {} class A {} impl Foo for A {}");
        ok("trait Foo { fun toBool(): Bool; }
            class A {}
            impl Foo for A { fun toBool(): Bool { return false; } }");
    }

    #[test]
    #[ignore]
    fn impl_struct() {
        ok("trait Foo {} struct A(x: Int32) impl Foo for A {}");
    }

    #[test]
    fn impl_class_type_params() {
        ok("trait MyTrait {} class Foo[T] impl MyTrait for Foo[String] {}");
    }

    #[test]
    fn impl_namespace() {
        err(
            "
            namespace foo { trait MyTrait {} }
            class Foo
            impl foo::MyTrait for Foo {}",
            pos(4, 18),
            SemError::NotAccessible("foo::MyTrait".into()),
        );

        err(
            "
            namespace foo { class Foo }
            trait MyTrait {}
            impl MyTrait for foo::Foo {}",
            pos(4, 30),
            SemError::NotAccessible("foo::Foo".into()),
        );
    }
}
<commit_msg>impldefck: prepare for checking type params<commit_after>use std::sync::Arc;

use crate::error::msg::SemError;
use crate::semck;
use crate::sym::NestedSymTable;
use crate::ty::SourceType;
use crate::vm::{Fct, FctId, FctParent, FileId, ImplId, NamespaceId, VM};

use dora_parser::ast;

pub fn check(vm: &VM) {
    for ximpl in vm.impls.iter() {
        let (impl_id, file_id, namespace_id, ast) = {
            let ximpl = ximpl.read();

            (
                ximpl.id,
                ximpl.file_id,
                ximpl.namespace_id,
                ximpl.ast.clone(),
            )
        };

        let mut implck = ImplCheck {
            vm,
            impl_id,
            file_id,
            namespace_id,
            sym: NestedSymTable::new(vm, namespace_id),
            ast: &ast,
        };

        implck.check();
    }
}

struct ImplCheck<'x> {
    vm: &'x VM,
    file_id: FileId,
    impl_id: ImplId,
    namespace_id: NamespaceId,
    sym: NestedSymTable<'x>,
    ast: &'x ast::Impl,
}

impl<'x> ImplCheck<'x> {
    fn check(&mut self) {
        assert!(self.ast.trait_type.is_some());

        self.sym.push_level();

        let mut ximpl = self.vm.impls[self.impl_id].write();

        let ast_trait_type = self.ast.trait_type.as_ref().unwrap();

        if let Some(trait_ty) =
            semck::read_type_table(self.vm, &self.sym, self.file_id.into(), ast_trait_type)
        {
            match trait_ty {
                SourceType::TraitObject(trait_id) => {
                    ximpl.trait_id = Some(trait_id);
                }

                _ => {
                    self.vm
                        .diag
                        .lock()
                        .report(self.file_id, self.ast.pos, SemError::ExpectedTrait);
                }
            }
        }

        if let Some(class_ty) = semck::read_type_table(
            self.vm,
            &self.sym,
            self.file_id.into(),
            &self.ast.class_type,
        ) {
            if class_ty.cls_id(self.vm).is_some() || class_ty.is_struct() {
                ximpl.ty = class_ty;
            } else {
                self.vm.diag.lock().report(
                    self.file_id,
                    self.ast.class_type.pos(),
                    SemError::ClassExpected,
                );
            }
        }

        if ximpl.trait_id.is_some() && !ximpl.ty.is_error() {
            let cls = self.vm.classes.idx(ximpl.cls_id(self.vm));
            let mut cls = cls.write();
            cls.traits.push(ximpl.trait_id());
            cls.impls.push(ximpl.id);
        }

        self.sym.pop_level();

        for method in &self.ast.methods {
            let method_id = self.visit_method(method);
            ximpl.methods.push(method_id);
        }
    }

    fn visit_method(&mut self, method: &Arc<ast::Function>) -> FctId {
        if method.block.is_none() && !method.internal {
            self.vm
                .diag
                .lock()
                .report(self.file_id.into(), method.pos, SemError::MissingFctBody);
        }

        let parent = FctParent::Impl(self.impl_id);

        let fct = Fct::new(self.file_id.into(), self.namespace_id, method, parent);
        self.vm.add_fct(fct)
    }
}

#[cfg(test)]
mod tests {
    use crate::error::msg::SemError;
    use crate::semck::tests::*;

    #[test]
    fn impl_method_without_body() {
        err(
            "
            trait Foo {
                fun foo(): Int32;
            }
            class Bar {}
            impl Foo for Bar { fun foo(): Int32;}",
            pos(6, 32),
            SemError::MissingFctBody,
        );
    }

    #[test]
    fn impl_method_defined_twice() {
        err(
            "
            trait Foo {
                fun foo(): Int32;
            }
            class Bar {}
            impl Foo for Bar {
                fun foo(): Int32 { return 0; }
                fun foo(): Int32 { return 1; }
            }",
            pos(8, 17),
            SemError::MethodExists("foo".into(), pos(7, 17)),
        );
    }

    #[test]
    fn impl_for_unknown_trait() {
        err(
            "class A {} impl Foo for A {}",
            pos(1, 17),
            SemError::UnknownIdentifier("Foo".into()),
        );
    }

    #[test]
    fn impl_for_unknown_class() {
        err(
            "trait Foo {} impl Foo for A {}",
            pos(1, 27),
            SemError::UnknownIdentifier("A".into()),
        );

        err(
            "trait Foo {} trait A {} impl Foo for A {}",
            pos(1, 38),
            SemError::ClassExpected,
        );
    }

    #[test]
    fn impl_definitions() {
        ok("trait Foo {} class A {} impl Foo for A {}");
        ok("trait Foo { fun toBool(): Bool; }
            class A {}
            impl Foo for A { fun toBool(): Bool { return false; } }");
    }

    #[test]
    #[ignore]
    fn impl_struct() {
        ok("trait Foo {} struct A(x: Int32) impl Foo for A {}");
    }

    #[test]
    fn impl_class_type_params() {
        ok("trait MyTrait {} class Foo[T] impl MyTrait for Foo[String] {}");
    }

    #[test]
    fn impl_namespace() {
        err(
            "
            namespace foo { trait MyTrait {} }
            class Foo
            impl foo::MyTrait for Foo {}",
            pos(4, 18),
            SemError::NotAccessible("foo::MyTrait".into()),
        );

        err(
            "
            namespace foo { class Foo }
            trait MyTrait {}
            impl MyTrait for foo::Foo {}",
            pos(4, 30),
            SemError::NotAccessible("foo::Foo".into()),
        );
    }
}
<|endoftext|>


<commit_before>
use libc::c_char;
pub use wlroots_sys::wlr_log_importance::{self, *};
use wlroots_sys::{__va_list_tag, wlr_log_init};
use vsprintf::vsprintf;

use utils::c_to_rust_string;

/// How verbose you want the logging. Lower levels prints more.
pub type LogVerbosity = wlr_log_importance;

/// The signature for the callback function you can hook into the logging
/// functionality of wlroots.
pub type LogCallback = fn(LogVerbosity, String);

static mut RUST_LOGGING_FN: LogCallback = dummy_callback;

/// Initialize wlroots logging at a certain level of verbosity with
/// an optional callback that will be called for every log.
///
/// To log using this system, use the `wlr_log!` macro.
// TODO Wrap the callback function type
pub fn init_logging<T>(verbosity: LogVerbosity, callback: T)
where T: Into<Option<LogCallback>>
{
    unsafe {
        match callback.into() {
            None => wlr_log_init(verbosity, None),
            Some(callback) => {
                RUST_LOGGING_FN = callback;
                wlr_log_init(verbosity, Some(log_callback));
            }
        }
    }
}

/// Dummy callback to fill in RUST_LOGGING_FN when it's not in use.
fn dummy_callback(_: LogVerbosity, _: String) {}

/// Real hook into the logging callback, calls the real user-supplied callback
/// with nice Rust inputs.
unsafe extern "C" fn log_callback(importance: wlr_log_importance,
                                  fmt: *const c_char,
                                  va_list: *mut __va_list_tag) {
    let message = vsprintf(fmt, va_list).unwrap_or_else(|_| {
        c_to_rust_string(fmt).unwrap_or_else(|| "".into())
    });
    RUST_LOGGING_FN(importance, message);
}
<commit_msg>Added log documentation<commit_after>//! Hooks into the wlroots logging functionality. Internally many events are logged
//! and are reported on standard error. The verbosity of the logs is determined by
//! [the verbosity level](type.LogVerbosity.html) when
//! [initializing the logs](fn.init_logging.html).
//!
//! To log using this system please utilize the [`wlr_log!`](../../macro.wlr_log.html) macro.

use libc::c_char;
pub use wlroots_sys::wlr_log_importance::{self, WLR_SILENT, WLR_ERROR, WLR_INFO,
                                          WLR_DEBUG, WLR_LOG_IMPORTANCE_LAST};
use wlroots_sys::{__va_list_tag, wlr_log_init};
use vsprintf::vsprintf;

use utils::c_to_rust_string;

/// How verbose you want the logging. Lower levels prints more.
pub type LogVerbosity = wlr_log_importance;

/// The signature for the callback function you can hook into the logging
/// functionality of wlroots.
pub type LogCallback = fn(LogVerbosity, String);

static mut RUST_LOGGING_FN: LogCallback = dummy_callback;

/// Initialize wlroots logging at a certain level of verbosity with
/// an optional callback that will be called for every log.
///
/// To log using this system, use the `wlr_log!` macro.
pub fn init_logging<F>(verbosity: LogVerbosity, callback: F)
where F: Into<Option<LogCallback>>
{
    unsafe {
        match callback.into() {
            None => wlr_log_init(verbosity, None),
            Some(callback) => {
                RUST_LOGGING_FN = callback;
                wlr_log_init(verbosity, Some(log_callback));
            }
        }
    }
}

/// Dummy callback to fill in RUST_LOGGING_FN when it's not in use.
fn dummy_callback(_: LogVerbosity, _: String) {}

/// Real hook into the logging callback, calls the real user-supplied callback
/// with nice Rust inputs.
unsafe extern "C" fn log_callback(importance: wlr_log_importance,
                                  fmt: *const c_char,
                                  va_list: *mut __va_list_tag) {
    let message = vsprintf(fmt, va_list).unwrap_or_else(|_| {
        c_to_rust_string(fmt).unwrap_or_else(|| "".into())
    });
    RUST_LOGGING_FN(importance, message);
}
<|endoftext|>


<commit_before>use std::error::Error;
use iron::prelude::*;
use iron::Handler;
use iron::status;
use web::page::Page;
use std::fmt;

#[derive(Debug, Copy, Clone)]
pub enum Nope {
    ResourceNotFound,
    CrateNotFound,
    NoResults,
}

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

impl Error for Nope {
    fn description(&self) -> &str {
        match *self {
            Nope::ResourceNotFound => "Requested resource not found",
            Nope::CrateNotFound => "Requested crate not found",
            Nope::NoResults => "Search yielded no results",
        }
    }
}

impl Handler for Nope {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match *self {
            Nope::ResourceNotFound => {
                // user tried to navigate to a resource (doc page/file) that doesn't exist
                Page::new("no such resource".to_owned())
                    .set_status(status::NotFound)
                    .title("The requested resource does not exist")
                    .to_resp("error")
            }
            Nope::CrateNotFound => {
                // user tried to navigate to a crate that doesn't exist
                Page::new("no such crate".to_owned())
                    .set_status(status::NotFound)
                    .title("The requested crate does not exist")
                    .to_resp("error")
            }
            Nope::NoResults => {
                use params::{Params, Value};
                let params = req.get::<Params>().unwrap();
                if let Some(&Value::String(ref query)) = params.find(&["query"]) {
                    // this used to be a search
                    Page::new(Vec::<super::releases::Release>::new())
                        .set_status(status::NotFound)
                        .set("search_query", &query)
                        .title(&format!("No crates found matching '{}'", query))
                        .to_resp("releases")
                } else {
                    unimplemented!();
                }
            }
        }
    }
}
<commit_msg>Handle searches with no query<commit_after>use std::error::Error;
use iron::prelude::*;
use iron::Handler;
use iron::status;
use web::page::Page;
use std::fmt;

#[derive(Debug, Copy, Clone)]
pub enum Nope {
    ResourceNotFound,
    CrateNotFound,
    NoResults,
}

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

impl Error for Nope {
    fn description(&self) -> &str {
        match *self {
            Nope::ResourceNotFound => "Requested resource not found",
            Nope::CrateNotFound => "Requested crate not found",
            Nope::NoResults => "Search yielded no results",
        }
    }
}

impl Handler for Nope {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match *self {
            Nope::ResourceNotFound => {
                // user tried to navigate to a resource (doc page/file) that doesn't exist
                Page::new("no such resource".to_owned())
                    .set_status(status::NotFound)
                    .title("The requested resource does not exist")
                    .to_resp("error")
            }
            Nope::CrateNotFound => {
                // user tried to navigate to a crate that doesn't exist
                Page::new("no such crate".to_owned())
                    .set_status(status::NotFound)
                    .title("The requested crate does not exist")
                    .to_resp("error")
            }
            Nope::NoResults => {
                use params::{Params, Value};
                let params = req.get::<Params>().unwrap();
                if let Some(&Value::String(ref query)) = params.find(&["query"]) {
                    // this used to be a search
                    Page::new(Vec::<super::releases::Release>::new())
                        .set_status(status::NotFound)
                        .set("search_query", &query)
                        .title(&format!("No crates found matching '{}'", query))
                        .to_resp("releases")
                } else {
                    // user did a search with no search terms
                    Page::new(Vec::<super::releases::Release>::new())
                        .set_status(status::NotFound)
                        .title("No results given for empty search query")
                        .to_resp("releases")
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate security_framework;
extern crate security_framework_sys;
extern crate tempdir;

use self::security_framework::base;
use self::security_framework::certificate::SecCertificate;
use self::security_framework::identity::SecIdentity;
use self::security_framework::import_export::{Pkcs12ImportOptions, ImportedIdentityOptions};
use self::security_framework::secure_transport::{self, SslContext, ProtocolSide, ConnectionType,
                                                 SslProtocol, ClientBuilder};
use self::security_framework_sys::base::errSecIO;
use self::tempdir::TempDir;
use std::fmt;
use std::io;
use std::error;
use std::sync::Mutex;
use std::sync::{Once, ONCE_INIT};

#[cfg(not(target_os = "ios"))]
use self::security_framework::os::macos::keychain::{self, SecKeychain, KeychainSettings};
use self::security_framework::os::macos::import_export::{SecItems, ImportOptions};

use Protocol;

static SET_AT_EXIT: Once = ONCE_INIT;

#[cfg(not(target_os = "ios"))]
lazy_static! {
    static ref TEMP_KEYCHAIN: Mutex<Option<(SecKeychain, TempDir)>> = Mutex::new(None);
}

fn convert_protocol(protocol: Protocol) -> SslProtocol {
    match protocol {
        Protocol::Sslv3 => SslProtocol::Ssl3,
        Protocol::Tlsv10 => SslProtocol::Tls1,
        Protocol::Tlsv11 => SslProtocol::Tls11,
        Protocol::Tlsv12 => SslProtocol::Tls12,
        Protocol::__NonExhaustive => unreachable!(),
    }
}

fn protocol_min_max(protocols: &[Protocol]) -> (SslProtocol, SslProtocol) {
    let mut min = Protocol::Tlsv12;
    let mut max = Protocol::Sslv3;
    for protocol in protocols {
        if (*protocol as usize) < (min as usize) {
            min = *protocol;
        }
        if (*protocol as usize) > (max as usize) {
            max = *protocol;
        }
    }
    (convert_protocol(min), convert_protocol(max))
}

pub struct Error(base::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<base::Error> for Error {
    fn from(error: base::Error) -> Error {
        Error(error)
    }
}

#[derive(Clone)]
pub struct Pkcs12 {
    identity: SecIdentity,
    chain: Vec<SecCertificate>,
}

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let mut imports = try!(Pkcs12::import_options(buf, pass));
        let import = imports.pop().unwrap();

        let identity = import.identity.expect(
            "Pkcs12 files must include an identity",
        );

        // FIXME: Compare the certificates for equality using CFEqual
        let identity_cert = try!(identity.certificate()).to_der();

        Ok(Pkcs12 {
            identity: identity,
            chain: import
                .cert_chain
                .unwrap_or(vec![])
                .into_iter()
                .filter(|c| c.to_der() != identity_cert)
                .collect(),
        })
    }

    #[cfg(not(target_os = "ios"))]
    fn import_options(buf: &[u8], pass: &str) -> Result<Vec<ImportedIdentityOptions>, Error> {
        SET_AT_EXIT.call_once(|| {
            extern "C" fn atexit() {
                *TEMP_KEYCHAIN.lock().unwrap() = None;
            }
            unsafe {
                libc::atexit(atexit);
            }
        });

        let keychain = match *TEMP_KEYCHAIN.lock().unwrap() {
            Some((ref keychain, _)) => keychain.clone(),
            ref mut lock @ None => {
                let dir = TempDir::new("native-tls").map_err(|_| {
                    Error(base::Error::from(errSecIO))
                })?;

                let mut keychain = keychain::CreateOptions::new().password(pass).create(
                    dir.path().join("tmp.keychain"),
                )?;
                keychain.set_settings(&KeychainSettings::new())?;

                *lock = Some((keychain, dir));
                lock.as_ref().unwrap().0.clone()
            }
        };
        let imports = try!(
            Pkcs12ImportOptions::new()
                .passphrase(pass)
                .keychain(keychain)
                .import_optional(buf)
        );
        Ok(imports)
    }

    #[cfg(target_os = "ios")]
    fn import_options(buf: &[u8], pass: &str) -> Result<Vec<ImportedIdentityOptions>, Error> {
        let imports = try!(
            Pkcs12ImportOptions::new()
                .passphrase(pass)
                .import_optional(buf)
        );
        Ok(imports)
    }
}

pub struct Certificate(SecCertificate);

impl Certificate {
    pub fn from_der(buf: &[u8]) -> Result<Certificate, Error> {
        let cert = try!(SecCertificate::from_der(buf));
        Ok(Certificate(cert))
    }

    pub fn from_pem(buf: &[u8]) -> Result<Certificate, Error> {
        let mut items = SecItems::default();
        try!(ImportOptions::new().items(&mut items).import(buf));
        match items.certificates.pop() {
            Some(cert) => Ok(Certificate(cert)),
            None => Err(Error(base::Error::from_code(0))),
        }
    }
}

pub enum HandshakeError<S> {
    Interrupted(MidHandshakeTlsStream<S>),
    Failure(Error),
}

impl<S> From<secure_transport::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream::Server(s))
            }
        }
    }
}

impl<S> From<secure_transport::ClientHandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::ClientHandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::ClientHandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::ClientHandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream::Client(s))
            }
        }
    }
}

impl<S> From<base::Error> for HandshakeError<S> {
    fn from(e: base::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub enum MidHandshakeTlsStream<S> {
    Server(secure_transport::MidHandshakeSslStream<S>),
    Client(secure_transport::MidHandshakeClientBuilder<S>),
}

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
where
    S: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MidHandshakeTlsStream::Server(ref s) => s.fmt(fmt),
            MidHandshakeTlsStream::Client(ref s) => s.fmt(fmt),
        }
    }
}

impl<S> MidHandshakeTlsStream<S>
where
    S: io::Read + io::Write,
{
    pub fn get_ref(&self) -> &S {
        match *self {
            MidHandshakeTlsStream::Server(ref s) => s.get_ref(),
            MidHandshakeTlsStream::Client(ref s) => s.get_ref(),
        }
    }

    pub fn get_mut(&mut self) -> &mut S {
        match *self {
            MidHandshakeTlsStream::Server(ref mut s) => s.get_mut(),
            MidHandshakeTlsStream::Client(ref mut s) => s.get_mut(),
        }
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self {
            MidHandshakeTlsStream::Server(s) => {
                match s.handshake() {
                    Ok(s) => Ok(TlsStream(s)),
                    Err(e) => Err(e.into()),
                }
            }
            MidHandshakeTlsStream::Client(s) => {
                match s.handshake() {
                    Ok(s) => Ok(TlsStream(s)),
                    Err(e) => Err(e.into()),
                }
            }
        }
    }
}

pub struct TlsConnectorBuilder(TlsConnector);

impl TlsConnectorBuilder {
    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        self.0.pkcs12 = Some(pkcs12);
        Ok(())
    }

    pub fn add_root_certificate(&mut self, cert: Certificate) -> Result<(), Error> {
        self.0.roots.push(cert.0);
        Ok(())
    }

    pub fn supported_protocols(&mut self, protocols: &[Protocol]) -> Result<(), Error> {
        self.0.protocols = protocols.to_vec();
        Ok(())
    }

    pub fn build(self) -> Result<TlsConnector, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsConnector {
    pkcs12: Option<Pkcs12>,
    protocols: Vec<Protocol>,
    roots: Vec<SecCertificate>,
}

impl TlsConnector {
    pub fn builder() -> Result<TlsConnectorBuilder, Error> {
        Ok(TlsConnectorBuilder(TlsConnector {
            pkcs12: None,
            protocols: vec![Protocol::Tlsv10, Protocol::Tlsv11, Protocol::Tlsv12],
            roots: vec![],
        }))
    }

    pub fn connect<S>(&self, domain: &str, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self.connect_inner(Some(domain), stream)
    }

    pub fn connect_no_domain<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self.connect_inner(None, stream)
    }

    fn connect_inner<S>(
        &self,
        domain: Option<&str>,
        stream: S,
    ) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = ClientBuilder::new();
        let (min, max) = protocol_min_max(&self.protocols);
        builder.protocol_min(min);
        builder.protocol_max(max);
        if let Some(pkcs12) = self.pkcs12.as_ref() {
            builder.identity(&pkcs12.identity, &pkcs12.chain);
        }
        builder.anchor_certificates(&self.roots);

        let r = match domain {
            Some(domain) => builder.handshake2(domain, stream),
            None => builder.danger_handshake_without_providing_domain_for_certificate_validation_and_server_name_indication(stream),
        };
        match r {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsAcceptorBuilder(TlsAcceptor);

impl TlsAcceptorBuilder {
    pub fn supported_protocols(&mut self, protocols: &[Protocol]) -> Result<(), Error> {
        self.0.protocols = protocols.to_vec();
        Ok(())
    }

    pub fn build(self) -> Result<TlsAcceptor, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsAcceptor {
    pkcs12: Pkcs12,
    protocols: Vec<Protocol>,
}

impl TlsAcceptor {
    pub fn builder(pkcs12: Pkcs12) -> Result<TlsAcceptorBuilder, Error> {
        Ok(TlsAcceptorBuilder(TlsAcceptor {
            pkcs12: pkcs12,
            protocols: vec![Protocol::Tlsv10, Protocol::Tlsv11, Protocol::Tlsv12],
        }))
    }

    pub fn accept<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut ctx = try!(SslContext::new(
            ProtocolSide::Server,
            ConnectionType::Stream,
        ));

        let (min, max) = protocol_min_max(&self.protocols);
        try!(ctx.set_protocol_version_min(min));
        try!(ctx.set_protocol_version_max(max));
        try!(ctx.set_certificate(
            &self.pkcs12.identity,
            &self.pkcs12.chain,
        ));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(secure_transport::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(try!(self.0.context().buffered_read_size()))
    }

    pub fn shutdown(&mut self) -> io::Result<()> {
        try!(self.0.close());
        Ok(())
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// Security Framework-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the Security Framework `SslStream`.
    fn raw_stream(&self) -> &secure_transport::SslStream<S>;

    /// Returns a mutable reference to the Security Framework `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &secure_transport::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S> {
        &mut (self.0).0
    }
}

/// Security Framework-specific extensions to `TlsConnectorBuilder`.
pub trait TlsConnectorBuilderExt {
    /// Deprecated
    #[deprecated(since = "0.1.2", note = "use add_root_certificate")]
    fn anchor_certificates(&mut self, certs: &[SecCertificate]) -> &mut Self;
}

impl TlsConnectorBuilderExt for ::TlsConnectorBuilder {
    fn anchor_certificates(&mut self, certs: &[SecCertificate]) -> &mut Self {
        (self.0).0.roots = certs.to_owned();
        self
    }
}

/// Security Framework-specific extensions to `Error`
pub trait ErrorExt {
    /// Extract the underlying Security Framework error for inspection.
    fn security_framework_error(&self) -> &base::Error;
}

impl ErrorExt for ::Error {
    fn security_framework_error(&self) -> &base::Error {
        &(self.0).0
    }
}
<commit_msg>Fix security-framework error for missing PEM cert<commit_after>extern crate libc;
extern crate security_framework;
extern crate security_framework_sys;
extern crate tempdir;

use self::security_framework::base;
use self::security_framework::certificate::SecCertificate;
use self::security_framework::identity::SecIdentity;
use self::security_framework::import_export::{Pkcs12ImportOptions, ImportedIdentityOptions};
use self::security_framework::secure_transport::{self, SslContext, ProtocolSide, ConnectionType,
                                                 SslProtocol, ClientBuilder};
use self::security_framework_sys::base::errSecIO;
use self::security_framework_sys::base::errSecParam;
use self::tempdir::TempDir;
use std::fmt;
use std::io;
use std::error;
use std::sync::Mutex;
use std::sync::{Once, ONCE_INIT};

#[cfg(not(target_os = "ios"))]
use self::security_framework::os::macos::keychain::{self, SecKeychain, KeychainSettings};
use self::security_framework::os::macos::import_export::{SecItems, ImportOptions};

use Protocol;

static SET_AT_EXIT: Once = ONCE_INIT;

#[cfg(not(target_os = "ios"))]
lazy_static! {
    static ref TEMP_KEYCHAIN: Mutex<Option<(SecKeychain, TempDir)>> = Mutex::new(None);
}

fn convert_protocol(protocol: Protocol) -> SslProtocol {
    match protocol {
        Protocol::Sslv3 => SslProtocol::Ssl3,
        Protocol::Tlsv10 => SslProtocol::Tls1,
        Protocol::Tlsv11 => SslProtocol::Tls11,
        Protocol::Tlsv12 => SslProtocol::Tls12,
        Protocol::__NonExhaustive => unreachable!(),
    }
}

fn protocol_min_max(protocols: &[Protocol]) -> (SslProtocol, SslProtocol) {
    let mut min = Protocol::Tlsv12;
    let mut max = Protocol::Sslv3;
    for protocol in protocols {
        if (*protocol as usize) < (min as usize) {
            min = *protocol;
        }
        if (*protocol as usize) > (max as usize) {
            max = *protocol;
        }
    }
    (convert_protocol(min), convert_protocol(max))
}

pub struct Error(base::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<base::Error> for Error {
    fn from(error: base::Error) -> Error {
        Error(error)
    }
}

#[derive(Clone)]
pub struct Pkcs12 {
    identity: SecIdentity,
    chain: Vec<SecCertificate>,
}

impl Pkcs12 {
    pub fn from_der(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let mut imports = try!(Pkcs12::import_options(buf, pass));
        let import = imports.pop().unwrap();

        let identity = import.identity.expect(
            "Pkcs12 files must include an identity",
        );

        // FIXME: Compare the certificates for equality using CFEqual
        let identity_cert = try!(identity.certificate()).to_der();

        Ok(Pkcs12 {
            identity: identity,
            chain: import
                .cert_chain
                .unwrap_or(vec![])
                .into_iter()
                .filter(|c| c.to_der() != identity_cert)
                .collect(),
        })
    }

    #[cfg(not(target_os = "ios"))]
    fn import_options(buf: &[u8], pass: &str) -> Result<Vec<ImportedIdentityOptions>, Error> {
        SET_AT_EXIT.call_once(|| {
            extern "C" fn atexit() {
                *TEMP_KEYCHAIN.lock().unwrap() = None;
            }
            unsafe {
                libc::atexit(atexit);
            }
        });

        let keychain = match *TEMP_KEYCHAIN.lock().unwrap() {
            Some((ref keychain, _)) => keychain.clone(),
            ref mut lock @ None => {
                let dir = TempDir::new("native-tls").map_err(|_| {
                    Error(base::Error::from(errSecIO))
                })?;

                let mut keychain = keychain::CreateOptions::new().password(pass).create(
                    dir.path().join("tmp.keychain"),
                )?;
                keychain.set_settings(&KeychainSettings::new())?;

                *lock = Some((keychain, dir));
                lock.as_ref().unwrap().0.clone()
            }
        };
        let imports = try!(
            Pkcs12ImportOptions::new()
                .passphrase(pass)
                .keychain(keychain)
                .import_optional(buf)
        );
        Ok(imports)
    }

    #[cfg(target_os = "ios")]
    fn import_options(buf: &[u8], pass: &str) -> Result<Vec<ImportedIdentityOptions>, Error> {
        let imports = try!(
            Pkcs12ImportOptions::new()
                .passphrase(pass)
                .import_optional(buf)
        );
        Ok(imports)
    }
}

pub struct Certificate(SecCertificate);

impl Certificate {
    pub fn from_der(buf: &[u8]) -> Result<Certificate, Error> {
        let cert = try!(SecCertificate::from_der(buf));
        Ok(Certificate(cert))
    }

    pub fn from_pem(buf: &[u8]) -> Result<Certificate, Error> {
        let mut items = SecItems::default();
        try!(ImportOptions::new().items(&mut items).import(buf));
        match items.certificates.pop() {
            Some(cert) => Ok(Certificate(cert)),
            None => Err(Error(base::Error::from(errSecParam))),
        }
    }
}

pub enum HandshakeError<S> {
    Interrupted(MidHandshakeTlsStream<S>),
    Failure(Error),
}

impl<S> From<secure_transport::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream::Server(s))
            }
        }
    }
}

impl<S> From<secure_transport::ClientHandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::ClientHandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::ClientHandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::ClientHandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream::Client(s))
            }
        }
    }
}

impl<S> From<base::Error> for HandshakeError<S> {
    fn from(e: base::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub enum MidHandshakeTlsStream<S> {
    Server(secure_transport::MidHandshakeSslStream<S>),
    Client(secure_transport::MidHandshakeClientBuilder<S>),
}

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
where
    S: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MidHandshakeTlsStream::Server(ref s) => s.fmt(fmt),
            MidHandshakeTlsStream::Client(ref s) => s.fmt(fmt),
        }
    }
}

impl<S> MidHandshakeTlsStream<S>
where
    S: io::Read + io::Write,
{
    pub fn get_ref(&self) -> &S {
        match *self {
            MidHandshakeTlsStream::Server(ref s) => s.get_ref(),
            MidHandshakeTlsStream::Client(ref s) => s.get_ref(),
        }
    }

    pub fn get_mut(&mut self) -> &mut S {
        match *self {
            MidHandshakeTlsStream::Server(ref mut s) => s.get_mut(),
            MidHandshakeTlsStream::Client(ref mut s) => s.get_mut(),
        }
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self {
            MidHandshakeTlsStream::Server(s) => {
                match s.handshake() {
                    Ok(s) => Ok(TlsStream(s)),
                    Err(e) => Err(e.into()),
                }
            }
            MidHandshakeTlsStream::Client(s) => {
                match s.handshake() {
                    Ok(s) => Ok(TlsStream(s)),
                    Err(e) => Err(e.into()),
                }
            }
        }
    }
}

pub struct TlsConnectorBuilder(TlsConnector);

impl TlsConnectorBuilder {
    pub fn identity(&mut self, pkcs12: Pkcs12) -> Result<(), Error> {
        self.0.pkcs12 = Some(pkcs12);
        Ok(())
    }

    pub fn add_root_certificate(&mut self, cert: Certificate) -> Result<(), Error> {
        self.0.roots.push(cert.0);
        Ok(())
    }

    pub fn supported_protocols(&mut self, protocols: &[Protocol]) -> Result<(), Error> {
        self.0.protocols = protocols.to_vec();
        Ok(())
    }

    pub fn build(self) -> Result<TlsConnector, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsConnector {
    pkcs12: Option<Pkcs12>,
    protocols: Vec<Protocol>,
    roots: Vec<SecCertificate>,
}

impl TlsConnector {
    pub fn builder() -> Result<TlsConnectorBuilder, Error> {
        Ok(TlsConnectorBuilder(TlsConnector {
            pkcs12: None,
            protocols: vec![Protocol::Tlsv10, Protocol::Tlsv11, Protocol::Tlsv12],
            roots: vec![],
        }))
    }

    pub fn connect<S>(&self, domain: &str, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self.connect_inner(Some(domain), stream)
    }

    pub fn connect_no_domain<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        self.connect_inner(None, stream)
    }

    fn connect_inner<S>(
        &self,
        domain: Option<&str>,
        stream: S,
    ) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut builder = ClientBuilder::new();
        let (min, max) = protocol_min_max(&self.protocols);
        builder.protocol_min(min);
        builder.protocol_max(max);
        if let Some(pkcs12) = self.pkcs12.as_ref() {
            builder.identity(&pkcs12.identity, &pkcs12.chain);
        }
        builder.anchor_certificates(&self.roots);

        let r = match domain {
            Some(domain) => builder.handshake2(domain, stream),
            None => builder.danger_handshake_without_providing_domain_for_certificate_validation_and_server_name_indication(stream),
        };
        match r {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsAcceptorBuilder(TlsAcceptor);

impl TlsAcceptorBuilder {
    pub fn supported_protocols(&mut self, protocols: &[Protocol]) -> Result<(), Error> {
        self.0.protocols = protocols.to_vec();
        Ok(())
    }

    pub fn build(self) -> Result<TlsAcceptor, Error> {
        Ok(self.0)
    }
}

#[derive(Clone)]
pub struct TlsAcceptor {
    pkcs12: Pkcs12,
    protocols: Vec<Protocol>,
}

impl TlsAcceptor {
    pub fn builder(pkcs12: Pkcs12) -> Result<TlsAcceptorBuilder, Error> {
        Ok(TlsAcceptorBuilder(TlsAcceptor {
            pkcs12: pkcs12,
            protocols: vec![Protocol::Tlsv10, Protocol::Tlsv11, Protocol::Tlsv12],
        }))
    }

    pub fn accept<S>(&self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
    where
        S: io::Read + io::Write,
    {
        let mut ctx = try!(SslContext::new(
            ProtocolSide::Server,
            ConnectionType::Stream,
        ));

        let (min, max) = protocol_min_max(&self.protocols);
        try!(ctx.set_protocol_version_min(min));
        try!(ctx.set_protocol_version_max(max));
        try!(ctx.set_certificate(
            &self.pkcs12.identity,
            &self.pkcs12.chain,
        ));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(secure_transport::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(try!(self.0.context().buffered_read_size()))
    }

    pub fn shutdown(&mut self) -> io::Result<()> {
        try!(self.0.close());
        Ok(())
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// Security Framework-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the Security Framework `SslStream`.
    fn raw_stream(&self) -> &secure_transport::SslStream<S>;

    /// Returns a mutable reference to the Security Framework `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &secure_transport::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S> {
        &mut (self.0).0
    }
}

/// Security Framework-specific extensions to `TlsConnectorBuilder`.
pub trait TlsConnectorBuilderExt {
    /// Deprecated
    #[deprecated(since = "0.1.2", note = "use add_root_certificate")]
    fn anchor_certificates(&mut self, certs: &[SecCertificate]) -> &mut Self;
}

impl TlsConnectorBuilderExt for ::TlsConnectorBuilder {
    fn anchor_certificates(&mut self, certs: &[SecCertificate]) -> &mut Self {
        (self.0).0.roots = certs.to_owned();
        self
    }
}

/// Security Framework-specific extensions to `Error`
pub trait ErrorExt {
    /// Extract the underlying Security Framework error for inspection.
    fn security_framework_error(&self) -> &base::Error;
}

impl ErrorExt for ::Error {
    fn security_framework_error(&self) -> &base::Error {
        &(self.0).0
    }
}
<|endoftext|>