<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Input / output.

/// Copies data from `src` to `dst`.
///
/// Panics if the length of `dst` is less than the length of `src`.
///
/// This implementation is copied from ::std::slice::bytes::copy_memory(),
/// which is marked as 'unstable' at the time of this writing.
#[inline]
pub fn copy_memory(src: &[u8], dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    // `dst` is unaliasable, so we know statically it doesn't overlap
    // with `src`.
    unsafe {
        ::std::ptr::copy_nonoverlapping(src.as_ptr(),
                                        dst.as_mut_ptr(),
                                        len_src);
    }
}

/// A producer of bytes.
pub trait InputStream {
    /// Reads at least `min_bytes` into `buf` unless EOF is encountered first. Returns the
    /// number of bytes read.
    fn try_read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize>;

    /// Reads at least `min_bytes` into `buf`, returning the number of bytes read. If EOF is
    /// encountered first, returns an error.
    fn read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize> {
        let n = try!(self.try_read(buf, min_bytes));
        if n < min_bytes {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
        } else {
            Ok(n)
        }
    }

    /// Reads into `buf` until it is full. Returns an error if EOF is encountered first.
    fn read_exact(&mut self, buf : &mut [u8]) -> ::std::io::Result<()> {
        let min_bytes = buf.len();
        try!(self.read(buf, min_bytes));
        Ok(())
    }
}

impl <R> InputStream for R where R : ::std::io::Read {
    fn try_read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize> {
        let mut pos = 0;
        while pos < min_bytes {
            let buf1 = &mut buf[pos ..];
            match self.read(buf1) {
                Ok(n) => {
                    pos += n;
                    if n == 0 { return Ok(pos); }
                }
                Err(e) => {
                    if e.kind() != ::std::io::ErrorKind::Interrupted {
                        return Err(e);
                    }
                    // Retry if we were interrupted.
                }
            }
        }
        return Ok(pos);
    }
}

pub trait BufferedInputStream : InputStream {
    fn skip(&mut self, bytes : usize) -> ::std::io::Result<()>;
    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)>;
}

pub struct BufferedInputStreamWrapper<R> {
    inner : R,
    buf : Vec<u8>,
    pos : usize,
    cap : usize
}

impl <R> BufferedInputStreamWrapper<R> {
    pub fn new(r : R) -> BufferedInputStreamWrapper<R> {
        let mut result = BufferedInputStreamWrapper {
            inner : r,
            buf : Vec::with_capacity(8192),
            pos : 0,
            cap : 0
        };
        unsafe {
            result.buf.set_len(8192)
        }
        return result;
    }
}

impl<R: InputStream> BufferedInputStream for BufferedInputStreamWrapper<R> {

   fn skip(&mut self, mut bytes : usize) -> ::std::io::Result<()> {
        let available = self.cap - self.pos;
        if bytes <= available {
            self.pos += bytes;
        } else {
            bytes -= available;
            if bytes <= self.buf.len() {
                //# Read the next buffer-full.
                let n = try!(self.inner.try_read(&mut self.buf[..], bytes));
                self.pos = bytes;
                self.cap = n;
            } else {
                //# Forward large skip to the underlying stream.
                panic!("TODO")
            }
        }
        Ok(())
    }

    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)> {
        if self.cap - self.pos == 0 {
            let n = try!(self.inner.try_read(&mut self.buf[..], 1));
            self.cap = n;
            self.pos = 0;
        }
        Ok((self.buf.get_unchecked(self.pos), self.buf.get_unchecked(self.cap)))
    }
}

impl<R: InputStream> InputStream for BufferedInputStreamWrapper<R> {
    fn try_read(&mut self, mut dst: &mut [u8], mut min_bytes : usize) -> ::std::io::Result<usize> {
        if min_bytes <= self.cap - self.pos {
            // Serve from the current buffer.
            let n = ::std::cmp::min(self.cap - self.pos, dst.len());
            copy_memory(&self.buf[self.pos .. self.pos + n], dst);
            self.pos += n;
            return Ok(n);
        } else {
            // Copy current available into destination.
            copy_memory(&self.buf[self.pos .. self.cap], dst);
            let from_first_buffer = self.cap - self.pos;

            let dst = &mut dst[from_first_buffer ..];
            min_bytes -= from_first_buffer;

            if dst.len() <= self.buf.len() {
                // Read the next buffer-full.
                let n = try!(self.inner.try_read(&mut self.buf[..], min_bytes));
                let from_second_buffer = ::std::cmp::min(n, dst.len());
                copy_memory(&self.buf[0 .. from_second_buffer], dst);
                self.cap = n;
                self.pos = from_second_buffer;
                return Ok(from_first_buffer + from_second_buffer);
            } else {
                // Forward large read to the underlying stream.
                self.pos = 0;
                self.cap = 0;
                return Ok(from_first_buffer + try!(self.inner.try_read(dst, min_bytes)));
            }
        }
    }
}

pub struct ArrayInputStream<'a> {
    array : &'a [u8]
}

impl <'a> ArrayInputStream<'a> {
    pub fn new<'b>(array : &'b [u8]) -> ArrayInputStream<'b> {
        ArrayInputStream { array : array }
    }
}

impl <'a> InputStream for ArrayInputStream<'a> {
    fn try_read(&mut self, dst: &mut [u8], _min_bytes : usize) -> ::std::io::Result<usize> {
        let n = ::std::cmp::min(dst.len(), self.array.len());
        copy_memory(&self.array[0 .. n], dst);
        self.array = &self.array[n ..];
        Ok(n)
    }
}

impl <'a> BufferedInputStream for ArrayInputStream<'a> {
    fn skip(&mut self, bytes : usize) -> ::std::io::Result<()> {
        assert!(self.array.len() >= bytes,
                "ArrayInputStream ended prematurely.");
        self.array = &self.array[bytes ..];
        Ok(())
    }
    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)> {
        let len = self.array.len();
        Ok((self.array.as_ptr(), self.array.get_unchecked(len)))
    }
}

/// A consumer of bytes.
pub trait OutputStream {
    /// Writes all of `buf`.
    fn write(&mut self, buf : &[u8]) -> ::std::io::Result<()>;
    fn flush(&mut self) -> ::std::io::Result<()> { Ok(()) }
}

impl <W> OutputStream for W where W : ::std::io::Write {
    fn write(&mut self, buf : &[u8]) -> ::std::io::Result<()> {
        self.write_all(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        self.flush()
    }
}

pub trait BufferedOutputStream : OutputStream {
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8);
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()>;
}

pub struct BufferedOutputStreamWrapper<'a, W:'a> {
    inner: &'a mut W,
    buf: Vec<u8>,
    pos: usize
}

impl <'a, W> BufferedOutputStreamWrapper<'a, W> {
    pub fn new<'b> (w : &'b mut W) -> BufferedOutputStreamWrapper<W> {
        let mut result = BufferedOutputStreamWrapper {
            inner: w,
            buf : Vec::with_capacity(8192),
            pos : 0
        };
        unsafe {
            result.buf.set_len(8192);
        }
        return result;
    }
}

impl<'a, W: OutputStream> BufferedOutputStream for BufferedOutputStreamWrapper<'a, W> {
    #[inline]
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8) {
        let len = self.buf.len();
        (self.buf.get_unchecked_mut(self.pos),
         self.buf.get_unchecked_mut(len))
    }

    #[inline]
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()> {
        let pos_ptr : *mut u8 = self.buf.get_unchecked_mut(self.pos);
        if ptr == pos_ptr { // easy case
            self.pos += size;
            Ok(())
        } else {
            let buf = ::std::slice::from_raw_parts_mut::<u8>(ptr, size);
            self.write(buf)
        }
    }

}

impl<'a, W: OutputStream> OutputStream for BufferedOutputStreamWrapper<'a, W> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
        let available = self.buf.len() - self.pos;
        let mut size = buf.len();
        if size <= available {
            let dst = &mut self.buf[self.pos ..];
            copy_memory(buf, dst);
            self.pos += size;
        } else if size <= self.buf.len() {
            // Too much for this buffer, but not a full buffer's
            // worth, so we'll go ahead and copy.
            {
                let dst = &mut self.buf[self.pos ..];
                copy_memory(&buf[0 .. available], dst);
            }
            try!(self.inner.write(&mut self.buf[..]));

            size -= available;
            let src = &buf[available ..];
            let dst = &mut self.buf[0 ..];
            copy_memory(src, dst);
            self.pos = size;
        } else {
            // Writing so much data that we might as well write
            // directly to avoid a copy.
            try!(self.inner.write(&self.buf[0 .. self.pos]));
            self.pos = 0;
            try!(self.inner.write(buf));
        }
        return Ok(());
    }

    fn flush(&mut self) -> ::std::io::Result<()> {
        if self.pos > 0 {
            try!(self.inner.write(&self.buf[0 .. self.pos]));
            self.pos = 0;
        }
        self.inner.flush()
    }
}

pub struct ArrayOutputStream<'a> {
    array : &'a mut [u8],
    fill_pos : usize,
}

