<commit_before>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_raw_str(&mut self, raw_str: &str) {
        self.buffer.push_all(raw_str.as_bytes());
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.buffer.push(b'"');
        self.js.encode_raw_str(name);
        self.js.buffer.push(b'"');
        self.js.buffer.push(b':');

        f(self.js);
    }
}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<commit_msg>Introduce encode_str_noescape<commit_after>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js);
    }
}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate protobuf;

mod message;

use std::fmt;

use protobuf::Message;

pub use message::error::*;
pub use message::launcher::*;
pub use message::supervisor::*;
use message::net::*;

pub const LAUNCHER_PIPE_ENV: &'static str = "HAB_LAUNCHER_PIPE";
pub const LAUNCHER_PID_ENV: &'static str = "HAB_LAUNCHER_PID";
/// Process exit code from Supervisor which indicates to Launcher that the Supervisor
/// ran to completion with a successful result. The Launcher should not attempt to restart
/// the Supervisor and should exit immediately with a successful exit code.
pub const OK_NO_RETRY_EXCODE: i32 = 84;
/// Same as `OK_NO_RETRY_EXCODE` except the Supervisor ran to completion with an unsuccessful
/// exit code. The Launcher should exit immediately with a non-zero exit code.
pub const ERR_NO_RETRY_EXCODE: i32 = 86;

pub struct NetTxn(Envelope);

impl NetTxn {
    pub fn build<T>(message: &T) -> Result<Self, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let mut env = Envelope::new();
        env.set_message_id(message.descriptor().name().to_string());
        env.set_payload(message.write_to_bytes()?);
        Ok(NetTxn(env))
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self, protobuf::ProtobufError> {
        let env = protobuf::parse_from_bytes::<Envelope>(bytes)?;
        Ok(NetTxn(env))
    }

    pub fn build_reply<T>(&self, message: &T) -> Result<Self, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let mut env = Self::build(message)?;
        env.0.set_txn_id(self.0.get_txn_id());
        Ok(env)
    }

    pub fn decode<T>(&self) -> Result<T, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let msg = protobuf::parse_from_bytes::<T>(self.0.get_payload())?;
        Ok(msg)
    }

    pub fn message_id(&self) -> &str {
        self.0.get_message_id()
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, protobuf::ProtobufError> {
        self.0.write_to_bytes()
    }
}

pub fn error<T>(err: T) -> NetErr
where
    T: ToString + Into<ErrCode>,
{
    let mut message = NetErr::new();
    message.set_msg(err.to_string());
    message.set_code(err.into());
    message
}

impl fmt::Display for NetErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}: {}", self.get_code(), self.get_msg())
    }
}

impl fmt::Display for ShutdownMethod {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let printable = match *self {
            ShutdownMethod::AlreadyExited => "Already Exited",
            ShutdownMethod::GracefulTermination => "Graceful Termination",
            ShutdownMethod::Killed => "Killed",
        };
        write!(f, "{}", printable)
    }
}
<commit_msg>Release Launcher's LOCK on Supervisor restart<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate protobuf;

mod message;

use std::fmt;

use protobuf::Message;

pub use message::error::*;
pub use message::launcher::*;
pub use message::supervisor::*;
use message::net::*;

pub const LAUNCHER_PIPE_ENV: &'static str = "HAB_LAUNCHER_PIPE";
pub const LAUNCHER_PID_ENV: &'static str = "HAB_LAUNCHER_PID";
// Set to instruct the Supervisor to clean the Launcher's process LOCK on startup. This is useful
// when restarting a Supervisor which terminated normally.
pub const LAUNCHER_LOCK_CLEAN_ENV: &'static str = "HAB_LAUNCHER_LOCK_CLEAN";
/// Process exit code from Supervisor which indicates to Launcher that the Supervisor
/// ran to completion with a successful result. The Launcher should not attempt to restart
/// the Supervisor and should exit immediately with a successful exit code.
pub const OK_NO_RETRY_EXCODE: i32 = 84;
/// Same as `OK_NO_RETRY_EXCODE` except the Supervisor ran to completion with an unsuccessful
/// exit code. The Launcher should exit immediately with a non-zero exit code.
pub const ERR_NO_RETRY_EXCODE: i32 = 86;

pub struct NetTxn(Envelope);

impl NetTxn {
    pub fn build<T>(message: &T) -> Result<Self, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let mut env = Envelope::new();
        env.set_message_id(message.descriptor().name().to_string());
        env.set_payload(message.write_to_bytes()?);
        Ok(NetTxn(env))
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self, protobuf::ProtobufError> {
        let env = protobuf::parse_from_bytes::<Envelope>(bytes)?;
        Ok(NetTxn(env))
    }

    pub fn build_reply<T>(&self, message: &T) -> Result<Self, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let mut env = Self::build(message)?;
        env.0.set_txn_id(self.0.get_txn_id());
        Ok(env)
    }

    pub fn decode<T>(&self) -> Result<T, protobuf::ProtobufError>
    where
        T: protobuf::MessageStatic,
    {
        let msg = protobuf::parse_from_bytes::<T>(self.0.get_payload())?;
        Ok(msg)
    }

    pub fn message_id(&self) -> &str {
        self.0.get_message_id()
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, protobuf::ProtobufError> {
        self.0.write_to_bytes()
    }
}

pub fn error<T>(err: T) -> NetErr
where
    T: ToString + Into<ErrCode>,
{
    let mut message = NetErr::new();
    message.set_msg(err.to_string());
    message.set_code(err.into());
    message
}

impl fmt::Display for NetErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}: {}", self.get_code(), self.get_msg())
    }
}

impl fmt::Display for ShutdownMethod {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let printable = match *self {
            ShutdownMethod::AlreadyExited => "Already Exited",
            ShutdownMethod::GracefulTermination => "Graceful Termination",
            ShutdownMethod::Killed => "Killed",
        };
        write!(f, "{}", printable)
    }
}
<|endoftext|>


<commit_before>//! A simple and easy wrapper around `Vec` to implement a FIFO queue. This is
//! no fancy, advanced data type but something simple you can use easily until
//! or unless you need something different.
//!
//! # Example
//!
//! ```
//! use queue::Queue;
//!
//! let mut q = Queue::new();
//!
//! q.queue("hello").unwrap();
//! q.queue("out").unwrap();
//! q.queue("there!").unwrap();
//!
//! while let Some(item) = q.dequeue() {
//!     println!("{}", item);
//! }
//! ```
//!
//! Outputs:
//!
//! ```text
//! hello
//! out
//! there!
//! ```

