<commit_before>//! Some iterator that produces tuples

use std::iter::Fuse;
use std::iter::Take;
use std::iter::Cycle;
use std::marker::PhantomData;

// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
// tuple-related methods to be used by clients in generic contexts, while
// hiding the implementation details of `TupleCollect`.
// See https://github.com/rust-itertools/itertools/issues/387

/// Implemented for homogeneous tuples of size up to 4.
pub trait HomogeneousTuple
    : TupleCollect
{}

impl<T: TupleCollect> HomogeneousTuple for T {}

/// An iterator over a incomplete tuple.
///
/// See [`.tuples()`](crate::Itertools::tuples) and
/// [`Tuples::into_buffer()`].
#[derive(Clone, Debug)]
pub struct TupleBuffer<T>
    where T: HomogeneousTuple
{
    cur: usize,
    buf: T::Buffer,
}

impl<T> TupleBuffer<T>
    where T: HomogeneousTuple
{
    fn new(buf: T::Buffer) -> Self {
        TupleBuffer {
            cur: 0,
            buf,
        }
    }
}

impl<T> Iterator for TupleBuffer<T>
    where T: HomogeneousTuple
{
    type Item = T::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let s = self.buf.as_mut();
        if let Some(ref mut item) = s.get_mut(self.cur) {
            self.cur += 1;
            item.take()
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let buffer = &self.buf.as_ref()[self.cur..];
        let len = if buffer.is_empty() {
            0
        } else {
            buffer.iter()
                  .position(|x| x.is_none())
                  .unwrap_or_else(|| buffer.len())
        };
        (len, Some(len))
    }
}

impl<T> ExactSizeIterator for TupleBuffer<T>
    where T: HomogeneousTuple
{
}

/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](crate::Itertools::tuples) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    iter: Fuse<I>,
    buf: T::Buffer,
}

/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    Tuples {
        iter: iter.fuse(),
        buf: Default::default(),
    }
}

impl<I, T> Iterator for Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        T::collect_from_iter(&mut self.iter, &mut self.buf)
    }
}

impl<I, T> Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut iter = (0..5).tuples();
    /// assert_eq!(Some((0, 1, 2)), iter.next());
    /// assert_eq!(None, iter.next());
    /// itertools::assert_equal(vec![3, 4], iter.into_buffer());
    /// ```
    pub fn into_buffer(self) -> TupleBuffer<T> {
        TupleBuffer::new(self.buf)
    }
}

/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    iter: I,
    last: Option<T>,
}

/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple,
          T::Item: Clone
{
    use std::iter::once;

    let mut last = None;
    if T::num_items() != 1 {
        // put in a duplicate item in front of the tuple; this simplifies
        // .next() function.
        if let Some(item) = iter.next() {
            let iter = once(item.clone()).chain(once(item)).chain(&mut iter);
            last = T::collect_from_iter_no_buf(iter);
        }
    }

    TupleWindows {
        last,
        iter,
    }
}

impl<I, T> Iterator for TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple + Clone,
          T::Item: Clone
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if T::num_items() == 1 {
            return T::collect_from_iter_no_buf(&mut self.iter)
        }
        if let Some(ref mut last) = self.last {
            if let Some(new) = self.iter.next() {
                last.left_shift_push(new);
                return Some(last.clone());
            }
        }
        None
    }
}

/// An iterator over all windows,wrapping back to the first elements when the
/// window would otherwise exceed the length of the iterator, producing tuples
/// of a specific size.
///
/// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct CircularTupleWindows<I, T: Clone>
    where I: Iterator<Item = T::Item> + Clone,
          T: TupleCollect + Clone
{
    iter: Take<TupleWindows<Cycle<I>, T>>,
    phantom_data: PhantomData<T>
}

pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T>
    where I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
          T: TupleCollect + Clone,
          T::Item: Clone
{
    let len = iter.len();
    let iter = tuple_windows(iter.cycle()).take(len);

    CircularTupleWindows {
        iter,
        phantom_data: PhantomData{}
    }
}

impl<I, T> Iterator for CircularTupleWindows<I, T>
    where I: Iterator<Item = T::Item> + Clone,
          T: TupleCollect + Clone,
          T::Item: Clone
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

pub trait TupleCollect: Sized {
    type Item;
    type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;

    fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
        where I: IntoIterator<Item = Self::Item>;

    fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
        where I: IntoIterator<Item = Self::Item>;

    fn num_items() -> usize;

    fn left_shift_push(&mut self, item: Self::Item);
}

macro_rules! count_ident{
    () => {0};
    ($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)};
}
macro_rules! rev_for_each_ident{
    ($m:ident, ) => {};
    ($m:ident, $i0:ident, $($i:ident,)*) => {
        rev_for_each_ident!($m, $($i,)*);
        $m!($i0);
    };
}

macro_rules! impl_tuple_collect {
    ($dummy:ident,) => {}; // stop
    ($dummy:ident, $($Y:ident,)*) => (
        impl_tuple_collect!($($Y,)*);
        impl<A> TupleCollect for ($(ignore_ident!($Y, A),)*) {
            type Item = A;
            type Buffer = [Option<A>; count_ident!($($Y,)*) - 1];

            #[allow(unused_assignments, unused_mut)]
            fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
                where I: IntoIterator<Item = A>
            {
                let mut iter = iter.into_iter();
                $(
                    let mut $Y = None;
                )*

                loop {
                    $(
                        $Y = iter.next();
                        if $Y.is_none() {
                            break
                        }
                    )*
                    return Some(($($Y.unwrap()),*,))
                }

                let mut i = 0;
                let mut s = buf.as_mut();
                $(
                    if i < s.len() {
                        s[i] = $Y;
                        i += 1;
                    }
                )*
                return None;
            }

            fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
                where I: IntoIterator<Item = A>
            {
                let mut iter = iter.into_iter();

                Some(($(
                    { let $Y = iter.next()?; $Y },
                )*))
            }

            fn num_items() -> usize {
                count_ident!($($Y,)*)
            }

            fn left_shift_push(&mut self, mut item: A) {
                use std::mem::replace;

                let &mut ($(ref mut $Y),*,) = self;
                macro_rules! replace_item{($i:ident) => {
                    item = replace($i, item);
                }};
                rev_for_each_ident!(replace_item, $($Y,)*);
                drop(item);
            }
        }
    )
}
impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,);
<commit_msg>Fix warning<commit_after>//! Some iterator that produces tuples