impl <'a> ArrayOutputStream<'a> {
    pub fn new<'b>(array : &'b mut [u8]) -> ArrayOutputStream<'b> {
        ArrayOutputStream {
            array : array,
            fill_pos : 0
        }
    }
}

impl <'a> OutputStream for ArrayOutputStream<'a> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
        assert!(buf.len() <= self.array.len() - self.fill_pos,
                "ArrayOutputStream's backing array was not large enough for the data written.");
        copy_memory(buf, &mut self.array[self.fill_pos ..]);
        self.fill_pos += buf.len();
        Ok(())
    }
}

impl <'a> BufferedOutputStream for ArrayOutputStream<'a> {
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8) {
        let len = self.array.len();
        (self.array.get_unchecked_mut(self.fill_pos),
         self.array.get_unchecked_mut(len))
    }
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()> {
        let fill_ptr : *mut u8 = self.array.get_unchecked_mut(self.fill_pos);
        if ptr == fill_ptr { // easy case
            self.fill_pos += size;
            Ok(())
        } else {
            let buf = ::std::slice::from_raw_parts_mut::<u8>(ptr, size);
            self.write(buf)
        }
    }
}
<commit_msg>copy_memory() should not be public<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Input / output.

/// Copies data from `src` to `dst`.
///
/// Panics if the length of `dst` is less than the length of `src`.
///
/// This implementation is copied from ::std::slice::bytes::copy_memory(),
/// which is marked as 'unstable' at the time of this writing.
#[inline]
fn copy_memory(src: &[u8], dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    // `dst` is unaliasable, so we know statically it doesn't overlap
    // with `src`.
    unsafe {
        ::std::ptr::copy_nonoverlapping(src.as_ptr(),
                                        dst.as_mut_ptr(),
                                        len_src);
    }
}

/// A producer of bytes.
pub trait InputStream {
    /// Reads at least `min_bytes` into `buf` unless EOF is encountered first. Returns the
    /// number of bytes read.
    fn try_read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize>;

    /// Reads at least `min_bytes` into `buf`, returning the number of bytes read. If EOF is
    /// encountered first, returns an error.
    fn read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize> {
        let n = try!(self.try_read(buf, min_bytes));
        if n < min_bytes {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
        } else {
            Ok(n)
        }
    }

    /// Reads into `buf` until it is full. Returns an error if EOF is encountered first.
    fn read_exact(&mut self, buf : &mut [u8]) -> ::std::io::Result<()> {
        let min_bytes = buf.len();
        try!(self.read(buf, min_bytes));
        Ok(())
    }
}

impl <R> InputStream for R where R : ::std::io::Read {
    fn try_read(&mut self, buf : &mut [u8], min_bytes : usize) -> ::std::io::Result<usize> {
        let mut pos = 0;
        while pos < min_bytes {
            let buf1 = &mut buf[pos ..];
            match self.read(buf1) {
                Ok(n) => {
                    pos += n;
                    if n == 0 { return Ok(pos); }
                }
                Err(e) => {
                    if e.kind() != ::std::io::ErrorKind::Interrupted {
                        return Err(e);
                    }
                    // Retry if we were interrupted.
                }
            }
        }
        return Ok(pos);
    }
}

pub trait BufferedInputStream : InputStream {
    fn skip(&mut self, bytes : usize) -> ::std::io::Result<()>;
    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)>;
}

pub struct BufferedInputStreamWrapper<R> {
    inner : R,
    buf : Vec<u8>,
    pos : usize,
    cap : usize
}

impl <R> BufferedInputStreamWrapper<R> {
    pub fn new(r : R) -> BufferedInputStreamWrapper<R> {
        let mut result = BufferedInputStreamWrapper {
            inner : r,
            buf : Vec::with_capacity(8192),
            pos : 0,
            cap : 0
        };
        unsafe {
            result.buf.set_len(8192)
        }
        return result;
    }
}

impl<R: InputStream> BufferedInputStream for BufferedInputStreamWrapper<R> {

   fn skip(&mut self, mut bytes : usize) -> ::std::io::Result<()> {
        let available = self.cap - self.pos;
        if bytes <= available {
            self.pos += bytes;
        } else {
            bytes -= available;
            if bytes <= self.buf.len() {
                //# Read the next buffer-full.
                let n = try!(self.inner.try_read(&mut self.buf[..], bytes));
                self.pos = bytes;
                self.cap = n;
            } else {
                //# Forward large skip to the underlying stream.
                panic!("TODO")
            }
        }
        Ok(())
    }

    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)> {
        if self.cap - self.pos == 0 {
            let n = try!(self.inner.try_read(&mut self.buf[..], 1));
            self.cap = n;
            self.pos = 0;
        }
        Ok((self.buf.get_unchecked(self.pos), self.buf.get_unchecked(self.cap)))
    }
}

impl<R: InputStream> InputStream for BufferedInputStreamWrapper<R> {
    fn try_read(&mut self, mut dst: &mut [u8], mut min_bytes : usize) -> ::std::io::Result<usize> {
        if min_bytes <= self.cap - self.pos {
            // Serve from the current buffer.
            let n = ::std::cmp::min(self.cap - self.pos, dst.len());
            copy_memory(&self.buf[self.pos .. self.pos + n], dst);
            self.pos += n;
            return Ok(n);
        } else {
            // Copy current available into destination.
            copy_memory(&self.buf[self.pos .. self.cap], dst);
            let from_first_buffer = self.cap - self.pos;

            let dst = &mut dst[from_first_buffer ..];
            min_bytes -= from_first_buffer;

            if dst.len() <= self.buf.len() {
                // Read the next buffer-full.
                let n = try!(self.inner.try_read(&mut self.buf[..], min_bytes));
                let from_second_buffer = ::std::cmp::min(n, dst.len());
                copy_memory(&self.buf[0 .. from_second_buffer], dst);
                self.cap = n;
                self.pos = from_second_buffer;
                return Ok(from_first_buffer + from_second_buffer);
            } else {
                // Forward large read to the underlying stream.
                self.pos = 0;
                self.cap = 0;
                return Ok(from_first_buffer + try!(self.inner.try_read(dst, min_bytes)));
            }
        }
    }
}

pub struct ArrayInputStream<'a> {
    array : &'a [u8]
}

impl <'a> ArrayInputStream<'a> {
    pub fn new<'b>(array : &'b [u8]) -> ArrayInputStream<'b> {
        ArrayInputStream { array : array }
    }
}

impl <'a> InputStream for ArrayInputStream<'a> {
    fn try_read(&mut self, dst: &mut [u8], _min_bytes : usize) -> ::std::io::Result<usize> {
        let n = ::std::cmp::min(dst.len(), self.array.len());
        copy_memory(&self.array[0 .. n], dst);
        self.array = &self.array[n ..];
        Ok(n)
    }
}

impl <'a> BufferedInputStream for ArrayInputStream<'a> {
    fn skip(&mut self, bytes : usize) -> ::std::io::Result<()> {
        assert!(self.array.len() >= bytes,
                "ArrayInputStream ended prematurely.");
        self.array = &self.array[bytes ..];
        Ok(())
    }
    unsafe fn get_read_buffer(&mut self) -> ::std::io::Result<(*const u8, *const u8)> {
        let len = self.array.len();
        Ok((self.array.as_ptr(), self.array.get_unchecked(len)))
    }
}

/// A consumer of bytes.
pub trait OutputStream {
    /// Writes all of `buf`.
    fn write(&mut self, buf : &[u8]) -> ::std::io::Result<()>;
    fn flush(&mut self) -> ::std::io::Result<()> { Ok(()) }
}

impl <W> OutputStream for W where W : ::std::io::Write {
    fn write(&mut self, buf : &[u8]) -> ::std::io::Result<()> {
        self.write_all(buf)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        self.flush()
    }
}

pub trait BufferedOutputStream : OutputStream {
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8);
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()>;
}

pub struct BufferedOutputStreamWrapper<'a, W:'a> {
    inner: &'a mut W,
    buf: Vec<u8>,
    pos: usize
}

impl <'a, W> BufferedOutputStreamWrapper<'a, W> {
    pub fn new<'b> (w : &'b mut W) -> BufferedOutputStreamWrapper<W> {
        let mut result = BufferedOutputStreamWrapper {
            inner: w,
            buf : Vec::with_capacity(8192),
            pos : 0
        };
        unsafe {
            result.buf.set_len(8192);
        }
        return result;
    }
}

impl<'a, W: OutputStream> BufferedOutputStream for BufferedOutputStreamWrapper<'a, W> {
    #[inline]
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8) {
        let len = self.buf.len();
        (self.buf.get_unchecked_mut(self.pos),
         self.buf.get_unchecked_mut(len))
    }

    #[inline]
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()> {
        let pos_ptr : *mut u8 = self.buf.get_unchecked_mut(self.pos);
        if ptr == pos_ptr { // easy case
            self.pos += size;
            Ok(())
        } else {
            let buf = ::std::slice::from_raw_parts_mut::<u8>(ptr, size);
            self.write(buf)
        }
    }

}