#[cfg(test)]
mod tests;

/// A first in, first out queue built around `Vec`.
///
/// An optional capacity can be set (or changed) to ensure the `Queue` never
/// grows past a certain size. If the capacity is not specified (ie set to
/// `None`) then the `Queue` will grow as needed. If you're worried about
/// memory allocation, set a capacity and the necessary memory will be
/// allocated at that time. Otherwise memory could be allocated, deallocated
/// and reallocated as the `Queue` changes size.
///
/// The only requirement of the type used is that it implements the `Clone`
/// trait.
///
/// # Example
///
/// ```
/// use queue::Queue;
///
/// let mut q = Queue::with_capacity(5);
///
/// for i in 0..5 {
/// 	q.queue(i).unwrap();
/// }
///
/// for i in 0..5 {
/// 	assert_eq!(q.dequeue(), Some(i));
/// }
/// ```
#[derive(Clone, Debug)]
pub struct Queue<T> {
	vec: Vec<T>,
	cap: Option<usize>,
}

impl<T: Clone> Queue<T> {
	/// Constructs a new `Queue<T>`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::new();
	/// ```
	pub fn new() -> Queue<T> {
		Queue {
			vec: Vec::new(),
			cap: None,
		}
	}

	/// Constructs a new `Queue<T>` with a specified capacity.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::with_capacity(20);
	/// ```
	pub fn with_capacity(cap: usize) -> Queue<T> {
		Queue {
			vec: Vec::with_capacity(cap),
			cap: Some(cap),
		}
	}

	/// Add an item to the end of the `Queue`. Returns `Ok(usize)` with the new
	/// length of the `Queue`, or `Err(())` if there is no more room.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// assert_eq!(q.peek(), Some("hello"));
	/// ```
	pub fn queue(&mut self, item: T) -> Result<usize, ()> {
		if let Some(cap) = self.cap {
			if self.vec.len() >= cap {
				Err(())
			} else {
				self.vec.push(item);
				Ok(self.vec.len())
			}
		} else {
			self.vec.push(item);
			Ok(self.vec.len())
		}
	}

	/// Forcefully ad an item to the end of the `Queue`. If the `Queue` is at
	/// capacity, the first item will be removed to make room. Returns `usize`
	/// with the new length of the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(1);
	/// q.queue("hello").unwrap();
	/// let _ = q.force_queue("world");
	/// assert_eq!(q.peek(), Some("world"));
	/// ```
	pub fn force_queue(&mut self, item: T) -> usize {
		if let Ok(len) = self.queue(item.clone()) {
			return len;
		} else {
			let _ = self.dequeue();
			return self.queue(item.clone()).unwrap();
		}
	}

	/// Remove the next item from the `Queue`. Returns `Option<T>` so it will
	/// return either `Some(T)` or `None` depending on if there's anything in
	/// the `Queue` to get.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// q.queue("world").unwrap();
	/// assert_eq!(q.dequeue(), Some("hello"));
	/// ```
	pub fn dequeue(&mut self) -> Option<T> {
		if self.vec.len() > 0 {
			Some(self.vec.remove(0))
		} else {
			None
		}
	}

	/// Peek at the next item in the `Queue`, if there's something there.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue(12).unwrap();
	/// assert_eq!(q.peek(), Some(12));
	/// ```
	pub fn peek(&self) -> Option<T> {
		if self.vec.len() > 0 {
			Some(self.vec[0].clone())
		} else {
			None
		}
	}

	/// The number of items currently in the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(8);
	/// q.queue(1).unwrap();
	/// q.queue(2).unwrap();
	/// assert_eq!(q.len(), 2);
	/// ```
	pub fn len(&self) -> usize {
		self.vec.len()
	}

	/// Query the capacity for a `Queue`. If there is no capacity set (the
	/// `Queue` can grow as needed) then `None` will be returned, otherwise
	/// it will be `Some(usize)`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let q: Queue<u8> = Queue::with_capacity(12);
	/// assert_eq!(q.capacity(), Some(12));
	/// ```
	pub fn capacity(&self) -> Option<usize> {
		self.cap
	}

	/// Modify the capacity of a `Queue`. If set to `None`, the `Queue` will
	/// grow automatically, as needed. Otherwise, it will be limited to the
	/// specified number of items. If there are more items in the `Queue` than
	/// the requested capacity, `Err(())` will be returned, otherwise the
	/// operation will succeed and `Ok(())` will be returned. If the capacity
	/// is shrunk, the underlying `Vec` will be shrunk also, which would free
	/// up whatever extra memory was allocated for the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<u8> = Queue::new();
	/// q.set_capacity(12).unwrap();
	/// q.set_capacity(None).unwrap();
	/// ```
	pub fn set_capacity<C: Into<Option<usize>>>(&mut self, cap: C) -> Result<(), ()> {
		let cap = cap.into();

		if cap == None {
			self.cap = None;
			return Ok(());
		}

		if cap == self.cap {
			return Ok(());
		}

		let cap = cap.unwrap();

		if cap < self.vec.len() {
			return Err(());
		}

		if let Some(scap) = self.cap {
			if cap < scap {
				self.vec.shrink_to_fit();
			}
		}

		let r = cap - self.vec.len();
		self.vec.reserve_exact(r);
		self.cap = Some(cap);

		Ok(())
	}
}
<commit_msg>use is_empty() to be more concise<commit_after>//! A simple and easy wrapper around `Vec` to implement a FIFO queue. This is
//! no fancy, advanced data type but something simple you can use easily until
//! or unless you need something different.
//!
//! # Example
//!
//! ```
//! use queue::Queue;
//!
//! let mut q = Queue::new();
//!
//! q.queue("hello").unwrap();
//! q.queue("out").unwrap();
//! q.queue("there!").unwrap();
//!
//! while let Some(item) = q.dequeue() {
//!     println!("{}", item);
//! }
//! ```
//!
//! Outputs:
//!
//! ```text
//! hello
//! out
//! there!
//! ```

#[cfg(test)]
mod tests;

/// A first in, first out queue built around `Vec`.
///
/// An optional capacity can be set (or changed) to ensure the `Queue` never
/// grows past a certain size. If the capacity is not specified (ie set to
/// `None`) then the `Queue` will grow as needed. If you're worried about
/// memory allocation, set a capacity and the necessary memory will be
/// allocated at that time. Otherwise memory could be allocated, deallocated
/// and reallocated as the `Queue` changes size.
///
/// The only requirement of the type used is that it implements the `Clone`
/// trait.
///
/// # Example
///
/// ```
/// use queue::Queue;
///
/// let mut q = Queue::with_capacity(5);
///
/// for i in 0..5 {
/// 	q.queue(i).unwrap();
/// }
///
/// for i in 0..5 {
/// 	assert_eq!(q.dequeue(), Some(i));
/// }
/// ```
#[derive(Clone, Debug)]
pub struct Queue<T> {
	vec: Vec<T>,
	cap: Option<usize>,
}