use std::iter::Fuse;
use std::iter::Take;
use std::iter::Cycle;
use std::marker::PhantomData;

// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
// tuple-related methods to be used by clients in generic contexts, while
// hiding the implementation details of `TupleCollect`.
// See https://github.com/rust-itertools/itertools/issues/387

/// Implemented for homogeneous tuples of size up to 4.
pub trait HomogeneousTuple
    : TupleCollect
{}

impl<T: TupleCollect> HomogeneousTuple for T {}

/// An iterator over a incomplete tuple.
///
/// See [`.tuples()`](crate::Itertools::tuples) and
/// [`Tuples::into_buffer()`].
#[derive(Clone, Debug)]
pub struct TupleBuffer<T>
    where T: HomogeneousTuple
{
    cur: usize,
    buf: T::Buffer,
}

impl<T> TupleBuffer<T>
    where T: HomogeneousTuple
{
    fn new(buf: T::Buffer) -> Self {
        TupleBuffer {
            cur: 0,
            buf,
        }
    }
}

impl<T> Iterator for TupleBuffer<T>
    where T: HomogeneousTuple
{
    type Item = T::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let s = self.buf.as_mut();
        if let Some(ref mut item) = s.get_mut(self.cur) {
            self.cur += 1;
            item.take()
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let buffer = &self.buf.as_ref()[self.cur..];
        let len = if buffer.is_empty() {
            0
        } else {
            buffer.iter()
                  .position(|x| x.is_none())
                  .unwrap_or_else(|| buffer.len())
        };
        (len, Some(len))
    }
}

impl<T> ExactSizeIterator for TupleBuffer<T>
    where T: HomogeneousTuple
{
}

/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](crate::Itertools::tuples) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    iter: Fuse<I>,
    buf: T::Buffer,
}

/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    Tuples {
        iter: iter.fuse(),
        buf: Default::default(),
    }
}

impl<I, T> Iterator for Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        T::collect_from_iter(&mut self.iter, &mut self.buf)
    }
}

impl<I, T> Tuples<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let mut iter = (0..5).tuples();
    /// assert_eq!(Some((0, 1, 2)), iter.next());
    /// assert_eq!(None, iter.next());
    /// itertools::assert_equal(vec![3, 4], iter.into_buffer());
    /// ```
    pub fn into_buffer(self) -> TupleBuffer<T> {
        TupleBuffer::new(self.buf)
    }
}

/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple
{
    iter: I,
    last: Option<T>,
}

/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple,
          T::Item: Clone
{
    use std::iter::once;

    let mut last = None;
    if T::num_items() != 1 {
        // put in a duplicate item in front of the tuple; this simplifies
        // .next() function.
        if let Some(item) = iter.next() {
            let iter = once(item.clone()).chain(once(item)).chain(&mut iter);
            last = T::collect_from_iter_no_buf(iter);
        }
    }

    TupleWindows {
        last,
        iter,
    }
}

impl<I, T> Iterator for TupleWindows<I, T>
    where I: Iterator<Item = T::Item>,
          T: HomogeneousTuple + Clone,
          T::Item: Clone
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if T::num_items() == 1 {
            return T::collect_from_iter_no_buf(&mut self.iter)
        }
        if let Some(ref mut last) = self.last {
            if let Some(new) = self.iter.next() {
                last.left_shift_push(new);
                return Some(last.clone());
            }
        }
        None
    }
}

/// An iterator over all windows,wrapping back to the first elements when the
/// window would otherwise exceed the length of the iterator, producing tuples
/// of a specific size.
///
/// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct CircularTupleWindows<I, T: Clone>
    where I: Iterator<Item = T::Item> + Clone,
          T: TupleCollect + Clone
{
    iter: Take<TupleWindows<Cycle<I>, T>>,
    phantom_data: PhantomData<T>
}

pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T>
    where I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
          T: TupleCollect + Clone,
          T::Item: Clone
{
    let len = iter.len();
    let iter = tuple_windows(iter.cycle()).take(len);

    CircularTupleWindows {
        iter,
        phantom_data: PhantomData{}
    }
}

impl<I, T> Iterator for CircularTupleWindows<I, T>
    where I: Iterator<Item = T::Item> + Clone,
          T: TupleCollect + Clone,
          T::Item: Clone
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

pub trait TupleCollect: Sized {
    type Item;
    type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;

    fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
        where I: IntoIterator<Item = Self::Item>;

    fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
        where I: IntoIterator<Item = Self::Item>;

    fn num_items() -> usize;

    fn left_shift_push(&mut self, item: Self::Item);
}

macro_rules! count_ident{
    () => {0};
    ($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)};
}
macro_rules! rev_for_each_ident{
    ($m:ident, ) => {};
    ($m:ident, $i0:ident, $($i:ident,)*) => {
        rev_for_each_ident!($m, $($i,)*);
        $m!($i0);
    };
}

macro_rules! impl_tuple_collect {
    ($dummy:ident,) => {}; // stop
    ($dummy:ident, $($Y:ident,)*) => (
        impl_tuple_collect!($($Y,)*);
        impl<A> TupleCollect for ($(ignore_ident!($Y, A),)*) {
            type Item = A;
            type Buffer = [Option<A>; count_ident!($($Y,)*) - 1];

            #[allow(unused_assignments, unused_mut)]
            fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
                where I: IntoIterator<Item = A>
            {
                let mut iter = iter.into_iter();
                $(
                    let mut $Y = None;
                )*

                loop {
                    $(
                        $Y = iter.next();
                        if $Y.is_none() {
                            break
                        }
                    )*
                    return Some(($($Y.unwrap()),*,))
                }

                let mut i = 0;
                let mut s = buf.as_mut();
                $(
                    if i < s.len() {
                        s[i] = $Y;
                        i += 1;
                    }
                )*
                return None;
            }

            fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
                where I: IntoIterator<Item = A>
            {
                let mut iter = iter.into_iter();

                Some(($(
                    { let $Y = iter.next()?; $Y },
                )*))
            }

            fn num_items() -> usize {
                count_ident!($($Y,)*)
            }

            fn left_shift_push(&mut self, mut item: A) {
                use std::mem::replace;

                let &mut ($(ref mut $Y),*,) = self;
                macro_rules! replace_item{($i:ident) => {
                    item = replace($i, item);
                }}
                rev_for_each_ident!(replace_item, $($Y,)*);
                drop(item);
            }
        }
    )
}
impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,);
<|endoftext|>