impl<'a, W: OutputStream> OutputStream for BufferedOutputStreamWrapper<'a, W> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
        let available = self.buf.len() - self.pos;
        let mut size = buf.len();
        if size <= available {
            let dst = &mut self.buf[self.pos ..];
            copy_memory(buf, dst);
            self.pos += size;
        } else if size <= self.buf.len() {
            // Too much for this buffer, but not a full buffer's
            // worth, so we'll go ahead and copy.
            {
                let dst = &mut self.buf[self.pos ..];
                copy_memory(&buf[0 .. available], dst);
            }
            try!(self.inner.write(&mut self.buf[..]));

            size -= available;
            let src = &buf[available ..];
            let dst = &mut self.buf[0 ..];
            copy_memory(src, dst);
            self.pos = size;
        } else {
            // Writing so much data that we might as well write
            // directly to avoid a copy.
            try!(self.inner.write(&self.buf[0 .. self.pos]));
            self.pos = 0;
            try!(self.inner.write(buf));
        }
        return Ok(());
    }

    fn flush(&mut self) -> ::std::io::Result<()> {
        if self.pos > 0 {
            try!(self.inner.write(&self.buf[0 .. self.pos]));
            self.pos = 0;
        }
        self.inner.flush()
    }
}

pub struct ArrayOutputStream<'a> {
    array : &'a mut [u8],
    fill_pos : usize,
}

impl <'a> ArrayOutputStream<'a> {
    pub fn new<'b>(array : &'b mut [u8]) -> ArrayOutputStream<'b> {
        ArrayOutputStream {
            array : array,
            fill_pos : 0
        }
    }
}

impl <'a> OutputStream for ArrayOutputStream<'a> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
        assert!(buf.len() <= self.array.len() - self.fill_pos,
                "ArrayOutputStream's backing array was not large enough for the data written.");
        copy_memory(buf, &mut self.array[self.fill_pos ..]);
        self.fill_pos += buf.len();
        Ok(())
    }
}

impl <'a> BufferedOutputStream for ArrayOutputStream<'a> {
    unsafe fn get_write_buffer(&mut self) -> (*mut u8, *mut u8) {
        let len = self.array.len();
        (self.array.get_unchecked_mut(self.fill_pos),
         self.array.get_unchecked_mut(len))
    }
    unsafe fn write_ptr(&mut self, ptr: *mut u8, size: usize) -> ::std::io::Result<()> {
        let fill_ptr : *mut u8 = self.array.get_unchecked_mut(self.fill_pos);
        if ptr == fill_ptr { // easy case
            self.fill_pos += size;
            Ok(())
        } else {
            let buf = ::std::slice::from_raw_parts_mut::<u8>(ptr, size);
            self.write(buf)
        }
    }
}
<|endoftext|>


<commit_before>use std::{env, fs, io};

fn main() {
    let git_sha = read_git_sha().unwrap();
    println!("cargo:rustc-env={}={}", "BUILD_SHA", git_sha);

    println!(
        "cargo:rustc-env=BUILD_TARGET={}",
        std::env::var("TARGET").unwrap()
    );
}

fn read_git_sha() -> io::Result<String> {
    let git_path = env::current_dir().unwrap().parent().unwrap().join(".git");
    let git_head_path = git_path.join("HEAD");
    println!("cargo:rerun-if-changed={}", git_head_path.to_str().unwrap());
    let mut head_content = fs::read_to_string(&git_head_path)?;
    assert!(head_content.ends_with("\n"));
    head_content.pop();

    if head_content.starts_with("ref: ") {
        // We're on a branch. Read the SHA from the ref file.
        head_content.replace_range(0.."ref: ".len(), "");
        let ref_filename = git_path.join(&head_content);
        println!("cargo:rerun-if-changed={}", ref_filename.to_str().unwrap());
        fs::read_to_string(&ref_filename)
    } else {
        // We're not on a branch. The `HEAD` file itself contains the sha.
        assert_eq!(head_content.len(), 40);
        Ok(head_content)
    }
}
<commit_msg>Don't rely on PWD to find .git folder in build script<commit_after>use std::path::PathBuf;
use std::{env, fs, io};

fn main() {
    let git_sha = read_git_sha().unwrap();
    println!("cargo:rustc-env={}={}", "BUILD_SHA", git_sha);

    println!(
        "cargo:rustc-env=BUILD_TARGET={}",
        std::env::var("TARGET").unwrap()
    );
}