impl<T: Clone> Queue<T> {
	/// Constructs a new `Queue<T>`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::new();
	/// ```
	pub fn new() -> Queue<T> {
		Queue {
			vec: Vec::new(),
			cap: None,
		}
	}

	/// Constructs a new `Queue<T>` with a specified capacity.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::with_capacity(20);
	/// ```
	pub fn with_capacity(cap: usize) -> Queue<T> {
		Queue {
			vec: Vec::with_capacity(cap),
			cap: Some(cap),
		}
	}

	/// Add an item to the end of the `Queue`. Returns `Ok(usize)` with the new
	/// length of the `Queue`, or `Err(())` if there is no more room.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// assert_eq!(q.peek(), Some("hello"));
	/// ```
	pub fn queue(&mut self, item: T) -> Result<usize, ()> {
		if let Some(cap) = self.cap {
			if self.vec.len() >= cap {
				Err(())
			} else {
				self.vec.push(item);
				Ok(self.vec.len())
			}
		} else {
			self.vec.push(item);
			Ok(self.vec.len())
		}
	}

	/// Forcefully ad an item to the end of the `Queue`. If the `Queue` is at
	/// capacity, the first item will be removed to make room. Returns `usize`
	/// with the new length of the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(1);
	/// q.queue("hello").unwrap();
	/// let _ = q.force_queue("world");
	/// assert_eq!(q.peek(), Some("world"));
	/// ```
	pub fn force_queue(&mut self, item: T) -> usize {
		if let Ok(len) = self.queue(item.clone()) {
			return len;
		} else {
			let _ = self.dequeue();
			return self.queue(item.clone()).unwrap();
		}
	}

	/// Remove the next item from the `Queue`. Returns `Option<T>` so it will
	/// return either `Some(T)` or `None` depending on if there's anything in
	/// the `Queue` to get.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// q.queue("world").unwrap();
	/// assert_eq!(q.dequeue(), Some("hello"));
	/// ```
	pub fn dequeue(&mut self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec.remove(0))
		} else {
			None
		}
	}

	/// Peek at the next item in the `Queue`, if there's something there.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue(12).unwrap();
	/// assert_eq!(q.peek(), Some(12));
	/// ```
	pub fn peek(&self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec[0].clone())
		} else {
			None
		}
	}

	/// The number of items currently in the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(8);
	/// q.queue(1).unwrap();
	/// q.queue(2).unwrap();
	/// assert_eq!(q.len(), 2);
	/// ```
	pub fn len(&self) -> usize {
		self.vec.len()
	}

	/// Query the capacity for a `Queue`. If there is no capacity set (the
	/// `Queue` can grow as needed) then `None` will be returned, otherwise
	/// it will be `Some(usize)`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let q: Queue<u8> = Queue::with_capacity(12);
	/// assert_eq!(q.capacity(), Some(12));
	/// ```
	pub fn capacity(&self) -> Option<usize> {
		self.cap
	}

	/// Modify the capacity of a `Queue`. If set to `None`, the `Queue` will
	/// grow automatically, as needed. Otherwise, it will be limited to the
	/// specified number of items. If there are more items in the `Queue` than
	/// the requested capacity, `Err(())` will be returned, otherwise the
	/// operation will succeed and `Ok(())` will be returned. If the capacity
	/// is shrunk, the underlying `Vec` will be shrunk also, which would free
	/// up whatever extra memory was allocated for the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<u8> = Queue::new();
	/// q.set_capacity(12).unwrap();
	/// q.set_capacity(None).unwrap();
	/// ```
	pub fn set_capacity<C: Into<Option<usize>>>(&mut self, cap: C) -> Result<(), ()> {
		let cap = cap.into();

		if cap == None {
			self.cap = None;
			return Ok(());
		}

		if cap == self.cap {
			return Ok(());
		}

		let cap = cap.unwrap();

		if cap < self.vec.len() {
			return Err(());
		}

		if let Some(scap) = self.cap {
			if cap < scap {
				self.vec.shrink_to_fit();
			}
		}

		let r = cap - self.vec.len();
		self.vec.reserve_exact(r);
		self.cap = Some(cap);

		Ok(())
	}
}
<|endoftext|>


<commit_before>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//! extern crate libnotify;
//!
//! fn main() {
//!     let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//!         panic!("{}", e);
//!     });
//!     let body_text = Some("This is the optional body text.");
//!     let n = notify.new_notification("This is the summary.", body_text, None)
//!                   .unwrap_or_else(|e| panic!("{}", e));
//!     n.show().unwrap_or_else(|e| panic!("{}", e));
//! }
//!
//! ```

#![warn(missing_docs)]

extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
extern crate gtypes;

use std::ffi::{self, CStr, CString};
use std::marker::PhantomData;
use std::fmt;
use std::error::Error;

use gtypes::{TRUE, FALSE};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists.
    AlreadyExists,
    /// Failed to initialize libnotify.
    InitError,
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitError => write!(f, "Failed to initialize libnotify."),
            NulError(ref e) => write!(f, "{}", e),
        }
    }
}

impl From<ffi::NulError> for ContextCreationError {
    fn from(src: ffi::NulError) -> Self {
        ContextCreationError::NulError(src)
    }
}

#[derive(Debug)]
/// An error that can happen when attempting to create a notification.
pub enum NotificationCreationError {
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
    /// An unknown error happened.
    Unknown,
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use NotificationCreationError::*;
        match *self {
            NulError(ref e) => write!(f, "{}", e),
            Unknown => write!(f, "Unknown error"),
        }
    }
}

impl From<ffi::NulError> for NotificationCreationError {
    fn from(src: ffi::NulError) -> Self {
        NotificationCreationError::NulError(src)
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = try!(CString::new(app_name));
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitError);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self,
                            summary: &str,
                            body: Option<&str>,
                            icon: Option<&str>)
                            -> Result<Notification, NotificationCreationError> {
        let summary = try!(CString::new(summary));
        let body = match body {
            Some(body) => Some(try!(CString::new(body))),
            None => None,
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null(),
        };
        let icon = match icon {
            Some(icon) => Some(try!(CString::new(icon))),
            None => None,
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null(),
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification {
                handle: n,
                _phantom: PhantomData,
            })
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>,
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), NotificationShowError> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                let result = Err(NotificationShowError {
                    message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
                });
                glib::g_error_free(err);
                return result;
            }
            return Ok(());
        }
    }
}