<commit_before>extern crate time;

use Result;
use types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};

const SQLITE_DATETIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S:%f";

impl ToSql for time::Timespec {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        let time_string = time::at_utc(*self)
            .strftime(SQLITE_DATETIME_FMT)
            .unwrap()
            .to_string();
        Ok(ToSqlOutput::from(time_string))
    }
}

impl FromSql for time::Timespec {
    fn column_result(value: ValueRef) -> FromSqlResult<Self> {
        value
            .as_str()
            .and_then(|s| match time::strptime(s, SQLITE_DATETIME_FMT) {
                          Ok(tm) => Ok(tm.to_timespec()),
                          Err(err) => Err(FromSqlError::Other(Box::new(err))),
                      })
    }
}

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

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")
            .unwrap();
        db
    }

    #[test]
    fn test_timespec() {
        let db = checked_memory_handle();

        let mut ts_vec = vec![];

        ts_vec.push(time::Timespec::new(10_000, 0));//January 1, 1970 2:46:40 AM
        ts_vec.push(time::Timespec::new(10_000, 1000));//January 1, 1970 2:46:40 AM (and one microsecond)
        ts_vec.push(time::Timespec::new(1500391124, 1_000_000));//July 18, 2017
        ts_vec.push(time::Timespec::new(2000000000, 2_000_000));//May 18, 2033
        ts_vec.push(time::Timespec::new(3000000000, 999_999_999));//January 24, 2065
        ts_vec.push(time::Timespec::new(10000000000, 0));//November 20, 2286

        for ts in ts_vec {

            db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts])
                .unwrap();

            let from: time::Timespec = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
                .unwrap();

            db.execute("DELETE FROM foo", &[]).unwrap();

            assert_eq!(from, ts);
        }

    }
}
<commit_msg>fixed timezone issue<commit_after>extern crate time;

use Result;
use types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};

const SQLITE_DATETIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S:%f %Z";

impl ToSql for time::Timespec {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        let time_string = time::at_utc(*self)
            .strftime(SQLITE_DATETIME_FMT)
            .unwrap()
            .to_string();
        Ok(ToSqlOutput::from(time_string))
    }
}

impl FromSql for time::Timespec {
    fn column_result(value: ValueRef) -> FromSqlResult<Self> {
        value
            .as_str()
            .and_then(|s| match time::strptime(s, SQLITE_DATETIME_FMT) {
                          Ok(tm) => Ok(tm.to_timespec()),
                          Err(err) => Err(FromSqlError::Other(Box::new(err))),
                      })
    }
}

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

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")
            .unwrap();
        db
    }

    #[test]
    fn test_timespec() {
        let db = checked_memory_handle();

        let mut ts_vec = vec![];

        ts_vec.push(time::Timespec::new(10_000, 0));//January 1, 1970 2:46:40 AM
        ts_vec.push(time::Timespec::new(10_000, 1000));//January 1, 1970 2:46:40 AM (and one microsecond)
        ts_vec.push(time::Timespec::new(1500391124, 1_000_000));//July 18, 2017
        ts_vec.push(time::Timespec::new(2000000000, 2_000_000));//May 18, 2033
        ts_vec.push(time::Timespec::new(3000000000, 999_999_999));//January 24, 2065
        ts_vec.push(time::Timespec::new(10000000000, 0));//November 20, 2286

        for ts in ts_vec {

            db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts])
                .unwrap();

            let from: time::Timespec = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
                .unwrap();

            db.execute("DELETE FROM foo", &[]).unwrap();

            assert_eq!(from, ts);
        }

    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//!   *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//!   *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.55")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
        redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, ops, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::arc::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{Duration, SystemTime, UNIX_EPOCH};

    #[cfg(feature = "unstable")]
    #[allow(deprecated)]
    pub use core::nonzero::{NonZero, Zeroable};

    #[cfg(feature = "unstable")]
    pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Add Avro to the list of supported data formats<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//!   *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//!   *(deserialization only)*
//! - [Avro], a binary data serialization format with support for
//!   schematized data.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Avro]: https://github.com/flavray/avro-rs
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.55")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
        redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(all(feature = "unstable", feature = "std"))]
extern crate core;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, ops, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::arc::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{Duration, SystemTime, UNIX_EPOCH};

    #[cfg(feature = "unstable")]
    #[allow(deprecated)]
    pub use core::nonzero::{NonZero, Zeroable};

    #[cfg(feature = "unstable")]
    pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>


<commit_before>use crate::builder::PossibleValue;
use crate::derive::ValueEnum;

/// Represents the color preferences for program output
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ColorChoice {
    /// Enables colored output only when the output is going to a terminal or TTY.
    ///
    /// **NOTE:** This is the default behavior of `clap`.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms).
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Auto)
    ///     .get_matches();
    /// ```
    Auto,

    /// Enables colored output regardless of whether or not the output is going to a terminal/TTY.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms).
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Always)
    ///     .get_matches();
    /// ```
    Always,

    /// Disables colored output no matter if the output is going to a terminal/TTY, or not.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms)
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Never)
    ///     .get_matches();
    /// ```
    Never,
}

impl Default for ColorChoice {
    fn default() -> Self {
        Self::Auto
    }
}

impl ValueEnum for ColorChoice {
    fn value_variants<'a>() -> &'a [Self] {
        &[Self::Auto, Self::Always, Self::Never]
    }

    fn to_possible_value(&self) -> Option<PossibleValue> {
        Some(match self {
            Self::Auto => {
                PossibleValue::new("auto").help("Use colored output if writing to a terminal/TTY")
            }
            Self::Always => PossibleValue::new("always").help("Always use colored output"),
            Self::Never => PossibleValue::new("never").help("Never use colored output"),
        })
    }
}
<commit_msg>feat: Add Display/FromStr to ColorChoice<commit_after>use crate::builder::PossibleValue;
use crate::derive::ValueEnum;