fn read_git_sha() -> io::Result<String> {
    let mut repo_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    let mut git_path;
    loop {
        git_path = repo_path.join(".git");
        if git_path.exists() {
            break;
        } else {
            assert!(repo_path.pop());
        }
    }
    let git_head_path = git_path.join("HEAD");
    println!("cargo:rerun-if-changed={}", git_head_path.to_str().unwrap());
    let mut head_content = fs::read_to_string(&git_head_path)?;
    assert!(head_content.ends_with("\n"));
    head_content.pop();

    if head_content.starts_with("ref: ") {
        // We're on a branch. Read the SHA from the ref file.
        head_content.replace_range(0.."ref: ".len(), "");
        let ref_filename = git_path.join(&head_content);
        println!("cargo:rerun-if-changed={}", ref_filename.to_str().unwrap());
        fs::read_to_string(&ref_filename)
    } else {
        // We're not on a branch. The `HEAD` file itself contains the sha.
        assert_eq!(head_content.len(), 40);
        Ok(head_content)
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::Path;

fn main() {
    println!("cargo:rustc-link-lib=indy");
    println!("cargo:rustc-link-lib=sodium");

    let target = env::var("TARGET").unwrap();
    println!("target={}", target);

    match target.find("-windows-") {
        Some(..) => {
            println!("cargo:rustc-link-lib=ssleay32");

            // TODO: FIXME: Provide more reliable dependencies resolving
            let output_dir = env::var("OUT_DIR").unwrap();
            let prebuilt_dir = env::var("INDY_DIR").unwrap();

            let dst = Path::new(&output_dir[..]).join("..\\..\\..");
            let prebuilt_lib = Path::new(&prebuilt_dir[..]).join("lib");

            println!("cargo:rustc-link-search=native={}", prebuilt_dir);
            println!("cargo:rustc-flags=-L {}/lib", prebuilt_dir);
            println!("cargo:include={}/include", prebuilt_dir);

            let files = vec!["indy.dll", "libeay32md.dll", "libsodium.dll", "libzmq-pw.dll", "ssleay32md.dll"];
            for f in files.iter() {
                if let Ok(_) = fs::copy(&prebuilt_lib.join(f), &dst.join(f)) {
                    println!("copy {} -> {}", &prebuilt_lib.join(f).display(), &dst.join(f).display());
                }
            }
            return;
        }
        None => {
            println!("cargo:rustc-link-lib=ssl");
        }
    }
}
<commit_msg>Try update build.rs file<commit_after>use std::env;
use std::fs;
use std::path::Path;

fn main() {
    println!("cargo:rustc-link-lib=indy");

    let target = env::var("TARGET").unwrap();
    println!("target={}", target);

    match target.find("-windows-") {
        Some(..) => {
            println!("cargo:rustc-link-lib=ssleay32");

            // TODO: FIXME: Provide more reliable dependencies resolving
            let output_dir = env::var("OUT_DIR").unwrap();
            let prebuilt_dir = env::var("INDY_DIR").unwrap();

            let dst = Path::new(&output_dir[..]).join("..\\..\\..");
            let prebuilt_lib = Path::new(&prebuilt_dir[..]).join("lib");

            println!("cargo:rustc-link-search=native={}", prebuilt_dir);
            println!("cargo:rustc-flags=-L {}/lib", prebuilt_dir);
            println!("cargo:include={}/include", prebuilt_dir);

            let files = vec!["indy.dll", "libeay32md.dll", "libsodium.dll", "libzmq-pw.dll", "ssleay32md.dll"];
            for f in files.iter() {
                if let Ok(_) = fs::copy(&prebuilt_lib.join(f), &dst.join(f)) {
                    println!("copy {} -> {}", &prebuilt_lib.join(f).display(), &dst.join(f).display());
                }
            }
            return;
        }
        None => {
            println!("cargo:rustc-link-lib=ssl");
        }
    }
}
<|endoftext|>


<commit_before>//! The implementation for Version 1 UUIDs.
//!
//! Note that you need feature `v1` in order to use these features.

use crate::prelude::*;
use core::sync::atomic;

/// The number of 100 ns ticks between the UUID epoch
/// `1582-10-15 00:00:00` and the Unix epoch `1970-01-01 00:00:00`.
const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;

/// A thread-safe, stateful context for the v1 generator to help ensure
/// process-wide uniqueness.
#[derive(Debug)]
pub struct Context {
    count: atomic::AtomicUsize,
}

/// Stores the number of nanoseconds from an epoch and a counter for ensuring
/// V1 ids generated on the same host are unique.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Timestamp {
    ticks: u64,
    counter: u16,
}

impl Timestamp {
    /// Construct a `Timestamp` from its raw component values: an RFC4122
    /// timestamp and counter.
    ///
    /// RFC4122, which defines the V1 UUID, specifies a 60-byte timestamp format
    /// as the number of 100-nanosecond intervals elapsed since 00:00:00.00,
    /// 15 Oct 1582, "the date of the Gregorian reform of the Christian
    /// calendar."
    ///
    /// The counter value is used to differentiate between ids generated by
    /// the same host computer in rapid succession (i.e. with the same observed
    /// time). See the [`ClockSequence`] trait for a generic interface to any
    /// counter generators that might be used.
    ///
    /// Internally, the timestamp is stored as a `u64`. For this reason, dates
    /// prior to October 1582 are not supported.
    ///
    /// [`ClockSequence`]: trait.ClockSequence.html
    pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
        Timestamp { ticks, counter }
    }

    /// Construct a `Timestamp` from a unix timestamp and sequence-generating
    /// `context`.
    ///
    /// A unix timestamp represents the elapsed time since Jan 1 1970. Libc's
    /// `clock_gettime` and other popular implementations traditionally
    /// represent this duration as a `timespec`: a struct with `u64` and
    /// `u32` fields representing the seconds, and "subsecond" or fractional
    /// nanoseconds elapsed since the timestamp's second began,
    /// respectively.
    ///
    /// This constructs a `Timestamp` from the seconds and fractional
    /// nanoseconds of a unix timestamp, converting the duration since 1970
    /// into the number of 100-nanosecond intervals since 00:00:00.00, 15
    /// Oct 1982 specified by RFC4122 and used internally by `Timestamp`.
    ///
    /// The function is not guaranteed to produce monotonically increasing
    /// values however. There is a slight possibility that two successive
    /// equal time values could be supplied and the sequence counter wraps back
    /// over to 0.
    ///
    /// If uniqueness and monotonicity is required, the user is responsible for
    /// ensuring that the time value always increases between calls (including
    /// between restarts of the process and device).
    pub fn from_unix(
        context: impl ClockSequence,
        seconds: u64,
        subsec_nanos: u32,
    ) -> Self {
        let counter = context.generate_sequence(seconds, subsec_nanos);
        let ticks = UUID_TICKS_BETWEEN_EPOCHS
            + seconds * 10_000_000
            + u64::from(subsec_nanos) / 100;

        Timestamp { ticks, counter }
    }

    /// Returns the raw RFC4122 timestamp and counter values stored by the
    /// `Timestamp`.
    ///
    /// The timestamp (the first, `u64` element in the tuple) represents the
    /// number of 100-nanosecond intervals since 00:00:00.00, 15 Oct 1582.
    /// The counter is used to differentiate between ids generated on the
    /// same host computer with the same observed time.
    pub const fn to_rfc4122(&self) -> (u64, u16) {
        (self.ticks, self.counter)
    }

    /// Returns the timestamp converted to the seconds and fractional
    /// nanoseconds since Jan 1 1970.
    ///
    /// Internally, the time is stored in 100-nanosecond intervals,
    /// thus the maximum precision represented by the fractional nanoseconds
    /// value is less than its unit size (100 ns vs. 1 ns).
    pub const fn to_unix(&self) -> (u64, u32) {
        (
            (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
            ((self.ticks - UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32
                * 100
        )
    }

    /// Returns the timestamp converted into nanoseconds elapsed since Jan 1
    /// 1970. Internally, the time is stored in 100-nanosecond intervals,
    /// thus the maximum precision represented is less than the units it is
    /// measured in (100 ns vs. 1 ns). The value returned represents the
    /// same duration as [`Timestamp::to_unix`]; this provides it in nanosecond
    /// units for convenience.
    pub const fn to_unix_nanos(&self) -> u64 {
        (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) * 100
    }
}

/// A trait that abstracts over generation of UUID v1 "Clock Sequence" values.
pub trait ClockSequence {
    /// Return a 16-bit number that will be used as the "clock sequence" in
    /// the UUID. The number must be different if the time has changed since
    /// the last time a clock sequence was requested.
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16;
}

impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16 {
        (**self).generate_sequence(seconds, subsec_nanos)
    }
}

impl Uuid {
    /// Create a new UUID (version 1) using a time value + sequence +
    /// *NodeId*.
    ///
    /// When generating [`Timestamp`]s using a [`ClockSequence`], this function
    /// is only guaranteed to produce unique values if the following conditions
    /// hold:
    ///
    /// 1. The *NodeId* is unique for this process,
    /// 2. The *Context* is shared across all threads which are generating v1
    ///    UUIDs,
    /// 3. The [`ClockSequence`] implementation reliably returns unique
    ///    clock sequences (this crate provides [`Context`] for this
    ///    purpose. However you can create your own [`ClockSequence`]
    ///    implementation, if [`Context`] does not meet your needs).
    ///
    /// The NodeID must be exactly 6 bytes long.
    ///
    /// Note that usage of this method requires the `v1` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// A UUID can be created from a unix [`Timestamp`] with a
    /// [`ClockSequence`]:
    ///
    /// ```rust
    /// use uuid::v1::{Timestamp, Context};
    /// use uuid::Uuid;
    ///
    /// let context = Context::new(42);
    /// let ts = Timestamp::from_unix(&context, 1497624119, 1234);
    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "f3b4958c-52a1-11e7-802a-010203040506"
    /// );
    /// ```
    ///
    /// The timestamp can also be created manually as per RFC4122:
    ///
    /// ```
    /// use uuid::v1::{Timestamp, Context};
    /// use uuid::Uuid;
    ///
    /// let context = Context::new(42);
    /// let ts = Timestamp::from_rfc4122(1497624119, 0);
    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "5943ee37-0000-1000-8000-010203040506"
    /// );
    /// ```
    ///
    /// [`Timestamp`]: v1/struct.Timestamp.html
    /// [`ClockSequence`]: v1/struct.ClockSequence.html
    /// [`Context`]: v1/struct.Context.html
    pub fn new_v1(ts: Timestamp, node_id: &[u8]) -> Result<Self, crate::Error> {
        const NODE_ID_LEN: usize = 6;

        let len = node_id.len();
        if len != NODE_ID_LEN {
            Err(crate::builder::Error::new(NODE_ID_LEN, len))?;
        }

        let time_low = (ts.ticks & 0xFFFF_FFFF) as u32;
        let time_mid = ((ts.ticks >> 32) & 0xFFFF) as u16;
        let time_high_and_version =
            (((ts.ticks >> 48) & 0x0FFF) as u16) | (1 << 12);

        let mut d4 = [0; 8];

        {
            d4[0] = (((ts.counter & 0x3F00) >> 8) as u8) | 0x80;
            d4[1] = (ts.counter & 0xFF) as u8;
        }

        d4[2..].copy_from_slice(node_id);

        Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
    }

    /// Returns an optional [`Timestamp`] storing the timestamp and
    /// counter portion parsed from a V1 UUID.
    ///
    /// Returns `None` if the supplied UUID is not V1.
    ///
    /// The V1 timestamp format defined in RFC4122 specifies a 60-bit
    /// integer representing the number of 100-nanosecond intervals
    /// since 00:00:00.00, 15 Oct 1582.
    ///
    /// [`Timestamp`] offers several options for converting the raw RFC4122
    /// value into more commonly-used formats, such as a unix timestamp.
    ///
    /// [`Timestamp`]: v1/struct.Timestamp.html
    pub fn to_timestamp(&self) -> Option<Timestamp> {
        if self
            .get_version()
            .map(|v| v != Version::Mac)
            .unwrap_or(true)
        {
            return None;
        }

        let ticks: u64 = u64::from(self.as_bytes()[6] & 0x0F) << 56
            | u64::from(self.as_bytes()[7]) << 48
            | u64::from(self.as_bytes()[4]) << 40
            | u64::from(self.as_bytes()[5]) << 32
            | u64::from(self.as_bytes()[0]) << 24
            | u64::from(self.as_bytes()[1]) << 16
            | u64::from(self.as_bytes()[2]) << 8
            | u64::from(self.as_bytes()[3]);

        let counter: u16 = u16::from(self.as_bytes()[8] & 0x3F) << 8
            | u16::from(self.as_bytes()[9]);

        Some(Timestamp::from_rfc4122(ticks, counter))
    }
}

impl Context {
    /// Creates a thread-safe, internally mutable context to help ensure
    /// uniqueness.
    ///
    /// This is a context which can be shared across threads. It maintains an
    /// internal counter that is incremented at every request, the value ends
    /// up in the clock_seq portion of the UUID (the fourth group). This
    /// will improve the probability that the UUID is unique across the
    /// process.
    pub const fn new(count: u16) -> Self {
        Self {
            count: atomic::AtomicUsize::new(count as usize),
        }
    }
}

impl ClockSequence for Context {
    fn generate_sequence(&self, _: u64, _: u32) -> u16 {
        (self.count.fetch_add(1, atomic::Ordering::SeqCst) & 0xffff) as u16
    }
}

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

    use crate::std::string::ToString;

    #[test]
    fn test_new_v1() {
        let time: u64 = 1_496_854_535;
        let time_fraction: u32 = 812_946_000;
        let node = [1, 2, 3, 4, 5, 6];
        let context = Context::new(0);

        {
            let uuid = Uuid::new_v1(
                Timestamp::from_unix(&context, time, time_fraction),
                &node,
            )
            .unwrap();

            assert_eq!(uuid.get_version(), Some(Version::Mac));
            assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
            assert_eq!(
                uuid.to_hyphenated().to_string(),
                "20616934-4ba2-11e7-8000-010203040506"
            );

            let ts = uuid.to_timestamp().unwrap().to_rfc4122();

            assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
            assert_eq!(ts.1, 0);
        };

        {
            let uuid2 = Uuid::new_v1(
                Timestamp::from_unix(&context, time, time_fraction),
                &node,
            )
            .unwrap();

            assert_eq!(
                uuid2.to_hyphenated().to_string(),
                "20616934-4ba2-11e7-8001-010203040506"
            );
            assert_eq!(uuid2.to_timestamp().unwrap().to_rfc4122().1, 1)
        };
    }
}
<commit_msg>fix format issues v2<commit_after>//! The implementation for Version 1 UUIDs.
//!
//! Note that you need feature `v1` in order to use these features.

use crate::prelude::*;
use core::sync::atomic;

/// The number of 100 ns ticks between the UUID epoch
/// `1582-10-15 00:00:00` and the Unix epoch `1970-01-01 00:00:00`.
const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;

/// A thread-safe, stateful context for the v1 generator to help ensure
/// process-wide uniqueness.
#[derive(Debug)]
pub struct Context {
    count: atomic::AtomicUsize,
}

/// Stores the number of nanoseconds from an epoch and a counter for ensuring
/// V1 ids generated on the same host are unique.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Timestamp {
    ticks: u64,
    counter: u16,
}