/// An error that can happen when attempting to show a notification.
#[derive(Debug)]
pub struct NotificationShowError {
    message: String,
}

impl fmt::Display for NotificationShowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Error showing notification: {}", self.message)
    }
}

impl Error for NotificationShowError {
    fn description(&self) -> &str {
        "Notification show error"
    }
}
<commit_msg>Remove unnecessary return statement<commit_after>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//! extern crate libnotify;
//!
//! fn main() {
//!     let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//!         panic!("{}", e);
//!     });
//!     let body_text = Some("This is the optional body text.");
//!     let n = notify.new_notification("This is the summary.", body_text, None)
//!                   .unwrap_or_else(|e| panic!("{}", e));
//!     n.show().unwrap_or_else(|e| panic!("{}", e));
//! }
//!
//! ```

#![warn(missing_docs)]

extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
extern crate gtypes;

use std::ffi::{self, CStr, CString};
use std::marker::PhantomData;
use std::fmt;
use std::error::Error;

use gtypes::{TRUE, FALSE};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists.
    AlreadyExists,
    /// Failed to initialize libnotify.
    InitError,
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitError => write!(f, "Failed to initialize libnotify."),
            NulError(ref e) => write!(f, "{}", e),
        }
    }
}

impl From<ffi::NulError> for ContextCreationError {
    fn from(src: ffi::NulError) -> Self {
        ContextCreationError::NulError(src)
    }
}

#[derive(Debug)]
/// An error that can happen when attempting to create a notification.
pub enum NotificationCreationError {
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
    /// An unknown error happened.
    Unknown,
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use NotificationCreationError::*;
        match *self {
            NulError(ref e) => write!(f, "{}", e),
            Unknown => write!(f, "Unknown error"),
        }
    }
}

impl From<ffi::NulError> for NotificationCreationError {
    fn from(src: ffi::NulError) -> Self {
        NotificationCreationError::NulError(src)
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = try!(CString::new(app_name));
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitError);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self,
                            summary: &str,
                            body: Option<&str>,
                            icon: Option<&str>)
                            -> Result<Notification, NotificationCreationError> {
        let summary = try!(CString::new(summary));
        let body = match body {
            Some(body) => Some(try!(CString::new(body))),
            None => None,
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null(),
        };
        let icon = match icon {
            Some(icon) => Some(try!(CString::new(icon))),
            None => None,
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null(),
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification {
                handle: n,
                _phantom: PhantomData,
            })
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>,
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), NotificationShowError> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                let result = Err(NotificationShowError {
                    message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
                });
                glib::g_error_free(err);
                return result;
            }
            Ok(())
        }
    }
}

/// An error that can happen when attempting to show a notification.
#[derive(Debug)]
pub struct NotificationShowError {
    message: String,
}

impl fmt::Display for NotificationShowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Error showing notification: {}", self.message)
    }
}

impl Error for NotificationShowError {
    fn description(&self) -> &str {
        "Notification show error"
    }
}
<|endoftext|>


<commit_before>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     stdout().write_all(data).unwrap();
//!     Ok(data.len())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.
//!
//! # Initialization
//!
//! The underlying libcurl library must be initialized before use and has
//! certain requirements on how this is done. Check the documentation for
//! [`init`] for more details.

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/curl/0.4")]

use std::ffi::CStr;
use std::str;
use std::sync::Once;

pub use crate::error::{Error, FormError, MultiError, ShareError};
mod error;

pub use crate::version::{Protocols, Version};
mod version;

pub mod easy;
pub mod multi;
mod panic;

/// Initializes the underlying libcurl library.
///
/// The underlying libcurl library must be initialized before use, and must be
/// done so on the main thread before any other threads are created by the
/// program. This crate will do this for you automatically in the following
/// scenarios:
///
/// - Creating a new [`Easy`][easy::Easy] or [`Multi`][multi::Multi] handle
/// - At program startup on Windows, macOS, Linux, Android, or FreeBSD systems
///
/// This should be sufficient for most applications and scenarios, but in any
/// other case, it is strongly recommended that you call this function manually
/// as soon as your program starts.
///
/// Calling this function more than once is harmless and has no effect.
#[inline]
pub fn init() {
    /// Used to prevent concurrent or duplicate initialization.
    static INIT: Once = Once::new();

    /// An exported constructor function. On supported platforms, this will be
    /// invoked automatically before the program's `main` is called.
    #[cfg_attr(
        any(target_os = "linux", target_os = "freebsd", target_os = "android"),
        link_section = ".init_array"
    )]
    #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
    #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
    static INIT_CTOR: extern "C" fn() = init_inner;

    /// This is the body of our constructor function.
    #[cfg_attr(
        any(target_os = "linux", target_os = "android"),
        link_section = ".text.startup"
    )]
    extern "C" fn init_inner() {
        INIT.call_once(|| {
            #[cfg(need_openssl_init)]
            openssl_probe::init_ssl_cert_env_vars();
            #[cfg(need_openssl_init)]
            openssl_sys::init();

            unsafe {
                assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
            }

            // Note that we explicitly don't schedule a call to
            // `curl_global_cleanup`. The documentation for that function says
            //
            // > You must not call it when any other thread in the program (i.e.
            // > a thread sharing the same memory) is running. This doesn't just
            // > mean no other thread that is using libcurl.
            //
            // We can't ever be sure of that, so unfortunately we can't call the
            // function.
        });
    }

    // We invoke our init function through our static to ensure the symbol isn't
    // optimized away by a bug: https://github.com/rust-lang/rust/issues/47384
    INIT_CTOR();
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}
<commit_msg>Refactor init to avoid link bugs on macOS Monterey (#426)<commit_after>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     stdout().write_all(data).unwrap();
//!     Ok(data.len())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.
//!
//! # Initialization
//!
//! The underlying libcurl library must be initialized before use and has
//! certain requirements on how this is done. Check the documentation for
//! [`init`] for more details.

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/curl/0.4")]

use std::ffi::CStr;
use std::str;
use std::sync::Once;

pub use crate::error::{Error, FormError, MultiError, ShareError};
mod error;

pub use crate::version::{Protocols, Version};
mod version;

pub mod easy;
pub mod multi;
mod panic;

#[cfg(test)]
static INITIALIZED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);