/// Represents the color preferences for program output
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ColorChoice {
    /// Enables colored output only when the output is going to a terminal or TTY.
    ///
    /// **NOTE:** This is the default behavior of `clap`.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms).
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Auto)
    ///     .get_matches();
    /// ```
    Auto,

    /// Enables colored output regardless of whether or not the output is going to a terminal/TTY.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms).
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Always)
    ///     .get_matches();
    /// ```
    Always,

    /// Disables colored output no matter if the output is going to a terminal/TTY, or not.
    ///
    /// # Platform Specific
    ///
    /// This setting only applies to Unix, Linux, and macOS (i.e. non-Windows platforms)
    ///
    /// # Examples
    ///
    #[cfg_attr(not(feature = "color"), doc = " ```ignore")]
    #[cfg_attr(feature = "color", doc = " ```no_run")]
    /// # use clap::{Command, ColorChoice};
    /// Command::new("myprog")
    ///     .color(ColorChoice::Never)
    ///     .get_matches();
    /// ```
    Never,
}

impl Default for ColorChoice {
    fn default() -> Self {
        Self::Auto
    }
}

impl std::fmt::Display for ColorChoice {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.to_possible_value()
            .expect("no values are skipped")
            .get_name()
            .fmt(f)
    }
}

impl std::str::FromStr for ColorChoice {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        for variant in Self::value_variants() {
            if variant.to_possible_value().unwrap().matches(s, false) {
                return Ok(*variant);
            }
        }
        Err(format!("Invalid variant: {}", s))
    }
}

impl ValueEnum for ColorChoice {
    fn value_variants<'a>() -> &'a [Self] {
        &[Self::Auto, Self::Always, Self::Never]
    }