impl Timestamp {
    /// Construct a `Timestamp` from its raw component values: an RFC4122
    /// timestamp and counter.
    ///
    /// RFC4122, which defines the V1 UUID, specifies a 60-byte timestamp format
    /// as the number of 100-nanosecond intervals elapsed since 00:00:00.00,
    /// 15 Oct 1582, "the date of the Gregorian reform of the Christian
    /// calendar."
    ///
    /// The counter value is used to differentiate between ids generated by
    /// the same host computer in rapid succession (i.e. with the same observed
    /// time). See the [`ClockSequence`] trait for a generic interface to any
    /// counter generators that might be used.
    ///
    /// Internally, the timestamp is stored as a `u64`. For this reason, dates
    /// prior to October 1582 are not supported.
    ///
    /// [`ClockSequence`]: trait.ClockSequence.html
    pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
        Timestamp { ticks, counter }
    }

    /// Construct a `Timestamp` from a unix timestamp and sequence-generating
    /// `context`.
    ///
    /// A unix timestamp represents the elapsed time since Jan 1 1970. Libc's
    /// `clock_gettime` and other popular implementations traditionally
    /// represent this duration as a `timespec`: a struct with `u64` and
    /// `u32` fields representing the seconds, and "subsecond" or fractional
    /// nanoseconds elapsed since the timestamp's second began,
    /// respectively.
    ///
    /// This constructs a `Timestamp` from the seconds and fractional
    /// nanoseconds of a unix timestamp, converting the duration since 1970
    /// into the number of 100-nanosecond intervals since 00:00:00.00, 15
    /// Oct 1982 specified by RFC4122 and used internally by `Timestamp`.
    ///
    /// The function is not guaranteed to produce monotonically increasing
    /// values however. There is a slight possibility that two successive
    /// equal time values could be supplied and the sequence counter wraps back
    /// over to 0.
    ///
    /// If uniqueness and monotonicity is required, the user is responsible for
    /// ensuring that the time value always increases between calls (including
    /// between restarts of the process and device).
    pub fn from_unix(
        context: impl ClockSequence,
        seconds: u64,
        subsec_nanos: u32,
    ) -> Self {
        let counter = context.generate_sequence(seconds, subsec_nanos);
        let ticks = UUID_TICKS_BETWEEN_EPOCHS
            + seconds * 10_000_000
            + u64::from(subsec_nanos) / 100;

        Timestamp { ticks, counter }
    }

    /// Returns the raw RFC4122 timestamp and counter values stored by the
    /// `Timestamp`.
    ///
    /// The timestamp (the first, `u64` element in the tuple) represents the
    /// number of 100-nanosecond intervals since 00:00:00.00, 15 Oct 1582.
    /// The counter is used to differentiate between ids generated on the
    /// same host computer with the same observed time.
    pub const fn to_rfc4122(&self) -> (u64, u16) {
        (self.ticks, self.counter)
    }

    /// Returns the timestamp converted to the seconds and fractional
    /// nanoseconds since Jan 1 1970.
    ///
    /// Internally, the time is stored in 100-nanosecond intervals,
    /// thus the maximum precision represented by the fractional nanoseconds
    /// value is less than its unit size (100 ns vs. 1 ns).
    pub const fn to_unix(&self) -> (u64, u32) {
        (
            (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
            ((self.ticks - UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32
                * 100,
        )
    }

    /// Returns the timestamp converted into nanoseconds elapsed since Jan 1
    /// 1970. Internally, the time is stored in 100-nanosecond intervals,
    /// thus the maximum precision represented is less than the units it is
    /// measured in (100 ns vs. 1 ns). The value returned represents the
    /// same duration as [`Timestamp::to_unix`]; this provides it in nanosecond
    /// units for convenience.
    pub const fn to_unix_nanos(&self) -> u64 {
        (self.ticks - UUID_TICKS_BETWEEN_EPOCHS) * 100
    }
}

/// A trait that abstracts over generation of UUID v1 "Clock Sequence" values.
pub trait ClockSequence {
    /// Return a 16-bit number that will be used as the "clock sequence" in
    /// the UUID. The number must be different if the time has changed since
    /// the last time a clock sequence was requested.
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16;
}

impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> u16 {
        (**self).generate_sequence(seconds, subsec_nanos)
    }
}

impl Uuid {
    /// Create a new UUID (version 1) using a time value + sequence +
    /// *NodeId*.
    ///
    /// When generating [`Timestamp`]s using a [`ClockSequence`], this function
    /// is only guaranteed to produce unique values if the following conditions
    /// hold:
    ///
    /// 1. The *NodeId* is unique for this process,
    /// 2. The *Context* is shared across all threads which are generating v1
    ///    UUIDs,
    /// 3. The [`ClockSequence`] implementation reliably returns unique
    ///    clock sequences (this crate provides [`Context`] for this
    ///    purpose. However you can create your own [`ClockSequence`]
    ///    implementation, if [`Context`] does not meet your needs).
    ///
    /// The NodeID must be exactly 6 bytes long.
    ///
    /// Note that usage of this method requires the `v1` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// A UUID can be created from a unix [`Timestamp`] with a
    /// [`ClockSequence`]:
    ///
    /// ```rust
    /// use uuid::v1::{Timestamp, Context};
    /// use uuid::Uuid;
    ///
    /// let context = Context::new(42);
    /// let ts = Timestamp::from_unix(&context, 1497624119, 1234);
    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "f3b4958c-52a1-11e7-802a-010203040506"
    /// );
    /// ```
    ///
    /// The timestamp can also be created manually as per RFC4122:
    ///
    /// ```
    /// use uuid::v1::{Timestamp, Context};
    /// use uuid::Uuid;
    ///
    /// let context = Context::new(42);
    /// let ts = Timestamp::from_rfc4122(1497624119, 0);
    /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]).expect("failed to generate UUID");
    ///
    /// assert_eq!(
    ///     uuid.to_hyphenated().to_string(),
    ///     "5943ee37-0000-1000-8000-010203040506"
    /// );
    /// ```
    ///
    /// [`Timestamp`]: v1/struct.Timestamp.html
    /// [`ClockSequence`]: v1/struct.ClockSequence.html
    /// [`Context`]: v1/struct.Context.html
    pub fn new_v1(ts: Timestamp, node_id: &[u8]) -> Result<Self, crate::Error> {
        const NODE_ID_LEN: usize = 6;

        let len = node_id.len();
        if len != NODE_ID_LEN {
            Err(crate::builder::Error::new(NODE_ID_LEN, len))?;
        }

        let time_low = (ts.ticks & 0xFFFF_FFFF) as u32;
        let time_mid = ((ts.ticks >> 32) & 0xFFFF) as u16;
        let time_high_and_version =
            (((ts.ticks >> 48) & 0x0FFF) as u16) | (1 << 12);

        let mut d4 = [0; 8];

        {
            d4[0] = (((ts.counter & 0x3F00) >> 8) as u8) | 0x80;
            d4[1] = (ts.counter & 0xFF) as u8;
        }

        d4[2..].copy_from_slice(node_id);

        Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
    }

    /// Returns an optional [`Timestamp`] storing the timestamp and
    /// counter portion parsed from a V1 UUID.
    ///
    /// Returns `None` if the supplied UUID is not V1.
    ///
    /// The V1 timestamp format defined in RFC4122 specifies a 60-bit
    /// integer representing the number of 100-nanosecond intervals
    /// since 00:00:00.00, 15 Oct 1582.
    ///
    /// [`Timestamp`] offers several options for converting the raw RFC4122
    /// value into more commonly-used formats, such as a unix timestamp.
    ///
    /// [`Timestamp`]: v1/struct.Timestamp.html
    pub fn to_timestamp(&self) -> Option<Timestamp> {
        if self
            .get_version()
            .map(|v| v != Version::Mac)
            .unwrap_or(true)
        {
            return None;
        }

        let ticks: u64 = u64::from(self.as_bytes()[6] & 0x0F) << 56
            | u64::from(self.as_bytes()[7]) << 48
            | u64::from(self.as_bytes()[4]) << 40
            | u64::from(self.as_bytes()[5]) << 32
            | u64::from(self.as_bytes()[0]) << 24
            | u64::from(self.as_bytes()[1]) << 16
            | u64::from(self.as_bytes()[2]) << 8
            | u64::from(self.as_bytes()[3]);

        let counter: u16 = u16::from(self.as_bytes()[8] & 0x3F) << 8
            | u16::from(self.as_bytes()[9]);

        Some(Timestamp::from_rfc4122(ticks, counter))
    }
}