/// Initializes the underlying libcurl library.
///
/// The underlying libcurl library must be initialized before use, and must be
/// done so on the main thread before any other threads are created by the
/// program. This crate will do this for you automatically in the following
/// scenarios:
///
/// - Creating a new [`Easy`][easy::Easy] or [`Multi`][multi::Multi] handle
/// - At program startup on Windows, macOS, Linux, Android, or FreeBSD systems
///
/// This should be sufficient for most applications and scenarios, but in any
/// other case, it is strongly recommended that you call this function manually
/// as soon as your program starts.
///
/// Calling this function more than once is harmless and has no effect.
#[inline]
pub fn init() {
    /// Used to prevent concurrent or duplicate initialization.
    static INIT: Once = Once::new();

    INIT.call_once(|| {
        #[cfg(need_openssl_init)]
        openssl_probe::init_ssl_cert_env_vars();
        #[cfg(need_openssl_init)]
        openssl_sys::init();

        unsafe {
            assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
        }

        #[cfg(test)]
        {
            INITIALIZED.store(true, std::sync::atomic::Ordering::SeqCst);
        }

        // Note that we explicitly don't schedule a call to
        // `curl_global_cleanup`. The documentation for that function says
        //
        // > You must not call it when any other thread in the program (i.e. a
        // > thread sharing the same memory) is running. This doesn't just mean
        // > no other thread that is using libcurl.
        //
        // We can't ever be sure of that, so unfortunately we can't call the
        // function.
    });
}

/// An exported constructor function. On supported platforms, this will be
/// invoked automatically before the program's `main` is called. This is done
/// for the convenience of library users since otherwise the thread-safety rules
/// around initialization can be difficult to fulfill.
///
/// This is a hidden public item to ensure the symbol isn't optimized away by a
/// rustc/LLVM bug: https://github.com/rust-lang/rust/issues/47384. As long as
/// any item in this module is used by the final binary (which `init` will be)
/// then this symbol should be preserved.
#[used]
#[doc(hidden)]
#[cfg_attr(
    any(target_os = "linux", target_os = "freebsd", target_os = "android"),
    link_section = ".init_array"
)]
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
pub static INIT_CTOR: extern "C" fn() = {
    /// This is the body of our constructor function.
    #[cfg_attr(
        any(target_os = "linux", target_os = "android"),
        link_section = ".text.startup"
    )]
    extern "C" fn init_ctor() {
        init();
    }

    init_ctor
};

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}

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

    #[test]
    #[cfg(any(
        target_os = "linux",
        target_os = "macos",
        target_os = "windows",
        target_os = "freebsd",
        target_os = "android"
    ))]
    fn is_initialized_before_main() {
        assert!(INITIALIZED.load(std::sync::atomic::Ordering::SeqCst));
    }
}
<|endoftext|>


<commit_before>//! `rust-sqlite3` is a rustic binding to the [sqlite3 API][].
//!
//! [sqlite3 API]: http://www.sqlite.org/c3ref/intro.html
//!
//! ```rust
//! extern crate time;
//! extern crate sqlite3;
//!
//! use time::Timespec;
//!
//!
//! use sqlite3::{DatabaseConnection, SqliteResult};
//! use sqlite3::{SQLITE_NULL, SQLITE_TEXT};
//!
//! #[deriving(Show)]
//! struct Person {
//!     id: i32,
//!     name: String,
//!     time_created: Timespec,
//!     // TODO: data: Option<Vec<u8>>
//! }
//!
//! pub fn main() {
//!     match io() {
//!         Ok(ppl) => println!("Found people: {}", ppl),
//!         Err(oops) => fail!(oops)
//!     }
//! }
//!
//! fn io() -> SqliteResult<Vec<Person>> {
//!     let mut conn = try!(DatabaseConnection::new());
//!
//!     try!(conn.exec("CREATE TABLE person (
//!                  id              SERIAL PRIMARY KEY,
//!                  name            VARCHAR NOT NULL,
//!                  time_created    TIMESTAMP NOT NULL
//!                )"));
//!
//!     let me = Person {
//!         id: 0,
//!         name: "Dan".to_string(),
//!         time_created: time::get_time(),
//!     };
//!     {
//!         let mut tx = try!(conn.prepare("INSERT INTO person (name, time_created)
//!                            VALUES ($1, $2)"));
//!         let changes = try!(conn.update(&mut tx, [&me.name, &me.time_created]));
//!         assert_eq!(changes, 1);
//!     }
//!
//!     let mut stmt = try!(conn.prepare("SELECT id, name, time_created FROM person"));
//!
//!     let mut ppl = vec!();
//!     try!(stmt.query(
//!         [],
//!         |row| {
//!             Ok(Person {
//!                 id: row.get(0u),
//!                 name: row.get(1u),
//!                 time_created: row.get(2u)
//!             })
//!         },
//!         (),
//!         |_, person| { ppl.push(person) }));
//!     Ok(ppl)
//! }
//! ```

#![crate_name = "sqlite3"]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]

extern crate libc;
extern crate time;

use std::fmt::Show;

pub use core::{DatabaseConnection, PreparedStatement, ResultSet, ResultRow};
pub use types::{FromSql, ToSql};

pub mod core;
pub mod types;

/// bindgen-bindings to libsqlite3
#[allow(non_camel_case_types, dead_code)]
pub mod ffi;

pub mod access;

impl core::DatabaseConnection {
    /// Execute a statement after binding any parameters.
    ///
    /// When the statement is done, The [number of rows
    /// modified][changes] is reported.
    ///
    /// [changes]: http://www.sqlite.org/c3ref/changes.html
    pub fn update<'db, 's>(&'db mut self,
                           stmt: &'s mut PreparedStatement<'s>,
                           values: &[&ToSql]) -> SqliteResult<uint> {
        let check = {
            try!(bind_values(stmt, values));
            let mut results = stmt.execute();
            match results.step() {
                None => Ok(()),
                Some(Ok(_row)) => Err(SQLITE_MISUSE),
                Some(Err(e)) => Err(e)
            }
        };
        check.map(|_ok| self.changes())
    }
}

impl<'s> core::PreparedStatement<'s> {
    /// Fold query results, after binding parameters.
    pub fn query<T, U>(&'s mut self,
                       values: &[&ToSql],
                       each_row: |&mut ResultRow|: 's -> SqliteResult<T>,
                       init: U,
                       accum: |U, T| -> U
                       ) -> SqliteResult<U> {
        try!(bind_values(self, values));
        let mut results = self.execute();
        let mut acc = init;
        loop {
            match results.step() {
                None => break,
                Some(Ok(ref mut row)) => match each_row(row) {
                    Ok(t) => acc = accum(acc, t),
                    Err(e) => return Err(e)
                },
                Some(Err(e)) => return Err(e)
            }
        }
        Ok(acc)
    }
}