    fn to_possible_value(&self) -> Option<PossibleValue> {
        Some(match self {
            Self::Auto => {
                PossibleValue::new("auto").help("Use colored output if writing to a terminal/TTY")
            }
            Self::Always => PossibleValue::new("always").help("Always use colored output"),
            Self::Never => PossibleValue::new("never").help("Never use colored output"),
        })
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::HTMLDataListElementBinding;
use dom::bindings::codegen::InheritTypes::{HTMLDataListElementDerived, NodeCast};
use dom::bindings::js::JS;
use dom::document::Document;
use dom::element::HTMLDataListElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLDataListElement {
    htmlelement: HTMLElement
}

impl HTMLDataListElementDerived for EventTarget {
    fn is_htmldatalistelement(&self) -> bool {
        match self.type_id {
            NodeTargetTypeId(ElementNodeTypeId(HTMLDataListElementTypeId)) => true,
            _ => false
        }
    }
}

impl HTMLDataListElement {
    pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDataListElement {
        HTMLDataListElement {
            htmlelement: HTMLElement::new_inherited(HTMLDataListElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDataListElement> {
        let element = HTMLDataListElement::new_inherited(localName, document.clone());
        Node::reflect_node(~element, document, HTMLDataListElementBinding::Wrap)
    }
}

impl HTMLDataListElement {
    pub fn Options(&self, abstract_self: &JS<HTMLDataListElement>) -> JS<HTMLCollection> {
        let node: JS<Node> = NodeCast::from(abstract_self);
        let doc = &self.htmlelement.element.node.owner_doc();
        let window = &doc.get().window;
        HTMLCollection::by_tag_name(window, &node, ~"option")
    }
}
<commit_msg>Support live HTMLCollection for DataListElement.options<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::HTMLDataListElementBinding;
use dom::bindings::codegen::InheritTypes::{HTMLDataListElementDerived, NodeCast};
use dom::bindings::js::JS;
use dom::document::Document;
use dom::element::{Element, HTMLDataListElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::{HTMLCollection, CollectionFilter};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLDataListElement {
    htmlelement: HTMLElement
}

impl HTMLDataListElementDerived for EventTarget {
    fn is_htmldatalistelement(&self) -> bool {
        match self.type_id {
            NodeTargetTypeId(ElementNodeTypeId(HTMLDataListElementTypeId)) => true,
            _ => false
        }
    }
}

impl HTMLDataListElement {
    pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDataListElement {
        HTMLDataListElement {
            htmlelement: HTMLElement::new_inherited(HTMLDataListElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDataListElement> {
        let element = HTMLDataListElement::new_inherited(localName, document.clone());
        Node::reflect_node(~element, document, HTMLDataListElementBinding::Wrap)
    }
}

impl HTMLDataListElement {
    pub fn Options(&self, abstract_self: &JS<HTMLDataListElement>) -> JS<HTMLCollection> {
        struct HTMLDataListOptionsFilter;
        impl CollectionFilter for HTMLDataListOptionsFilter {
            fn filter(&self, elem: &JS<Element>, _root: &JS<Node>) -> bool {
                elem.get().tag_name == ~"option"
            }
        }
        let node: JS<Node> = NodeCast::from(abstract_self);
        let filter = ~HTMLDataListOptionsFilter;
        HTMLCollection::create_live(&window_from_node(&node), &node, filter)
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//    https://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.

use crate::{
    conversion::ConvertError,
    types::{make_ident, TypeName},
};
use indoc::indoc;
use lazy_static::lazy_static;
use std::collections::HashMap;
use syn::{parse_quote, GenericArgument, PathArguments, Type, TypePath, TypePtr};

//// The behavior of the type.
#[derive(Debug)]
enum Behavior {
    CxxContainerByValueSafe,
    CxxContainerNotByValueSafe,
    CxxString,
    RustStr,
    RustString,
    RustByValue,
    CByValue,
    CVariableLengthByValue,
    CVoid,
}

/// Details about known special types, mostly primitives.
#[derive(Debug)]
struct TypeDetails {
    /// The name used by cxx (in Rust code) for this type.
    rs_name: String,
    /// C++ equivalent name for a Rust type.
    cpp_name: String,
    //// The behavior of the type.
    behavior: Behavior,
    /// Any extra non-canonical names
    extra_non_canonical_name: Option<String>,
}

impl TypeDetails {
    fn new(
        rs_name: String,
        cpp_name: String,
        behavior: Behavior,
        extra_non_canonical_name: Option<String>,
    ) -> Self {
        TypeDetails {
            rs_name,
            cpp_name,
            behavior,
            extra_non_canonical_name,
        }
    }

    /// Whether and how to include this in the prelude given to bindgen.
    fn get_prelude_entry(&self) -> Option<String> {
        match self.behavior {
            Behavior::RustString
            | Behavior::RustStr
            | Behavior::CxxString
            | Behavior::CxxContainerByValueSafe
            | Behavior::CxxContainerNotByValueSafe => {
                let tn = TypeName::new_from_user_input(&self.rs_name);
                let cxx_name = tn.get_final_ident();
                let (templating, payload) = match self.behavior {
                    Behavior::CxxContainerByValueSafe | Behavior::CxxContainerNotByValueSafe => {
                        ("template<typename T> ", "T* ptr")
                    }
                    _ => ("", "char* ptr"),
                };
                Some(format!(
                    indoc! {"
                    /**
                    *

                    */
                    {}class {} {{
                        {};
                    }};

                    "},
                    self.cpp_name, templating, cxx_name, payload
                ))
            }
            _ => None,
        }
    }

    fn to_type_path(&self) -> TypePath {
        let segs = self.rs_name.split("::").map(make_ident);
        parse_quote! {
            #(#segs)::*
        }
    }
}

/// Database of known types.
pub(crate) struct TypeDatabase {
    by_rs_name: HashMap<TypeName, TypeDetails>,
    canonical_names: HashMap<TypeName, TypeName>,
}

lazy_static! {
    /// Database of known types.
    pub(crate) static ref KNOWN_TYPES: TypeDatabase = create_type_database();
}

impl TypeDatabase {
    fn get(&self, ty: &TypeName) -> Option<&TypeDetails> {
        // The following line is important. It says that
        // when we encounter something like 'std::unique_ptr'
        // in the bindgen-generated bindings, we'll immediately
        // start to refer to that as 'UniquePtr' henceforth.
        let canonical_name = self.canonical_names.get(ty).unwrap_or(ty);
        self.by_rs_name.get(canonical_name)
    }

    /// Prelude of C++ for squirting into bindgen. This configures
    /// bindgen to output simpler types to replace some STL types
    /// that bindgen just can't cope with. Although we then replace
    /// those types with cxx types (e.g. UniquePtr), this intermediate
    /// step is still necessary because bindgen can't otherwise
    /// give us the templated types (e.g. when faced with the STL
    /// unique_ptr, bindgen would normally give us std_unique_ptr
    /// as opposed to std_unique_ptr<T>.)
    pub(crate) fn get_prelude(&self) -> String {
        itertools::join(
            self.by_rs_name
                .values()
                .filter_map(|t| t.get_prelude_entry()),
            "\n",
        )
    }

    /// Types which are known to be safe (or unsafe) to hold and pass by
    /// value in Rust.
    pub(crate) fn get_pod_safe_types(&self) -> impl Iterator<Item = (&TypeName, bool)> {
        self.by_rs_name.iter().map(|(tn, td)| {
            (
                tn,
                match td.behavior {
                    Behavior::CxxContainerByValueSafe
                    | Behavior::RustStr
                    | Behavior::RustString
                    | Behavior::RustByValue
                    | Behavior::CByValue
                    | Behavior::CVariableLengthByValue => true,
                    Behavior::CxxString
                    | Behavior::CxxContainerNotByValueSafe
                    | Behavior::CVoid => false,
                },
            )
        })
    }

    /// Whether this TypePath should be treated as a value in C++
    /// but a reference in Rust. This only applies to rust::Str
    /// (C++ name) which is &str in Rust.
    pub(crate) fn should_dereference_in_cpp(&self, typ: &TypePath) -> bool {
        let tn = TypeName::from_type_path(typ);
        self.get(&tn)
            .map(|td| matches!(td.behavior, Behavior::RustStr))
            .unwrap_or(false)
    }

    /// Here we substitute any names which we know are Special from
    /// our type database, e.g. std::unique_ptr -> UniquePtr.
    /// We strip off and ignore
    /// any PathArguments within this TypePath - callers should
    /// put them back again if needs be.
    pub(crate) fn known_type_substitute_path(&self, typ: &TypePath) -> Option<TypePath> {
        let tn = TypeName::from_type_path(typ);
        self.get(&tn).map(|td| td.to_type_path())
    }

    pub(crate) fn special_cpp_name(&self, rs: &TypeName) -> Option<String> {
        self.get(rs).map(|x| x.cpp_name.to_string())
    }

    pub(crate) fn is_known_type(&self, ty: &TypeName) -> bool {
        self.get(ty).is_some()
    }

    pub(crate) fn known_type_type_path(&self, ty: &TypeName) -> Option<TypePath> {
        self.get(ty).map(|td| td.to_type_path())
    }

    /// Whether this is one of the ctypes (mostly variable length integers)
    /// which we need to wrap.
    pub(crate) fn is_ctype(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|td| match td.behavior {
                Behavior::CVariableLengthByValue | Behavior::CVoid => true,
                _ => false,
            })
            .unwrap_or(false)
    }

    /// Whether this is a generic type acceptable to cxx. Otherwise,
    /// if we encounter a generic, we'll replace it with a synthesized concrete
    /// type.
    pub(crate) fn is_cxx_acceptable_generic(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|x| match x.behavior {
                Behavior::CxxContainerByValueSafe | Behavior::CxxContainerNotByValueSafe => true,
                _ => false,
            })
            .unwrap_or(false)
    }

    pub(crate) fn convertible_from_strs(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|x| matches!(x.behavior, Behavior::CxxString))
            .unwrap_or(false)
    }
}

fn create_type_database() -> TypeDatabase {
    let mut by_rs_name = HashMap::new();

    let mut do_insert =
        |td: TypeDetails| by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    do_insert(TypeDetails::new(
        "cxx::UniquePtr".into(),
        "std::unique_ptr".into(),
        Behavior::CxxContainerByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::CxxVector".into(),
        "std::vector".into(),
        Behavior::CxxContainerNotByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::SharedPtr".into(),
        "std::shared_ptr".into(),
        Behavior::CxxContainerByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::CxxString".into(),
        "std::string".into(),
        Behavior::CxxString,
        None,
    ));
    do_insert(TypeDetails::new(
        "str".into(),
        "rust::Str".into(),
        Behavior::RustStr,
        None,
    ));
    do_insert(TypeDetails::new(
        "String".into(),
        "rust::String".into(),
        Behavior::RustString,
        None,
    ));
    do_insert(TypeDetails::new(
        "i8".into(),
        "int8_t".into(),
        Behavior::CByValue,
        Some("std::os::raw::c_schar".into()),
    ));
    do_insert(TypeDetails::new(
        "u8".into(),
        "uint8_t".into(),
        Behavior::CByValue,
        Some("std::os::raw::c_uchar".into()),
    ));
    for (cpp_type, rust_type) in (4..7)
        .map(|x| 2i32.pow(x))
        .map(|x| {
            vec![
                (format!("uint{}_t", x), format!("u{}", x)),
                (format!("int{}_t", x), format!("i{}", x)),
            ]
        })
        .flatten()
    {
        do_insert(TypeDetails::new(
            rust_type,
            cpp_type,
            Behavior::CByValue,
            None,
        ));
    }
    do_insert(TypeDetails::new(
        "bool".into(),
        "bool".into(),
        Behavior::CByValue,
        None,
    ));

    do_insert(TypeDetails::new(
        "std::pin::Pin".into(),
        "Pin".into(),
        Behavior::RustByValue, // because this is actually Pin<&something>
        None,
    ));

    let mut insert_ctype = |cname: &str| {
        let td = TypeDetails::new(
            format!("autocxx::c_{}", cname),
            cname.into(),
            Behavior::CVariableLengthByValue,
            Some(format!("std::os::raw::c_{}", cname)),
        );
        by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);
        let td = TypeDetails::new(
            format!("autocxx::c_u{}", cname),
            format!("unsigned {}", cname),
            Behavior::CVariableLengthByValue,
            Some(format!("std::os::raw::c_u{}", cname)),
        );
        by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);
    };

    insert_ctype("long");
    insert_ctype("int");
    insert_ctype("short");

    let td = TypeDetails::new("f32".into(), "float".into(), Behavior::CByValue, None);
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new("f64".into(), "double".into(), Behavior::CByValue, None);
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new(
        "std::os::raw::c_char".into(),
        "char".into(),
        Behavior::CByValue,
        None,
    );
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new(
        "autocxx::c_void".into(),
        "void".into(),
        Behavior::CVoid,
        Some(format!("std::os::raw::c_void")),
    );
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let mut by_cppname = HashMap::new();
    for td in by_rs_name.values() {
        let rs_name = TypeName::new_from_user_input(&td.rs_name);
        if let Some(extra_non_canonical_name) = &td.extra_non_canonical_name {
            by_cppname.insert(
                TypeName::new_from_user_input(extra_non_canonical_name),
                rs_name.clone(),
            );
        }
        by_cppname.insert(TypeName::new_from_user_input(&td.cpp_name), rs_name);
    }

    TypeDatabase {
        by_rs_name,
        canonical_names: by_cppname,
    }
}

/// This is worked out basically using trial and error.
/// Excluding std* and rust* is obvious, but the other items...
/// in theory bindgen ought to be smart enough to work out that
/// they're not used and therefore not generate code for them.
/// But it doesm unless we blocklist them. This is obviously
/// a bit sensitive to the particular STL in use so one day
/// it would be good to dig into bindgen's behavior here - TODO.
const BINDGEN_BLOCKLIST: &[&str] = &["std.*", "__gnu.*", ".*mbstate_t.*", "rust.*"];

/// Get the list of types to give to bindgen to ask it _not_ to
/// generate code for.
pub(crate) fn get_initial_blocklist() -> Vec<String> {
    BINDGEN_BLOCKLIST.iter().map(|s| s.to_string()).collect()
}

/// If a given type lacks a copy constructor, we should always use
/// std::move in wrapper functions.
pub(crate) fn type_lacks_copy_constructor(ty: &Type) -> bool {
    // In future we may wish to look this up in KNOWN_TYPES.
    match ty {
        Type::Path(typ) => {
            let tn = TypeName::from_type_path(typ);
            tn.to_cpp_name().starts_with("std::unique_ptr")
        }
        _ => false,
    }
}

pub(crate) fn confirm_inner_type_is_acceptable_generic_payload(
    path_args: &PathArguments,
    desc: &TypeName,
) -> Result<(), ConvertError> {
    // For now, all supported generics accept the same payloads. This
    // may change in future in which case we'll need to accept more arguments here.
    match path_args {
        PathArguments::None => Ok(()),
        PathArguments::Parenthesized(_) => Err(ConvertError::TemplatedTypeContainingNonPathArg(
            desc.clone(),
        )),
        PathArguments::AngleBracketed(ab) => {
            for inner in &ab.args {
                match inner {
                    GenericArgument::Type(Type::Path(typ)) => {
                        if let Some(more_generics) = typ.path.segments.last() {
                            confirm_inner_type_is_acceptable_generic_payload(
                                &more_generics.arguments,
                                desc,
                            )?;
                        }
                    }
                    _ => {
                        return Err(ConvertError::TemplatedTypeContainingNonPathArg(
                            desc.clone(),
                        ))
                    }
                }
            }
            Ok(())
        }
    }
}

pub(crate) fn ensure_pointee_is_valid(ptr: &TypePtr) -> Result<(), ConvertError> {
    match *ptr.elem {
        Type::Path(..) => Ok(()),
        _ => Err(ConvertError::InvalidPointee),
    }
}
<commit_msg>Use Into to make concise.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//    https://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.

use crate::{
    conversion::ConvertError,
    types::{make_ident, TypeName},
};
use indoc::indoc;
use lazy_static::lazy_static;
use std::collections::HashMap;
use syn::{parse_quote, GenericArgument, PathArguments, Type, TypePath, TypePtr};

//// The behavior of the type.
#[derive(Debug)]
enum Behavior {
    CxxContainerByValueSafe,
    CxxContainerNotByValueSafe,
    CxxString,
    RustStr,
    RustString,
    RustByValue,
    CByValue,
    CVariableLengthByValue,
    CVoid,
}

/// Details about known special types, mostly primitives.
#[derive(Debug)]
struct TypeDetails {
    /// The name used by cxx (in Rust code) for this type.
    rs_name: String,
    /// C++ equivalent name for a Rust type.
    cpp_name: String,
    //// The behavior of the type.
    behavior: Behavior,
    /// Any extra non-canonical names
    extra_non_canonical_name: Option<String>,
}

impl TypeDetails {
    fn new(
        rs_name: impl Into<String>,
        cpp_name: impl Into<String>,
        behavior: Behavior,
        extra_non_canonical_name: Option<String>,
    ) -> Self {
        TypeDetails {
            rs_name: rs_name.into(),
            cpp_name: cpp_name.into(),
            behavior,
            extra_non_canonical_name,
        }
    }

    /// Whether and how to include this in the prelude given to bindgen.
    fn get_prelude_entry(&self) -> Option<String> {
        match self.behavior {
            Behavior::RustString
            | Behavior::RustStr
            | Behavior::CxxString
            | Behavior::CxxContainerByValueSafe
            | Behavior::CxxContainerNotByValueSafe => {
                let tn = TypeName::new_from_user_input(&self.rs_name);
                let cxx_name = tn.get_final_ident();
                let (templating, payload) = match self.behavior {
                    Behavior::CxxContainerByValueSafe | Behavior::CxxContainerNotByValueSafe => {
                        ("template<typename T> ", "T* ptr")
                    }
                    _ => ("", "char* ptr"),
                };
                Some(format!(
                    indoc! {"
                    /**
                    *

                    */
                    {}class {} {{
                        {};
                    }};

                    "},
                    self.cpp_name, templating, cxx_name, payload
                ))
            }
            _ => None,
        }
    }

    fn to_type_path(&self) -> TypePath {
        let segs = self.rs_name.split("::").map(make_ident);
        parse_quote! {
            #(#segs)::*
        }
    }
}

/// Database of known types.
pub(crate) struct TypeDatabase {
    by_rs_name: HashMap<TypeName, TypeDetails>,
    canonical_names: HashMap<TypeName, TypeName>,
}

lazy_static! {
    /// Database of known types.
    pub(crate) static ref KNOWN_TYPES: TypeDatabase = create_type_database();
}

impl TypeDatabase {
    fn get(&self, ty: &TypeName) -> Option<&TypeDetails> {
        // The following line is important. It says that
        // when we encounter something like 'std::unique_ptr'
        // in the bindgen-generated bindings, we'll immediately
        // start to refer to that as 'UniquePtr' henceforth.
        let canonical_name = self.canonical_names.get(ty).unwrap_or(ty);
        self.by_rs_name.get(canonical_name)
    }

    /// Prelude of C++ for squirting into bindgen. This configures
    /// bindgen to output simpler types to replace some STL types
    /// that bindgen just can't cope with. Although we then replace
    /// those types with cxx types (e.g. UniquePtr), this intermediate
    /// step is still necessary because bindgen can't otherwise
    /// give us the templated types (e.g. when faced with the STL
    /// unique_ptr, bindgen would normally give us std_unique_ptr
    /// as opposed to std_unique_ptr<T>.)
    pub(crate) fn get_prelude(&self) -> String {
        itertools::join(
            self.by_rs_name
                .values()
                .filter_map(|t| t.get_prelude_entry()),
            "\n",
        )
    }

    /// Types which are known to be safe (or unsafe) to hold and pass by
    /// value in Rust.
    pub(crate) fn get_pod_safe_types(&self) -> impl Iterator<Item = (&TypeName, bool)> {
        self.by_rs_name.iter().map(|(tn, td)| {
            (
                tn,
                match td.behavior {
                    Behavior::CxxContainerByValueSafe
                    | Behavior::RustStr
                    | Behavior::RustString
                    | Behavior::RustByValue
                    | Behavior::CByValue
                    | Behavior::CVariableLengthByValue => true,
                    Behavior::CxxString
                    | Behavior::CxxContainerNotByValueSafe
                    | Behavior::CVoid => false,
                },
            )
        })
    }

    /// Whether this TypePath should be treated as a value in C++
    /// but a reference in Rust. This only applies to rust::Str
    /// (C++ name) which is &str in Rust.
    pub(crate) fn should_dereference_in_cpp(&self, typ: &TypePath) -> bool {
        let tn = TypeName::from_type_path(typ);
        self.get(&tn)
            .map(|td| matches!(td.behavior, Behavior::RustStr))
            .unwrap_or(false)
    }

    /// Here we substitute any names which we know are Special from
    /// our type database, e.g. std::unique_ptr -> UniquePtr.
    /// We strip off and ignore
    /// any PathArguments within this TypePath - callers should
    /// put them back again if needs be.
    pub(crate) fn known_type_substitute_path(&self, typ: &TypePath) -> Option<TypePath> {
        let tn = TypeName::from_type_path(typ);
        self.get(&tn).map(|td| td.to_type_path())
    }

    pub(crate) fn special_cpp_name(&self, rs: &TypeName) -> Option<String> {
        self.get(rs).map(|x| x.cpp_name.to_string())
    }

    pub(crate) fn is_known_type(&self, ty: &TypeName) -> bool {
        self.get(ty).is_some()
    }

    pub(crate) fn known_type_type_path(&self, ty: &TypeName) -> Option<TypePath> {
        self.get(ty).map(|td| td.to_type_path())
    }

    /// Whether this is one of the ctypes (mostly variable length integers)
    /// which we need to wrap.
    pub(crate) fn is_ctype(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|td| match td.behavior {
                Behavior::CVariableLengthByValue | Behavior::CVoid => true,
                _ => false,
            })
            .unwrap_or(false)
    }

    /// Whether this is a generic type acceptable to cxx. Otherwise,
    /// if we encounter a generic, we'll replace it with a synthesized concrete
    /// type.
    pub(crate) fn is_cxx_acceptable_generic(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|x| match x.behavior {
                Behavior::CxxContainerByValueSafe | Behavior::CxxContainerNotByValueSafe => true,
                _ => false,
            })
            .unwrap_or(false)
    }

    pub(crate) fn convertible_from_strs(&self, ty: &TypeName) -> bool {
        self.get(ty)
            .map(|x| matches!(x.behavior, Behavior::CxxString))
            .unwrap_or(false)
    }
}

fn create_type_database() -> TypeDatabase {
    let mut by_rs_name = HashMap::new();

    let mut do_insert =
        |td: TypeDetails| by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    do_insert(TypeDetails::new(
        "cxx::UniquePtr",
        "std::unique_ptr",
        Behavior::CxxContainerByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::CxxVector",
        "std::vector",
        Behavior::CxxContainerNotByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::SharedPtr",
        "std::shared_ptr",
        Behavior::CxxContainerByValueSafe,
        None,
    ));
    do_insert(TypeDetails::new(
        "cxx::CxxString",
        "std::string",
        Behavior::CxxString,
        None,
    ));
    do_insert(TypeDetails::new(
        "str",
        "rust::Str",
        Behavior::RustStr,
        None,
    ));
    do_insert(TypeDetails::new(
        "String",
        "rust::String",
        Behavior::RustString,
        None,
    ));
    do_insert(TypeDetails::new(
        "i8",
        "int8_t",
        Behavior::CByValue,
        Some("std::os::raw::c_schar".into()),
    ));
    do_insert(TypeDetails::new(
        "u8",
        "uint8_t",
        Behavior::CByValue,
        Some("std::os::raw::c_uchar".into()),
    ));
    for (cpp_type, rust_type) in (4..7)
        .map(|x| 2i32.pow(x))
        .map(|x| {
            vec![
                (format!("uint{}_t", x), format!("u{}", x)),
                (format!("int{}_t", x), format!("i{}", x)),
            ]
        })
        .flatten()
    {
        do_insert(TypeDetails::new(
            rust_type,
            cpp_type,
            Behavior::CByValue,
            None,
        ));
    }
    do_insert(TypeDetails::new("bool", "bool", Behavior::CByValue, None));

    do_insert(TypeDetails::new(
        "std::pin::Pin",
        "Pin",
        Behavior::RustByValue, // because this is actually Pin<&something>
        None,
    ));

    let mut insert_ctype = |cname: &str| {
        let td = TypeDetails::new(
            format!("autocxx::c_{}", cname),
            cname,
            Behavior::CVariableLengthByValue,
            Some(format!("std::os::raw::c_{}", cname)),
        );
        by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);
        let td = TypeDetails::new(
            format!("autocxx::c_u{}", cname),
            format!("unsigned {}", cname),
            Behavior::CVariableLengthByValue,
            Some(format!("std::os::raw::c_u{}", cname)),
        );
        by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);
    };

    insert_ctype("long");
    insert_ctype("int");
    insert_ctype("short");

    let td = TypeDetails::new("f32", "float", Behavior::CByValue, None);
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new("f64", "double", Behavior::CByValue, None);
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new("std::os::raw::c_char", "char", Behavior::CByValue, None);
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let td = TypeDetails::new(
        "autocxx::c_void",
        "void",
        Behavior::CVoid,
        Some(format!("std::os::raw::c_void")),
    );
    by_rs_name.insert(TypeName::new_from_user_input(&td.rs_name), td);

    let mut by_cppname = HashMap::new();
    for td in by_rs_name.values() {
        let rs_name = TypeName::new_from_user_input(&td.rs_name);
        if let Some(extra_non_canonical_name) = &td.extra_non_canonical_name {
            by_cppname.insert(
                TypeName::new_from_user_input(extra_non_canonical_name),
                rs_name.clone(),
            );
        }
        by_cppname.insert(TypeName::new_from_user_input(&td.cpp_name), rs_name);
    }

    TypeDatabase {
        by_rs_name,
        canonical_names: by_cppname,
    }
}

/// This is worked out basically using trial and error.
/// Excluding std* and rust* is obvious, but the other items...
/// in theory bindgen ought to be smart enough to work out that
/// they're not used and therefore not generate code for them.
/// But it doesm unless we blocklist them. This is obviously
/// a bit sensitive to the particular STL in use so one day
/// it would be good to dig into bindgen's behavior here - TODO.
const BINDGEN_BLOCKLIST: &[&str] = &["std.*", "__gnu.*", ".*mbstate_t.*", "rust.*"];

/// Get the list of types to give to bindgen to ask it _not_ to
/// generate code for.
pub(crate) fn get_initial_blocklist() -> Vec<String> {
    BINDGEN_BLOCKLIST.iter().map(|s| s.to_string()).collect()
}

/// If a given type lacks a copy constructor, we should always use
/// std::move in wrapper functions.
pub(crate) fn type_lacks_copy_constructor(ty: &Type) -> bool {
    // In future we may wish to look this up in KNOWN_TYPES.
    match ty {
        Type::Path(typ) => {
            let tn = TypeName::from_type_path(typ);
            tn.to_cpp_name().starts_with("std::unique_ptr")
        }
        _ => false,
    }
}

pub(crate) fn confirm_inner_type_is_acceptable_generic_payload(
    path_args: &PathArguments,
    desc: &TypeName,
) -> Result<(), ConvertError> {
    // For now, all supported generics accept the same payloads. This
    // may change in future in which case we'll need to accept more arguments here.
    match path_args {
        PathArguments::None => Ok(()),
        PathArguments::Parenthesized(_) => Err(ConvertError::TemplatedTypeContainingNonPathArg(
            desc.clone(),
        )),
        PathArguments::AngleBracketed(ab) => {
            for inner in &ab.args {
                match inner {
                    GenericArgument::Type(Type::Path(typ)) => {
                        if let Some(more_generics) = typ.path.segments.last() {
                            confirm_inner_type_is_acceptable_generic_payload(
                                &more_generics.arguments,
                                desc,
                            )?;
                        }
                    }
                    _ => {
                        return Err(ConvertError::TemplatedTypeContainingNonPathArg(
                            desc.clone(),
                        ))
                    }
                }
            }
            Ok(())
        }
    }
}

pub(crate) fn ensure_pointee_is_valid(ptr: &TypePtr) -> Result<(), ConvertError> {
    match *ptr.elem {
        Type::Path(..) => Ok(()),
        _ => Err(ConvertError::InvalidPointee),
    }
}
<|endoftext|>