impl Context {
    /// Creates a thread-safe, internally mutable context to help ensure
    /// uniqueness.
    ///
    /// This is a context which can be shared across threads. It maintains an
    /// internal counter that is incremented at every request, the value ends
    /// up in the clock_seq portion of the UUID (the fourth group). This
    /// will improve the probability that the UUID is unique across the
    /// process.
    pub const fn new(count: u16) -> Self {
        Self {
            count: atomic::AtomicUsize::new(count as usize),
        }
    }
}

impl ClockSequence for Context {
    fn generate_sequence(&self, _: u64, _: u32) -> u16 {
        (self.count.fetch_add(1, atomic::Ordering::SeqCst) & 0xffff) as u16
    }
}

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

    use crate::std::string::ToString;

    #[test]
    fn test_new_v1() {
        let time: u64 = 1_496_854_535;
        let time_fraction: u32 = 812_946_000;
        let node = [1, 2, 3, 4, 5, 6];
        let context = Context::new(0);

        {
            let uuid = Uuid::new_v1(
                Timestamp::from_unix(&context, time, time_fraction),
                &node,
            )
            .unwrap();

            assert_eq!(uuid.get_version(), Some(Version::Mac));
            assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
            assert_eq!(
                uuid.to_hyphenated().to_string(),
                "20616934-4ba2-11e7-8000-010203040506"
            );

            let ts = uuid.to_timestamp().unwrap().to_rfc4122();

            assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
            assert_eq!(ts.1, 0);
        };

        {
            let uuid2 = Uuid::new_v1(
                Timestamp::from_unix(&context, time, time_fraction),
                &node,
            )
            .unwrap();

            assert_eq!(
                uuid2.to_hyphenated().to_string(),
                "20616934-4ba2-11e7-8001-010203040506"
            );
            assert_eq!(uuid2.to_timestamp().unwrap().to_rfc4122().1, 1)
        };
    }
}
<|endoftext|>


<commit_before>//! This module encompasses all types needed to send mail using version 3 of the mail
//! send API.

use std::collections::HashMap;

use data_encoding::BASE64;
use reqwest::header::{self, HeaderMap, HeaderValue, InvalidHeaderValue};
use serde::Serialize;

#[cfg(not(feature = "async"))]
use reqwest::blocking::{Client, Response};
#[cfg(feature = "async")]
use reqwest::{Client, Response};

use crate::error::{RequestNotSuccessful, SendgridResult};

const V3_API_URL: &str = "https://api.sendgrid.com/v3/mail/send";

/// Just a redefinition of a map to store string keys and values.
pub type SGMap = HashMap<String, String>;

/// Used to send a V3 message body.
#[derive(Clone, Debug)]
pub struct Sender {
    api_key: String,
    client: Client,
}

/// The main structure for a V3 API mail send call. This is composed of many other smaller
/// structures used to add lots of customization to your message.
#[derive(Default, Serialize)]
pub struct Message {
    from: Email,
    subject: String,
    personalizations: Vec<Personalization>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content: Option<Vec<Content>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    attachments: Option<Vec<Attachment>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    template_id: Option<String>,
}

/// An email with a required address and an optional name field.
#[derive(Clone, Default, Serialize)]
pub struct Email {
    email: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
}

/// The body of an email with the content type and the message.
#[derive(Clone, Default, Serialize)]
pub struct Content {
    #[serde(rename = "type")]
    content_type: String,
    value: String,
}

/// A personalization block for a V3 message. It has to at least contain one email as a to
/// address. All other fields are optional.
#[derive(Default, Serialize)]
pub struct Personalization {
    to: Vec<Email>,

    #[serde(skip_serializing_if = "Option::is_none")]
    cc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    bcc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    subject: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    headers: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    substitutions: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    custom_args: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    dynamic_template_data: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    send_at: Option<u64>,
}

/// An attachment block for a V3 message. Content and filename are required. If the
/// mime_type is unspecified, the email will use Sendgrid's default for attachments
/// which is 'application/octet-stream'.
#[derive(Default, Serialize)]
pub struct Attachment {
    content: String,

    filename: String,

    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    mime_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    disposition: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content_id: Option<String>,
}

impl Sender {
    /// Construct a new V3 message sender.
    pub fn new(api_key: String) -> Sender {
        Sender {
            api_key,
            client: Client::new(),
        }
    }

    fn get_headers(&self) -> Result<HeaderMap, InvalidHeaderValue> {
        let mut headers = HeaderMap::new();
        headers.insert(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", self.api_key.clone()))?,
        );
        headers.insert(
            header::CONTENT_TYPE,
            HeaderValue::from_static("application/json"),
        );
        headers.insert(header::USER_AGENT, HeaderValue::from_static("sendgrid-rs"));
        Ok(headers)
    }

    #[cfg(feature = "async")]
    /// Send a V3 message and return the HTTP response or an error.
    pub async fn send(&self, mail: &Message) -> SendgridResult<Response> {
        let headers = self.get_headers()?;

        let resp = self
            .client
            .post(V3_API_URL)
            .headers(headers)
            .body(mail.gen_json())
            .send()
            .await?;

        if let Err(_) = resp.error_for_status_ref() {
            return Err(RequestNotSuccessful::new(resp.status(), resp.text().await?).into());
        }

        Ok(resp)
    }

    #[cfg(not(feature = "async"))]
    /// Send a V3 message and return the HTTP response or an error.
    pub fn send(&self, mail: &Message) -> SendgridResult<Response> {
        let headers = self.get_headers()?;
        let body = mail.gen_json();

        let resp = self
            .client
            .post(V3_API_URL)
            .headers(headers)
            .body(body)
            .send()?;

        if let Err(_) = resp.error_for_status_ref() {
            return Err(RequestNotSuccessful::new(resp.status(), resp.text()?).into());
        }

        Ok(resp)
    }
}

impl Message {
    /// Construct a new V3 message.
    pub fn new() -> Message {
        Message::default()
    }

    /// Set the from address.
    pub fn set_from(mut self, from: Email) -> Message {
        self.from = from;
        self
    }

    /// Set the subject.
    pub fn set_subject(mut self, subject: &str) -> Message {
        self.subject = String::from(subject);
        self
    }

    /// Set the template id.
    pub fn set_template_id(mut self, template_id: &str) -> Message {
        self.template_id = Some(String::from(template_id));
        self
    }

    /// Add content to the message.
    pub fn add_content(mut self, c: Content) -> Message {
        match self.content {
            None => {
                let mut content = Vec::new();
                content.push(c);
                self.content = Some(content);
            }
            Some(ref mut content) => content.push(c),
        };
        self
    }

    /// Add a personalization to the message.
    pub fn add_personalization(mut self, p: Personalization) -> Message {
        self.personalizations.push(p);
        self
    }

    /// Add an attachment to the message.
    pub fn add_attachment(mut self, a: Attachment) -> Message {
        match self.attachments {
            None => {
                let mut attachments = Vec::new();
                attachments.push(a);
                self.attachments = Some(attachments);
            }
            Some(ref mut attachments) => attachments.push(a),
        };
        self
    }

    fn gen_json(&self) -> String {
        serde_json::to_string(self).unwrap()
    }
}

impl Email {
    /// Construct a new email type.
    pub fn new() -> Email {
        Email::default()
    }

    /// Set the address for this email.
    pub fn set_email(mut self, email: &str) -> Email {
        self.email = String::from(email);
        self
    }

    /// Set an optional name.
    pub fn set_name(mut self, name: &str) -> Email {
        self.name = Some(String::from(name));
        self
    }
}

impl Content {
    /// Construct a new content type.
    pub fn new() -> Content {
        Content::default()
    }

    /// Set the type of this content.
    pub fn set_content_type(mut self, content_type: &str) -> Content {
        self.content_type = String::from(content_type);
        self
    }

    /// Set the corresponding message for this content.
    pub fn set_value(mut self, value: &str) -> Content {
        self.value = String::from(value);
        self
    }
}

impl Personalization {
    /// Construct a new personalization block for this message.
    pub fn new() -> Personalization {
        Personalization::default()
    }