fn bind_values<'db>(s: &'db mut PreparedStatement, values: &[&ToSql]) -> SqliteResult<()> {
    for (ix, v) in values.iter().enumerate() {
        try!(v.to_sql(s, ix + 1));
    }
    Ok(())
}

impl<'s, 'r> core::ResultRow<'s, 'r> {
    pub fn get<I: RowIndex + Show + Clone, T: FromSql>(&mut self, idx: I) -> T {
        match self.get_opt(idx.clone()) {
            Ok(ok) => ok,
            Err(err) => fail!("retrieving column {}: {}", idx, err)
        }
    }

    pub fn get_opt<I: RowIndex, T: FromSql>(&mut self, idx: I) -> SqliteResult<T> {
        match idx.idx(self) {
            Some(idx) => FromSql::from_sql(self, idx),
            None => Err(SQLITE_MISUSE)
        }
    }

}

/// A trait implemented by types that can index into columns of a row.
///
/// *inspired by sfackler's [RowIndex][]*
/// [RowIndex]: http://www.rust-ci.org/sfackler/rust-postgres/doc/postgres/trait.RowIndex.html
pub trait RowIndex {
    fn idx(&self, row: &mut ResultRow) -> Option<uint>;
}

impl RowIndex for uint {
    fn idx(&self, _row: &mut ResultRow) -> Option<uint> { Some(*self) }
}

impl RowIndex for &'static str {
    fn idx(&self, row: &mut ResultRow) -> Option<uint> {
        let mut ixs = range(0, row.column_count());
        ixs.find(|ix| row.with_column_name(*ix, false, |name| name == *self))
    }
}

/// The type used for returning and propagating sqlite3 errors.
#[must_use]
pub type SqliteResult<T> = Result<T, SqliteError>;

/// Result codes for errors.
///
/// cf. [sqlite3 result codes][codes].
///
/// Note `SQLITE_OK` is not included; we use `Ok(...)` instead.
///
/// Likewise, in place of `SQLITE_ROW` and `SQLITE_DONE`, we return
/// `Some(...)` or `None` from `ResultSet::next()`.
///
/// [codes]: http://www.sqlite.org/c3ref/c_abort.html
#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteError {
    SQLITE_ERROR     =  1,
    SQLITE_INTERNAL  =  2,
    SQLITE_PERM      =  3,
    SQLITE_ABORT     =  4,
    SQLITE_BUSY      =  5,
    SQLITE_LOCKED    =  6,
    SQLITE_NOMEM     =  7,
    SQLITE_READONLY  =  8,
    SQLITE_INTERRUPT =  9,
    SQLITE_IOERR     = 10,
    SQLITE_CORRUPT   = 11,
    SQLITE_NOTFOUND  = 12,
    SQLITE_FULL      = 13,
    SQLITE_CANTOPEN  = 14,
    SQLITE_PROTOCOL  = 15,
    SQLITE_EMPTY     = 16,
    SQLITE_SCHEMA    = 17,
    SQLITE_TOOBIG    = 18,
    SQLITE_CONSTRAINT= 19,
    SQLITE_MISMATCH  = 20,
    SQLITE_MISUSE    = 21,
    SQLITE_NOLFS     = 22,
    SQLITE_AUTH      = 23,
    SQLITE_FORMAT    = 24,
    SQLITE_RANGE     = 25,
    SQLITE_NOTADB    = 26
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum ColumnType {
    SQLITE_INTEGER = 1,
    SQLITE_FLOAT   = 2,
    SQLITE_TEXT    = 3,
    SQLITE_BLOB    = 4,
    SQLITE_NULL    = 5
}

#[cfg(test)]
mod bind_tests {
    use super::{DatabaseConnection, ResultSet};
    use super::{SqliteResult};

    #[test]
    fn bind_fun() {
        fn go() -> SqliteResult<()> {
            let mut database = try!(DatabaseConnection::new());

            try!(database.exec(
                "BEGIN;
                CREATE TABLE test (id int, name text, address text);
                INSERT INTO test (id, name, address) VALUES (1, 'John Doe', '123 w Pine');
                COMMIT;"));

            {
                let mut tx = try!(database.prepare(
                    "INSERT INTO test (id, name, address) VALUES (?, ?, ?)"));
                try!(tx.bind_int(1, 2));
                try!(tx.bind_text(2, "Jane Doe"));
                try!(tx.bind_text(3, "345 e Walnut"));
                let mut results = tx.execute();
                assert!(results.step().is_none());
            }
            assert_eq!(database.changes(), 1);

            let mut q = try!(database.prepare("select * from test order by id"));
            let mut rows = q.execute();
            match rows.step() {
                Some(Ok(ref mut row)) => {
                    assert_eq!(row.get::<uint, i32>(0), 1);
                    // TODO let name = q.get_text(1);
                    // assert_eq!(name.as_slice(), "John Doe");
                },
                _ => fail!()
            }

            match rows.step() {
                Some(Ok(ref mut row)) => {
                    assert_eq!(row.get::<uint, i32>(0), 2);
                    //TODO let addr = q.get_text(2);
                    // assert_eq!(addr.as_slice(), "345 e Walnut");
                },
                _ => fail!()
            }
            Ok(())
        }
        match go() {
            Ok(_) => (),
            Err(e) => fail!("oops! {}", e)
        }
    }

    fn with_query<T>(sql: &str, f: |rows: &mut ResultSet| -> T) -> SqliteResult<T> {
        let mut db = try!(DatabaseConnection::new());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn named_rowindex() {
        fn go() -> SqliteResult<(uint, i32)> {
            let mut count = 0;
            let mut sum = 0;

            with_query("select 1 as col1
                       union all
                       select 2", |rows| {
                loop {
                    match rows.step() {
                        Some(Ok(ref mut row)) => {
                            count += 1;
                            sum += row.get("col1")
                        },
                        _ => break
                    }
                }
                (count, sum)
            })
        }
        assert_eq!(go(), Ok((2, 3)))
    }
}
<commit_msg>oops... taking out some assert_eq!()s left unused imports<commit_after>//! `rust-sqlite3` is a rustic binding to the [sqlite3 API][].
//!
//! [sqlite3 API]: http://www.sqlite.org/c3ref/intro.html
//!
//! ```rust
//! extern crate time;
//! extern crate sqlite3;
//!
//! use time::Timespec;
//!
//!
//! use sqlite3::{DatabaseConnection, SqliteResult};
//!
//! #[deriving(Show)]
//! struct Person {
//!     id: i32,
//!     name: String,
//!     time_created: Timespec,
//!     // TODO: data: Option<Vec<u8>>
//! }
//!
//! pub fn main() {
//!     match io() {
//!         Ok(ppl) => println!("Found people: {}", ppl),
//!         Err(oops) => fail!(oops)
//!     }
//! }
//!
//! fn io() -> SqliteResult<Vec<Person>> {
//!     let mut conn = try!(DatabaseConnection::new());
//!
//!     try!(conn.exec("CREATE TABLE person (
//!                  id              SERIAL PRIMARY KEY,
//!                  name            VARCHAR NOT NULL,
//!                  time_created    TIMESTAMP NOT NULL
//!                )"));
//!
//!     let me = Person {
//!         id: 0,
//!         name: "Dan".to_string(),
//!         time_created: time::get_time(),
//!     };
//!     {
//!         let mut tx = try!(conn.prepare("INSERT INTO person (name, time_created)
//!                            VALUES ($1, $2)"));
//!         let changes = try!(conn.update(&mut tx, [&me.name, &me.time_created]));
//!         assert_eq!(changes, 1);
//!     }
//!
//!     let mut stmt = try!(conn.prepare("SELECT id, name, time_created FROM person"));
//!
//!     let mut ppl = vec!();
//!     try!(stmt.query(
//!         [],
//!         |row| {
//!             Ok(Person {
//!                 id: row.get(0u),
//!                 name: row.get(1u),
//!                 time_created: row.get(2u)
//!             })
//!         },
//!         (),
//!         |_, person| { ppl.push(person) }));
//!     Ok(ppl)
//! }
//! ```

#![crate_name = "sqlite3"]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]

extern crate libc;
extern crate time;

use std::fmt::Show;

pub use core::{DatabaseConnection, PreparedStatement, ResultSet, ResultRow};
pub use types::{FromSql, ToSql};

pub mod core;
pub mod types;

/// bindgen-bindings to libsqlite3
#[allow(non_camel_case_types, dead_code)]
pub mod ffi;

pub mod access;

impl core::DatabaseConnection {
    /// Execute a statement after binding any parameters.
    ///
    /// When the statement is done, The [number of rows
    /// modified][changes] is reported.
    ///
    /// [changes]: http://www.sqlite.org/c3ref/changes.html
    pub fn update<'db, 's>(&'db mut self,
                           stmt: &'s mut PreparedStatement<'s>,
                           values: &[&ToSql]) -> SqliteResult<uint> {
        let check = {
            try!(bind_values(stmt, values));
            let mut results = stmt.execute();
            match results.step() {
                None => Ok(()),
                Some(Ok(_row)) => Err(SQLITE_MISUSE),
                Some(Err(e)) => Err(e)
            }
        };
        check.map(|_ok| self.changes())
    }
}

impl<'s> core::PreparedStatement<'s> {
    /// Fold query results, after binding parameters.
    pub fn query<T, U>(&'s mut self,
                       values: &[&ToSql],
                       each_row: |&mut ResultRow|: 's -> SqliteResult<T>,
                       init: U,
                       accum: |U, T| -> U
                       ) -> SqliteResult<U> {
        try!(bind_values(self, values));
        let mut results = self.execute();
        let mut acc = init;
        loop {
            match results.step() {
                None => break,
                Some(Ok(ref mut row)) => match each_row(row) {
                    Ok(t) => acc = accum(acc, t),
                    Err(e) => return Err(e)
                },
                Some(Err(e)) => return Err(e)
            }
        }
        Ok(acc)
    }
}

fn bind_values<'db>(s: &'db mut PreparedStatement, values: &[&ToSql]) -> SqliteResult<()> {
    for (ix, v) in values.iter().enumerate() {
        try!(v.to_sql(s, ix + 1));
    }
    Ok(())
}

impl<'s, 'r> core::ResultRow<'s, 'r> {
    pub fn get<I: RowIndex + Show + Clone, T: FromSql>(&mut self, idx: I) -> T {
        match self.get_opt(idx.clone()) {
            Ok(ok) => ok,
            Err(err) => fail!("retrieving column {}: {}", idx, err)
        }
    }

    pub fn get_opt<I: RowIndex, T: FromSql>(&mut self, idx: I) -> SqliteResult<T> {
        match idx.idx(self) {
            Some(idx) => FromSql::from_sql(self, idx),
            None => Err(SQLITE_MISUSE)
        }
    }

}

/// A trait implemented by types that can index into columns of a row.
///
/// *inspired by sfackler's [RowIndex][]*
/// [RowIndex]: http://www.rust-ci.org/sfackler/rust-postgres/doc/postgres/trait.RowIndex.html
pub trait RowIndex {
    fn idx(&self, row: &mut ResultRow) -> Option<uint>;
}

impl RowIndex for uint {
    fn idx(&self, _row: &mut ResultRow) -> Option<uint> { Some(*self) }
}

impl RowIndex for &'static str {
    fn idx(&self, row: &mut ResultRow) -> Option<uint> {
        let mut ixs = range(0, row.column_count());
        ixs.find(|ix| row.with_column_name(*ix, false, |name| name == *self))
    }
}

/// The type used for returning and propagating sqlite3 errors.
#[must_use]
pub type SqliteResult<T> = Result<T, SqliteError>;

/// Result codes for errors.
///
/// cf. [sqlite3 result codes][codes].
///
/// Note `SQLITE_OK` is not included; we use `Ok(...)` instead.
///
/// Likewise, in place of `SQLITE_ROW` and `SQLITE_DONE`, we return
/// `Some(...)` or `None` from `ResultSet::next()`.
///
/// [codes]: http://www.sqlite.org/c3ref/c_abort.html
#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteError {
    SQLITE_ERROR     =  1,
    SQLITE_INTERNAL  =  2,
    SQLITE_PERM      =  3,
    SQLITE_ABORT     =  4,
    SQLITE_BUSY      =  5,
    SQLITE_LOCKED    =  6,
    SQLITE_NOMEM     =  7,
    SQLITE_READONLY  =  8,
    SQLITE_INTERRUPT =  9,
    SQLITE_IOERR     = 10,
    SQLITE_CORRUPT   = 11,
    SQLITE_NOTFOUND  = 12,
    SQLITE_FULL      = 13,
    SQLITE_CANTOPEN  = 14,
    SQLITE_PROTOCOL  = 15,
    SQLITE_EMPTY     = 16,
    SQLITE_SCHEMA    = 17,
    SQLITE_TOOBIG    = 18,
    SQLITE_CONSTRAINT= 19,
    SQLITE_MISMATCH  = 20,
    SQLITE_MISUSE    = 21,
    SQLITE_NOLFS     = 22,
    SQLITE_AUTH      = 23,
    SQLITE_FORMAT    = 24,
    SQLITE_RANGE     = 25,
    SQLITE_NOTADB    = 26
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum ColumnType {
    SQLITE_INTEGER = 1,
    SQLITE_FLOAT   = 2,
    SQLITE_TEXT    = 3,
    SQLITE_BLOB    = 4,
    SQLITE_NULL    = 5
}