    /// Add a to field.
    pub fn add_to(mut self, to: Email) -> Personalization {
        self.to.push(to);
        self
    }

    /// Add a CC field.
    pub fn add_cc(mut self, cc: Email) -> Personalization {
        match self.cc {
            None => {
                let mut ccs = Vec::new();
                ccs.push(cc);
                self.cc = Some(ccs);
            }
            Some(ref mut c) => {
                c.push(cc);
            }
        }
        self
    }

    /// Add a BCC field.
    pub fn add_bcc(mut self, bcc: Email) -> Personalization {
        match self.bcc {
            None => {
                let mut bccs = Vec::new();
                bccs.push(bcc);
                self.bcc = Some(bccs);
            }
            Some(ref mut b) => {
                b.push(bcc);
            }
        }
        self
    }

    /// Add a headers field.
    pub fn add_headers(mut self, headers: SGMap) -> Personalization {
        match self.headers {
            None => {
                let mut h = HashMap::new();
                for (name, value) in headers {
                    h.insert(name, value);
                }
                self.headers = Some(h);
            }
            Some(ref mut h) => {
                h.extend(headers);
            }
        }
        self
    }

    /// Add a dynamic template data field.
    pub fn add_dynamic_template_data(mut self, dynamic_template_data: SGMap) -> Personalization {
        match self.dynamic_template_data {
            None => {
                let mut h = HashMap::new();
                for (name, value) in dynamic_template_data {
                    h.insert(name, value);
                }
                self.dynamic_template_data = Some(h);
            }
            Some(ref mut h) => {
                h.extend(dynamic_template_data);
            }
        }
        self
    }
}

impl Attachment {
    /// Construct a new attachment for this message.
    pub fn new() -> Attachment {
        Attachment::default()
    }

    /// The raw body of the attachment.
    pub fn set_content(mut self, c: &[u8]) -> Attachment {
        self.content = BASE64.encode(c);
        self
    }

    /// The base64 body of the attachment.
    pub fn set_base64_content(mut self, c: &str) -> Attachment {
        self.content = String::from(c);
        self
    }

    /// Sets the filename for the attachment.
    pub fn set_filename(mut self, filename: &str) -> Attachment {
        self.filename = filename.into();
        self
    }

    /// Set an optional mime type. Sendgrid will default to 'application/octet-stream'
    /// if unspecified.
    pub fn set_mime_type(mut self, mime: &str) -> Attachment {
        self.mime_type = Some(String::from(mime));
        self
    }
}
<commit_msg>(#72)<commit_after>//! This module encompasses all types needed to send mail using version 3 of the mail
//! send API.

use std::collections::HashMap;

use data_encoding::BASE64;
use reqwest::header::{self, HeaderMap, HeaderValue, InvalidHeaderValue};
use serde::Serialize;

#[cfg(not(feature = "async"))]
use reqwest::blocking::{Client, Response};
#[cfg(feature = "async")]
use reqwest::{Client, Response};

use crate::error::{RequestNotSuccessful, SendgridResult};

const V3_API_URL: &str = "https://api.sendgrid.com/v3/mail/send";

/// Just a redefinition of a map to store string keys and values.
pub type SGMap = HashMap<String, String>;

/// Used to send a V3 message body.
#[derive(Clone, Debug)]
pub struct Sender {
    api_key: String,
    client: Client,
}

/// The main structure for a V3 API mail send call. This is composed of many other smaller
/// structures used to add lots of customization to your message.
#[derive(Default, Serialize)]
pub struct Message {
    from: Email,
    subject: String,
    personalizations: Vec<Personalization>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content: Option<Vec<Content>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    attachments: Option<Vec<Attachment>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    template_id: Option<String>,
}

/// An email with a required address and an optional name field.
#[derive(Clone, Default, Serialize)]
pub struct Email {
    email: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
}

/// The body of an email with the content type and the message.
#[derive(Clone, Default, Serialize)]
pub struct Content {
    #[serde(rename = "type")]
    content_type: String,
    value: String,
}

/// A personalization block for a V3 message. It has to at least contain one email as a to
/// address. All other fields are optional.
#[derive(Default, Serialize)]
pub struct Personalization {
    to: Vec<Email>,

    #[serde(skip_serializing_if = "Option::is_none")]
    cc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    bcc: Option<Vec<Email>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    subject: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    headers: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    substitutions: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    custom_args: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    dynamic_template_data: Option<SGMap>,

    #[serde(skip_serializing_if = "Option::is_none")]
    send_at: Option<u64>,
}

/// An attachment block for a V3 message. Content and filename are required. If the
/// mime_type is unspecified, the email will use Sendgrid's default for attachments
/// which is 'application/octet-stream'.
#[derive(Default, Serialize)]
pub struct Attachment {
    content: String,

    filename: String,

    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    mime_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    disposition: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    content_id: Option<String>,
}

impl Sender {
    /// Construct a new V3 message sender.
    pub fn new(api_key: String) -> Sender {
        Sender {
            api_key,
            client: Client::new(),
        }
    }

    fn get_headers(&self) -> Result<HeaderMap, InvalidHeaderValue> {
        let mut headers = HeaderMap::new();
        headers.insert(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", self.api_key.clone()))?,
        );
        headers.insert(
            header::CONTENT_TYPE,
            HeaderValue::from_static("application/json"),
        );
        headers.insert(header::USER_AGENT, HeaderValue::from_static("sendgrid-rs"));
        Ok(headers)
    }

    #[cfg(feature = "async")]
    /// Send a V3 message and return the HTTP response or an error.
    pub async fn send(&self, mail: &Message) -> SendgridResult<Response> {
        let headers = self.get_headers()?;

        let resp = self
            .client
            .post(V3_API_URL)
            .headers(headers)
            .body(mail.gen_json())
            .send()
            .await?;

        if let Err(_) = resp.error_for_status_ref() {
            return Err(RequestNotSuccessful::new(resp.status(), resp.text().await?).into());
        }

        Ok(resp)
    }

    #[cfg(not(feature = "async"))]
    /// Send a V3 message and return the HTTP response or an error.
    pub fn send(&self, mail: &Message) -> SendgridResult<Response> {
        let headers = self.get_headers()?;
        let body = mail.gen_json();

        let resp = self
            .client
            .post(V3_API_URL)
            .headers(headers)
            .body(body)
            .send()?;

        if let Err(_) = resp.error_for_status_ref() {
            return Err(RequestNotSuccessful::new(resp.status(), resp.text()?).into());
        }

        Ok(resp)
    }
}

impl Message {
    /// Construct a new V3 message.
    pub fn new() -> Message {
        Message::default()
    }

    /// Set the from address.
    pub fn set_from(mut self, from: Email) -> Message {
        self.from = from;
        self
    }

    /// Set the subject.
    pub fn set_subject(mut self, subject: &str) -> Message {
        self.subject = String::from(subject);
        self
    }

    /// Set the template id.
    pub fn set_template_id(mut self, template_id: &str) -> Message {
        self.template_id = Some(String::from(template_id));
        self
    }

    /// Add content to the message.
    pub fn add_content(mut self, c: Content) -> Message {
        match self.content {
            None => {
                let mut content = Vec::new();
                content.push(c);
                self.content = Some(content);
            }
            Some(ref mut content) => content.push(c),
        };
        self
    }

    /// Add a personalization to the message.
    pub fn add_personalization(mut self, p: Personalization) -> Message {
        self.personalizations.push(p);
        self
    }

    /// Add an attachment to the message.
    pub fn add_attachment(mut self, a: Attachment) -> Message {
        match self.attachments {
            None => {
                let mut attachments = Vec::new();
                attachments.push(a);
                self.attachments = Some(attachments);
            }
            Some(ref mut attachments) => attachments.push(a),
        };
        self
    }

    fn gen_json(&self) -> String {
        serde_json::to_string(self).unwrap()
    }
}

impl Email {
    /// Construct a new email type.
    pub fn new() -> Email {
        Email::default()
    }

    /// Set the address for this email.
    pub fn set_email(mut self, email: &str) -> Email {
        self.email = String::from(email);
        self
    }

    /// Set an optional name.
    pub fn set_name(mut self, name: &str) -> Email {
        self.name = Some(String::from(name));
        self
    }
}

impl Content {
    /// Construct a new content type.
    pub fn new() -> Content {
        Content::default()
    }

    /// Set the type of this content.
    pub fn set_content_type(mut self, content_type: &str) -> Content {
        self.content_type = String::from(content_type);
        self
    }

    /// Set the corresponding message for this content.
    pub fn set_value(mut self, value: &str) -> Content {
        self.value = String::from(value);
        self
    }
}

impl Personalization {
    /// Construct a new personalization block for this message.
    pub fn new() -> Personalization {
        Personalization::default()
    }

    /// Add a to field.
    pub fn add_to(mut self, to: Email) -> Personalization {
        self.to.push(to);
        self
    }

    /// Add a CC field.
    pub fn add_cc(mut self, cc: Email) -> Personalization {
        match self.cc {
            None => {
                let mut ccs = Vec::new();
                ccs.push(cc);
                self.cc = Some(ccs);
            }
            Some(ref mut c) => {
                c.push(cc);
            }
        }
        self
    }

    /// Add a BCC field.
    pub fn add_bcc(mut self, bcc: Email) -> Personalization {
        match self.bcc {
            None => {
                let mut bccs = Vec::new();
                bccs.push(bcc);
                self.bcc = Some(bccs);
            }
            Some(ref mut b) => {
                b.push(bcc);
            }
        }
        self
    }

    /// Add a headers field.
    pub fn add_headers(mut self, headers: SGMap) -> Personalization {
        match self.headers {
            None => {
                let mut h = HashMap::new();
                for (name, value) in headers {
                    h.insert(name, value);
                }
                self.headers = Some(h);
            }
            Some(ref mut h) => {
                h.extend(headers);
            }
        }
        self
    }

    /// Add a dynamic template data field.
    pub fn add_dynamic_template_data(mut self, dynamic_template_data: SGMap) -> Personalization {
        match self.dynamic_template_data {
            None => {
                let mut h = HashMap::new();
                for (name, value) in dynamic_template_data {
                    h.insert(name, value);
                }
                self.dynamic_template_data = Some(h);
            }
            Some(ref mut h) => {
                h.extend(dynamic_template_data);
            }
        }
        self
    }
}

impl Attachment {
    /// Construct a new attachment for this message.
    pub fn new() -> Attachment {
        Attachment::default()
    }

    /// The raw body of the attachment.
    pub fn set_content(mut self, c: &[u8]) -> Attachment {
        self.content = BASE64.encode(c);
        self
    }

    /// The base64 body of the attachment.
    pub fn set_base64_content(mut self, c: &str) -> Attachment {
        self.content = String::from(c);
        self
    }

    /// Sets the filename for the attachment.
    pub fn set_filename(mut self, filename: &str) -> Attachment {
        self.filename = filename.into();
        self
    }

    /// Set an optional mime type. Sendgrid will default to 'application/octet-stream'
    /// if unspecified.
    pub fn set_mime_type(mut self, mime: &str) -> Attachment {
        self.mime_type = Some(String::from(mime));
        self
    }

    /// Set an optional content id.
    pub fn set_content_id(mut self, content_id: &str) -> Attachment {
        self.content_id = Some(String::from(content_id));
        self
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs, io};

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let mut builder = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL");
    if cfg!(feature = "unstable") {
        builder = builder.clang_arg("-DWLR_USE_UNSTABLE");
    }
    if !cfg!(feature = "static") {
        // config.h won't exist, so make a dummy file.
        // We don't need it because of the following -D defines.
        fs::create_dir_all(format!("{}{}", target_dir, "/include/wlr/"))
            .expect("Could not create <out>/include/wlr");
        fs::File::create(format!("{}{}", target_dir, "/include/wlr/config.h"))
            .expect("Could not create dummy config.h file");
        // meson automatically sets up variables, but if we are linking
        // dynamically bindgen will no longer have them.
        builder = builder.clang_args(
            [
                format!("-DWLR_HAS_LIBCAP={}", cfg!(feature = "libcap") as u8),
                format!("-DWLR_HAS_SYSTEMD={}", cfg!(feature = "systemd") as u8),
                format!("-DWLR_HAS_ELOGIND={}", cfg!(feature = "elogind") as u8),
                format!("-DWLR_HAS_X11_BACKEND={}", cfg!(feature = "x11_backend") as u8),
                format!("-DWLR_HAS_XWAYLAND={}", cfg!(feature = "xwayland") as u8),
                format!("-DWLR_HAS_XCB_ERRORS={}", cfg!(feature = "xcb_errors") as u8),
                format!("-DWLR_HAS_XCB_ICCCM={}", cfg!(feature = "xcb_icccm") as u8)
            ]
            .iter()
        )
    }
    let generated = builder.generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=xcb-xinput");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    println!("cargo:rerun-if-changed={}", "src/gen.rs");
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path = PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path
        .to_str()
        .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/x11", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_backend_x11");
        println!("cargo:rustc-link-lib=static=wlr_render");
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    if Path::new("wlroots").exists() {
        meson::build("wlroots", build_path_str);
    } else {
        panic!("The `wlroots` submodule does not exist");
    }
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols_prefix = pkg_config::get_variable("wayland-protocols", "prefix").unwrap();
    let protocols = fs::read_dir(format!("{}/share/wayland-protocols/stable", protocols_prefix))?.chain(
        fs::read_dir(format!("{}/share/wayland-protocols/unstable", protocols_prefix))?
    );
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner")
                .arg("server-header")
                .arg(path.clone())
                .arg(format!("{}/{}.h", out_path.to_str().unwrap(), filename))
                .status()
                .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[
        ("./wlroots/protocol/server-decoration.xml", "server_decoration"),
        (
            "./wlroots/protocol/wlr-gamma-control-unstable-v1.xml",
            "gamma_control"
        ),
        ("./wlroots/protocol/wlr-screencopy-unstable-v1.xml", "screencopy"),
        ("./wlroots/protocol/screenshooter.xml", "screenshooter"),
        ("./wlroots/protocol/idle.xml", "idle")
    ];

    for protocol in protocols {
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_server_api.rs", protocol.1)),
            wayland_scanner::Side::Server
        );
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_client_api.rs", protocol.1)),
            wayland_scanner::Side::Client
        );
        wayland_scanner::generate_c_interfaces(
            protocol.0,
            output_dir.join(format!("{}_interfaces.rs", protocol.1))
        );
    }
}

fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
    if pkg_config::probe_library("xcb-errors").is_ok() {
        println!("cargo:rustc-link-lib=dylib=xcb-errors");
    }
}
<commit_msg>Remove re-run if changed<commit_after>extern crate bindgen;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs, io};

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let mut builder = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL");
    if cfg!(feature = "unstable") {
        builder = builder.clang_arg("-DWLR_USE_UNSTABLE");
    }
    if !cfg!(feature = "static") {
        // config.h won't exist, so make a dummy file.
        // We don't need it because of the following -D defines.
        fs::create_dir_all(format!("{}{}", target_dir, "/include/wlr/"))
            .expect("Could not create <out>/include/wlr");
        fs::File::create(format!("{}{}", target_dir, "/include/wlr/config.h"))
            .expect("Could not create dummy config.h file");
        // meson automatically sets up variables, but if we are linking
        // dynamically bindgen will no longer have them.
        builder = builder.clang_args(
            [
                format!("-DWLR_HAS_LIBCAP={}", cfg!(feature = "libcap") as u8),
                format!("-DWLR_HAS_SYSTEMD={}", cfg!(feature = "systemd") as u8),
                format!("-DWLR_HAS_ELOGIND={}", cfg!(feature = "elogind") as u8),
                format!("-DWLR_HAS_X11_BACKEND={}", cfg!(feature = "x11_backend") as u8),
                format!("-DWLR_HAS_XWAYLAND={}", cfg!(feature = "xwayland") as u8),
                format!("-DWLR_HAS_XCB_ERRORS={}", cfg!(feature = "xcb_errors") as u8),
                format!("-DWLR_HAS_XCB_ICCCM={}", cfg!(feature = "xcb_icccm") as u8)
            ]
            .iter()
        )
    }
    let generated = builder.generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=xcb-xinput");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path = PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path
        .to_str()
        .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/x11", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_backend_x11");
        println!("cargo:rustc-link-lib=static=wlr_render");
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    if Path::new("wlroots").exists() {
        meson::build("wlroots", build_path_str);
    } else {
        panic!("The `wlroots` submodule does not exist");
    }
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols_prefix = pkg_config::get_variable("wayland-protocols", "prefix").unwrap();
    let protocols = fs::read_dir(format!("{}/share/wayland-protocols/stable", protocols_prefix))?.chain(
        fs::read_dir(format!("{}/share/wayland-protocols/unstable", protocols_prefix))?
    );
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner")
                .arg("server-header")
                .arg(path.clone())
                .arg(format!("{}/{}.h", out_path.to_str().unwrap(), filename))
                .status()
                .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[
        ("./wlroots/protocol/server-decoration.xml", "server_decoration"),
        (
            "./wlroots/protocol/wlr-gamma-control-unstable-v1.xml",
            "gamma_control"
        ),
        ("./wlroots/protocol/wlr-screencopy-unstable-v1.xml", "screencopy"),
        ("./wlroots/protocol/screenshooter.xml", "screenshooter"),
        ("./wlroots/protocol/idle.xml", "idle")
    ];

    for protocol in protocols {
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_server_api.rs", protocol.1)),
            wayland_scanner::Side::Server
        );
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_client_api.rs", protocol.1)),
            wayland_scanner::Side::Client
        );
        wayland_scanner::generate_c_interfaces(
            protocol.0,
            output_dir.join(format!("{}_interfaces.rs", protocol.1))
        );
    }
}

fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
    if pkg_config::probe_library("xcb-errors").is_ok() {
        println!("cargo:rustc-link-lib=dylib=xcb-errors");
    }
}
<|endoftext|>