#[cfg(test)]
mod bind_tests {
    use super::{DatabaseConnection, ResultSet};
    use super::{SqliteResult};

    #[test]
    fn bind_fun() {
        fn go() -> SqliteResult<()> {
            let mut database = try!(DatabaseConnection::new());

            try!(database.exec(
                "BEGIN;
                CREATE TABLE test (id int, name text, address text);
                INSERT INTO test (id, name, address) VALUES (1, 'John Doe', '123 w Pine');
                COMMIT;"));

            {
                let mut tx = try!(database.prepare(
                    "INSERT INTO test (id, name, address) VALUES (?, ?, ?)"));
                try!(tx.bind_int(1, 2));
                try!(tx.bind_text(2, "Jane Doe"));
                try!(tx.bind_text(3, "345 e Walnut"));
                let mut results = tx.execute();
                assert!(results.step().is_none());
            }
            assert_eq!(database.changes(), 1);

            let mut q = try!(database.prepare("select * from test order by id"));
            let mut rows = q.execute();
            match rows.step() {
                Some(Ok(ref mut row)) => {
                    assert_eq!(row.get::<uint, i32>(0), 1);
                    // TODO let name = q.get_text(1);
                    // assert_eq!(name.as_slice(), "John Doe");
                },
                _ => fail!()
            }

            match rows.step() {
                Some(Ok(ref mut row)) => {
                    assert_eq!(row.get::<uint, i32>(0), 2);
                    //TODO let addr = q.get_text(2);
                    // assert_eq!(addr.as_slice(), "345 e Walnut");
                },
                _ => fail!()
            }
            Ok(())
        }
        match go() {
            Ok(_) => (),
            Err(e) => fail!("oops! {}", e)
        }
    }

    fn with_query<T>(sql: &str, f: |rows: &mut ResultSet| -> T) -> SqliteResult<T> {
        let mut db = try!(DatabaseConnection::new());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn named_rowindex() {
        fn go() -> SqliteResult<(uint, i32)> {
            let mut count = 0;
            let mut sum = 0;

            with_query("select 1 as col1
                       union all
                       select 2", |rows| {
                loop {
                    match rows.step() {
                        Some(Ok(ref mut row)) => {
                            count += 1;
                            sum += row.get("col1")
                        },
                        _ => break
                    }
                }
                (count, sum)
            })
        }
        assert_eq!(go(), Ok((2, 3)))
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotCommandCenter::new();

    for line in input.lines() {
        br.exec_command(line);
    }

    br.outputs.get(&0).unwrap().first().unwrap() *
        br.outputs.get(&1).unwrap().first().unwrap() *
        br.outputs.get(&2).unwrap().first().unwrap()
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
            self.process_bots();
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);

                if let Some(command) = self.saved_commands.remove(&check_bot_key) {
                    println!("COMMAND CTR found command: {:?}", command);
                    let (low_value, high_value) = self.bot_low_high(check_bot_key);
                    println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                    match command.low_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.low_value_key,
                            low_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.low_value_key,
                            low_value
                        ),
                    }

                    match command.high_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.high_value_key,
                            high_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.high_value_key,
                            high_value
                        ),
                    }
                } else {
                    println!("COMMAND CTR found no saved command for bot {} that has two chips", check_bot_key);
                }

            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    println!("Bot {} found {} < {}", self.key, c1, c2);
                    (c1, c2)
                } else {
                    println!("Bot {} found {} < {}", self.key, c2, c1);
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<commit_msg>Setup for day 11<commit_after>
pub fn puzzle(input: &str) -> usize {
    0
}

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

}
<|endoftext|>


<commit_before>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![deny(future_incompatible)]
#![deny(nonstandard_style)]
#![deny(rust_2018_idioms)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unsafe_code)]
#![deny(unused_qualifications)]
#![deny(clippy::doc_markdown)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::use_self)]
#![allow(clippy::default_trait_access)]
#![allow(clippy::enum_glob_use)]
#![deny(clippy::replace_consts)]
#![deny(clippy::explicit_iter_loop)]
#![deny(clippy::match_same_arms)]
#![deny(clippy::used_underscore_binding)]
#![deny(clippy::inline_always)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::shadow_unrelated)]
#![deny(clippy::shadow_same)]
#![deny(clippy::shadow_reuse)]
#![deny(clippy::cast_possible_truncation)]
#![deny(clippy::cast_possible_wrap)]
#![deny(clippy::cast_sign_loss)]
#![deny(clippy::cast_precision_loss)]
#![deny(clippy::needless_pass_by_value)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod frag;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod pagetable;
mod prefix;
mod result;
mod stack;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
        pagetable::PAGETABLE_NODE_SZ,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::interpolation_search_lub,
        config::StorageParameters,
        context::Context,
        frag::Frag,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        pagetable::PageTable,
        result::CasResult,
        stack::{node_from_frag_vec, Stack, StackIter},
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(&buf);
    hasher.finalize()
}

type TreePtr<'g> = pagecache::PagePtr<'g>;

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
fn debug_delay() {}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;
<commit_msg>organize the clippy lints better<commit_after>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    clippy::doc_markdown,
    clippy::replace_consts,
    clippy::explicit_iter_loop,
    clippy::match_same_arms,
    clippy::used_underscore_binding,
    clippy::inline_always,
    clippy::cast_lossless,
    clippy::shadow_unrelated,
    clippy::shadow_same,
    clippy::shadow_reuse,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_sign_loss,
    clippy::cast_precision_loss
)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod frag;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod pagetable;
mod prefix;
mod result;
mod stack;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
        pagetable::PAGETABLE_NODE_SZ,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::interpolation_search_lub,
        config::StorageParameters,
        context::Context,
        frag::Frag,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        pagetable::PageTable,
        result::CasResult,
        stack::{node_from_frag_vec, Stack, StackIter},
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(&buf);
    hasher.finalize()
}

type TreePtr<'g> = pagecache::PagePtr<'g>;

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
fn debug_delay() {}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;
<|endoftext|>