<commit_before>
#[derive(Debug)]
#[cfg(feature = "std")]
/// Serialization Error
pub enum Error {
    /// `io::Error` (no available in ![no_std] mode)
    Io(std::io::Error),
    /// `fmt::Error`
    Fmt(std::fmt::Error),
    /// Other error
    Other,
}

#[derive(Debug)]
#[cfg(not(feature = "std"))]
/// Serialization Error
pub enum Error {
    /// `fmt::Error`
    Fmt(core::fmt::Error),
    /// Other error
    Other,
}

/// Serialization `Result`
pub type Result<T=()> = result::Result<T, Error>;

#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<core::fmt::Error> for Error {
    fn from(_: core::fmt::Error) -> Error {
        Error::Other
    }
}

#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
    fn from(e: Error) -> std::io::Error {
        match e {
            Error::Io(e) => e,
            Error::Fmt(_) => std::io::Error::new(std::io::ErrorKind::Other, "formatting error"),
            Error::Other => std::io::Error::new(std::io::ErrorKind::Other, "other error"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref e) => e.description(),
            Error::Fmt(_) => "formatting error",
            Error::Other => "serialization error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref e) => Some(e),
            Error::Fmt(ref e) => Some(e),
            Error::Other => None,
        }
    }
}

#[cfg(feature = "std")]
impl core::fmt::Display for Error {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Io(ref e) => e.fmt(fmt),
            Error::Fmt(ref e) => e.fmt(fmt),
            Error::Other => fmt.write_str("Other serialization error"),
        }
    }
}

macro_rules! impl_default_as_fmt{
    ($t:ty, $f:ident) => {
        /// Emit $t
        fn $f(&mut self, key : &str, val : $t)
            -> Result {
                self.emit_arguments(key, &format_args!("{}", val))
            }
    };
}

/// Serializer
///
/// Drains using `Format` will internally use
/// types implementing this trait.
pub trait Serializer {

    /// Emit usize
    impl_default_as_fmt!(usize, emit_usize);
    /// Emit isize
    impl_default_as_fmt!(isize, emit_isize);
    /// Emit bool
    impl_default_as_fmt!(bool, emit_bool);
    /// Emit char
    impl_default_as_fmt!(char, emit_char);
    /// Emit u8
    impl_default_as_fmt!(u8, emit_u8);
    /// Emit i8
    impl_default_as_fmt!(i8, emit_i8);
    /// Emit u16
    impl_default_as_fmt!(u16, emit_u16);
    /// Emit i16
    impl_default_as_fmt!(i16, emit_i16);
    /// Emit u32
    impl_default_as_fmt!(u32, emit_u32);
    /// Emit i32
    impl_default_as_fmt!(i32, emit_i32);
    /// Emit f32
    impl_default_as_fmt!(f32, emit_f32);
    /// Emit u64
    impl_default_as_fmt!(u64, emit_u64);
    /// Emit i64
    impl_default_as_fmt!(i64, emit_i64);
    /// Emit f64
    impl_default_as_fmt!(f64, emit_f64);
    /// Emit str
    impl_default_as_fmt!(&str, emit_str);

    /// Emit `()`
    fn emit_unit(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!("()"))
    }

    /// Emit `None`
    fn emit_none(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!(""))
    }

    /// Emit `fmt::Arguments`
    ///
    /// This is the only method that has to implemented, but for performance and to retain type
    /// information most serious `Serializer`s will want to implement all other methods as well.
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result;
}

/// Serializer to closure adapter.
///
/// Formats all arguments as fmt::Arguments and passes them to a given closure.
struct AsFmtSerializer<F>(pub F)
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result;

impl<F> Serializer for AsFmtSerializer<F>
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result
{
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result {
        (self.0)(key, *val)
    }
}

/// Value that can be serialized
pub trait Value {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result;
}

/// Value that can be serialized
pub trait Key {
    /// To text representation
    fn as_str(&self) -> &str;
}

impl<'a> Key for &'a str {
    fn as_str(&self) -> &str {
        &self
    }
}

impl Key for str {
    fn as_str(&self) -> &str {
        &self
    }
}

impl Key for String {
    fn as_str(&self) -> &str {
        self.as_str()
    }
}

macro_rules! impl_value_for{
    ($t:ty, $f:ident) => {
        impl Value for $t {
            fn serialize(&self, _record : &Record, key : &str, serializer : &mut Serializer)
                         -> Result {
                serializer.$f(key, *self)
            }
        }
    };
}

impl_value_for!(usize, emit_usize);
impl_value_for!(isize, emit_isize);
impl_value_for!(bool, emit_bool);
impl_value_for!(char, emit_char);
impl_value_for!(u8, emit_u8);
impl_value_for!(i8, emit_i8);
impl_value_for!(u16, emit_u16);
impl_value_for!(i16, emit_i16);
impl_value_for!(u32, emit_u32);
impl_value_for!(i32, emit_i32);
impl_value_for!(f32, emit_f32);
impl_value_for!(u64, emit_u64);
impl_value_for!(i64, emit_i64);
impl_value_for!(f64, emit_f64);

impl Value for () {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_unit(key)
    }
}

impl Value for str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for &'a str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for fmt::Arguments<'a> {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_arguments(key, self)
    }
}

impl Value for String {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self.as_str())
    }
}

impl<T: Value> Value for Option<T> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        match *self {
            Some(ref s) => s.serialize(record, key, serializer),
            None => serializer.emit_none(key),
        }
    }
}

impl Value for Box<Value + Send + 'static> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Arc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Rc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for core::num::Wrapping<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        self.0.serialize(record, key, serializer)
    }
}

impl<V: 'static + Value, F> Value for F
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self)(record).serialize(record, key, serializer)
    }
}

/// Explicit lazy-closure `Value`
pub struct FnValue<V: 'static + Value, F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V;

impl<V: 'static + Value, F> Value for FnValue<V, F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self.0)(record).serialize(record, key, serializer)
    }
}

/// Handle passed to `PushFnValue` closure
///
/// It makes sure only one value is serialized, and will automatically emit
/// `()` if nothing else was serialized.
pub struct PushFnSerializer<'a> {
    record: &'a Record<'a>,
    key: &'a str,
    serializer: &'a mut Serializer,
    done: bool,
}

impl<'a> PushFnSerializer<'a> {
    /// Serialize a value
    ///
    /// This consumes `self` to prevent serializing one value multiple times
    pub fn serialize<'b, S: 'b + Value>(mut self, s: S) -> Result {
        self.done = true;
        s.serialize(self.record, self.key, self.serializer)
    }
}

impl<'a> Drop for PushFnSerializer<'a> {
    fn drop(&mut self) {
        if !self.done {
            // unfortunately this gives no change to return serialization errors
            let _ = self.serializer.emit_unit(self.key);
        }
    }
}

/// Lazy `Value` that writes to Serializer
///
/// It's more natural for closures used as lazy values to return `Serialize`
/// implementing type, but sometimes that forces an allocation (eg. Strings)
///
/// In some cases it might make sense for another closure form to be used - one
/// taking a serializer as an argument, which avoids lifetimes / allocation issues.
///
/// Generally this method should be used if it avoids a big allocation of
/// `Serialize`-implementing type in performance-critical logging statement.
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::{PushFnValue, Logger, Discard};
///
/// fn main() {
///     let _root = Logger::root(Discard, o!( ));
///     info!(_root, "foo"; "writer_closure" => PushFnValue(|_ , s| {
///                    let generated_string = format!("{}", 1);
///                    s.serialize(generated_string.as_str())
///             }));
/// }
/// ```
pub struct PushFnValue<F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result;

impl<F> Value for PushFnValue<F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result
{
    fn serialize(&self, record: &Record, key: &str, serializer: &mut Serializer)
        -> Result {
        let ser = PushFnSerializer {
            record: record,
            key: key,
            serializer: serializer,
            done: false,
        };
        (self.0)(record, ser)
    }
}

/// Key-value pair(s) that can be serialized
///
/// Zero, one or more key value pairs chained together
pub trait KV {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
                 -> Result;

    /// Split into tuple of `(first, rest)`
    fn split_first(&self) -> Option<(&KV, &KV)>;
}

/// Single pair `Key` and `Value`
pub struct SingleKV<K, V>(pub K, pub V)
    where K : Key, V : Value;

impl<K, V> KV for SingleKV<K, V>
    where K : Key,
          V : Value
{
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            self.1.serialize(record, self.0.as_str(), serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((self, &STATIC_TERMINATOR_UNIT))
    }
}

impl KV for () {
    fn serialize(&self,
                 _record: &Record,
                 _serializer: &mut Serializer)
        -> Result {
            Ok(())
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        None
    }
}

impl<T: KV, R: KV> KV for (T, R) {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            try!(self.0.serialize(record, serializer));
            self.1.serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((&self.0, &self.1))
    }
}

impl<T> KV for Box<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}

impl<T> KV for Arc<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}
<commit_msg>Fix comment<commit_after>
#[derive(Debug)]
#[cfg(feature = "std")]
/// Serialization Error
pub enum Error {
    /// `io::Error` (no available in ![no_std] mode)
    Io(std::io::Error),
    /// `fmt::Error`
    Fmt(std::fmt::Error),
    /// Other error
    Other,
}

#[derive(Debug)]
#[cfg(not(feature = "std"))]
/// Serialization Error
pub enum Error {
    /// `fmt::Error`
    Fmt(core::fmt::Error),
    /// Other error
    Other,
}

/// Serialization `Result`
pub type Result<T=()> = result::Result<T, Error>;

#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<core::fmt::Error> for Error {
    fn from(_: core::fmt::Error) -> Error {
        Error::Other
    }
}

#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
    fn from(e: Error) -> std::io::Error {
        match e {
            Error::Io(e) => e,
            Error::Fmt(_) => std::io::Error::new(std::io::ErrorKind::Other, "formatting error"),
            Error::Other => std::io::Error::new(std::io::ErrorKind::Other, "other error"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref e) => e.description(),
            Error::Fmt(_) => "formatting error",
            Error::Other => "serialization error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref e) => Some(e),
            Error::Fmt(ref e) => Some(e),
            Error::Other => None,
        }
    }
}

#[cfg(feature = "std")]
impl core::fmt::Display for Error {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Io(ref e) => e.fmt(fmt),
            Error::Fmt(ref e) => e.fmt(fmt),
            Error::Other => fmt.write_str("Other serialization error"),
        }
    }
}

macro_rules! impl_default_as_fmt{
    ($t:ty, $f:ident) => {
        /// Emit $t
        fn $f(&mut self, key : &str, val : $t)
            -> Result {
                self.emit_arguments(key, &format_args!("{}", val))
            }
    };
}

/// Serializer
///
/// Drains using `Format` will internally use
/// types implementing this trait.
pub trait Serializer {

    /// Emit usize
    impl_default_as_fmt!(usize, emit_usize);
    /// Emit isize
    impl_default_as_fmt!(isize, emit_isize);
    /// Emit bool
    impl_default_as_fmt!(bool, emit_bool);
    /// Emit char
    impl_default_as_fmt!(char, emit_char);
    /// Emit u8
    impl_default_as_fmt!(u8, emit_u8);
    /// Emit i8
    impl_default_as_fmt!(i8, emit_i8);
    /// Emit u16
    impl_default_as_fmt!(u16, emit_u16);
    /// Emit i16
    impl_default_as_fmt!(i16, emit_i16);
    /// Emit u32
    impl_default_as_fmt!(u32, emit_u32);
    /// Emit i32
    impl_default_as_fmt!(i32, emit_i32);
    /// Emit f32
    impl_default_as_fmt!(f32, emit_f32);
    /// Emit u64
    impl_default_as_fmt!(u64, emit_u64);
    /// Emit i64
    impl_default_as_fmt!(i64, emit_i64);
    /// Emit f64
    impl_default_as_fmt!(f64, emit_f64);
    /// Emit str
    impl_default_as_fmt!(&str, emit_str);

    /// Emit `()`
    fn emit_unit(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!("()"))
    }

    /// Emit `None`
    fn emit_none(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!(""))
    }

    /// Emit `fmt::Arguments`
    ///
    /// This is the only method that has to implemented, but for performance and to retain type
    /// information most serious `Serializer`s will want to implement all other methods as well.
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result;
}

/// Serializer to closure adapter.
///
/// Formats all arguments as fmt::Arguments and passes them to a given closure.
struct AsFmtSerializer<F>(pub F)
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result;

impl<F> Serializer for AsFmtSerializer<F>
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result
{
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result {
        (self.0)(key, *val)
    }
}

/// Value that can be serialized
pub trait Value {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result;
}

/// Type that can be used as a key
pub trait Key {
    /// To text representation
    fn as_str(&self) -> &str;
}

impl<'a> Key for &'a str {
    fn as_str(&self) -> &str {
        &self
    }
}

impl Key for str {
    fn as_str(&self) -> &str {
        &self
    }
}

impl Key for String {
    fn as_str(&self) -> &str {
        self.as_str()
    }
}

macro_rules! impl_value_for{
    ($t:ty, $f:ident) => {
        impl Value for $t {
            fn serialize(&self, _record : &Record, key : &str, serializer : &mut Serializer)
                         -> Result {
                serializer.$f(key, *self)
            }
        }
    };
}

impl_value_for!(usize, emit_usize);
impl_value_for!(isize, emit_isize);
impl_value_for!(bool, emit_bool);
impl_value_for!(char, emit_char);
impl_value_for!(u8, emit_u8);
impl_value_for!(i8, emit_i8);
impl_value_for!(u16, emit_u16);
impl_value_for!(i16, emit_i16);
impl_value_for!(u32, emit_u32);
impl_value_for!(i32, emit_i32);
impl_value_for!(f32, emit_f32);
impl_value_for!(u64, emit_u64);
impl_value_for!(i64, emit_i64);
impl_value_for!(f64, emit_f64);

impl Value for () {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_unit(key)
    }
}

impl Value for str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for &'a str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for fmt::Arguments<'a> {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_arguments(key, self)
    }
}

impl Value for String {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self.as_str())
    }
}

impl<T: Value> Value for Option<T> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        match *self {
            Some(ref s) => s.serialize(record, key, serializer),
            None => serializer.emit_none(key),
        }
    }
}

impl Value for Box<Value + Send + 'static> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Arc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Rc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for core::num::Wrapping<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        self.0.serialize(record, key, serializer)
    }
}

impl<V: 'static + Value, F> Value for F
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self)(record).serialize(record, key, serializer)
    }
}

/// Explicit lazy-closure `Value`
pub struct FnValue<V: 'static + Value, F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V;

impl<V: 'static + Value, F> Value for FnValue<V, F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self.0)(record).serialize(record, key, serializer)
    }
}

/// Handle passed to `PushFnValue` closure
///
/// It makes sure only one value is serialized, and will automatically emit
/// `()` if nothing else was serialized.
pub struct PushFnSerializer<'a> {
    record: &'a Record<'a>,
    key: &'a str,
    serializer: &'a mut Serializer,
    done: bool,
}

impl<'a> PushFnSerializer<'a> {
    /// Serialize a value
    ///
    /// This consumes `self` to prevent serializing one value multiple times
    pub fn serialize<'b, S: 'b + Value>(mut self, s: S) -> Result {
        self.done = true;
        s.serialize(self.record, self.key, self.serializer)
    }
}

impl<'a> Drop for PushFnSerializer<'a> {
    fn drop(&mut self) {
        if !self.done {
            // unfortunately this gives no change to return serialization errors
            let _ = self.serializer.emit_unit(self.key);
        }
    }
}

/// Lazy `Value` that writes to Serializer
///
/// It's more natural for closures used as lazy values to return `Serialize`
/// implementing type, but sometimes that forces an allocation (eg. Strings)
///
/// In some cases it might make sense for another closure form to be used - one
/// taking a serializer as an argument, which avoids lifetimes / allocation issues.
///
/// Generally this method should be used if it avoids a big allocation of
/// `Serialize`-implementing type in performance-critical logging statement.
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::{PushFnValue, Logger, Discard};
///
/// fn main() {
///     let _root = Logger::root(Discard, o!( ));
///     info!(_root, "foo"; "writer_closure" => PushFnValue(|_ , s| {
///                    let generated_string = format!("{}", 1);
///                    s.serialize(generated_string.as_str())
///             }));
/// }
/// ```
pub struct PushFnValue<F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result;

impl<F> Value for PushFnValue<F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result
{
    fn serialize(&self, record: &Record, key: &str, serializer: &mut Serializer)
        -> Result {
        let ser = PushFnSerializer {
            record: record,
            key: key,
            serializer: serializer,
            done: false,
        };
        (self.0)(record, ser)
    }
}

/// Key-value pair(s) that can be serialized
///
/// Zero, one or more key value pairs chained together
pub trait KV {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
                 -> Result;

    /// Split into tuple of `(first, rest)`
    fn split_first(&self) -> Option<(&KV, &KV)>;
}

/// Single pair `Key` and `Value`
pub struct SingleKV<K, V>(pub K, pub V)
    where K : Key, V : Value;

impl<K, V> KV for SingleKV<K, V>
    where K : Key,
          V : Value
{
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            self.1.serialize(record, self.0.as_str(), serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((self, &STATIC_TERMINATOR_UNIT))
    }
}

impl KV for () {
    fn serialize(&self,
                 _record: &Record,
                 _serializer: &mut Serializer)
        -> Result {
            Ok(())
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        None
    }
}

impl<T: KV, R: KV> KV for (T, R) {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            try!(self.0.serialize(record, serializer));
            self.1.serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((&self.0, &self.1))
    }
}

impl<T> KV for Box<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}

impl<T> KV for Arc<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}
<|endoftext|>


<commit_before>extern crate r6;

use std::collections::HashMap;
use std::rc::Rc;
use std::io::BufReader;
use std::borrow::Cow;
use r6::runtime::Runtime;
use r6::compiler::{Compiler, EnvVar, Syntax};
use r6::primitive::PRIM_ADD;
use r6::parser::Parser;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let mut glob = HashMap::new();
            glob.insert(Cow::Borrowed("lambda"), EnvVar::Syntax(Syntax::Lambda));
            glob.insert(Cow::Borrowed("+"), EnvVar::PrimFunc("+", Rc::new(PRIM_ADD)));
            let mut compiler = Compiler::new(&glob);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}
<commit_msg>Test code using libbase instead of manual library instantiation<commit_after>extern crate r6;

use std::io::BufReader;
use r6::runtime::Runtime;
use r6::compiler::Compiler;
use r6::base::libbase;
use r6::parser::Parser;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let base = libbase();
            let mut compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}
<|endoftext|>


<commit_before>use crate::common::*;
use crate::data::packet::Packet;
use crate::data::value::*;
use std::any::Any;
use std::io::{Cursor, ErrorKind, Seek, SeekFrom, Write};
use std::sync::Arc;

use crate::error::*;

/// A trait for a non-seekable object.
pub trait WriteOwned: Write {}
/// A trait for a seekable object.
pub trait WriteSeek: Write + Seek {}

impl<T: Write> WriteOwned for T {}
impl<T: Write + Seek> WriteSeek for T {}

/// Runtime wrapper around either a [`Write`] or a [`WriteSeek`] trait object
/// which supports querying for seek support.
pub enum Writer<WO = Cursor<Vec<u8>>, WS = Cursor<Vec<u8>>> {
    NonSeekable(WO, u64),
    Seekable(WS),
}

impl<WO: WriteOwned> Writer<WO, Cursor<Vec<u8>>> {
    /// Creates a [`Writer`] from an object that implements the [`Write`] trait.
    pub fn from_nonseekable(inner: WO) -> Self {
        Self::NonSeekable(inner, 0)
    }
}

impl<WS: WriteSeek> Writer<Cursor<Vec<u8>>, WS> {
    /// Creates a [`Writer`] from an object that implements both
    /// [`Write`] and [`Seek`] traits.
    pub fn from_seekable(inner: WS) -> Self {
        Self::Seekable(inner)
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Writer<WO, WS> {
    /// Returns whether the [`Writer`] can seek within the source.
    pub fn is_seekable(&self) -> bool {
        matches!(self, Self::Seekable(_))
    }

    /// Returns stream position.
    pub fn position(&mut self) -> Result<u64> {
        match self {
            Self::NonSeekable(_, index) => Ok(*index),
            Self::Seekable(ref mut inner) => inner.stream_position().map_err(|e| e.into()),
        }
    }

    /// Returns a reference to the non-seekable object whether is present.
    pub fn non_seekable_object(&self) -> Option<(&WO, u64)> {
        if let Self::NonSeekable(inner, index) = self {
            Some((inner, *index))
        } else {
            None
        }
    }

    /// Returns a reference to the seekable object whether is present.
    pub fn seekable_object(&self) -> Option<&WS> {
        if let Self::Seekable(inner) = self {
            Some(inner)
        } else {
            None
        }
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Write for Writer<WO, WS> {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        match self {
            Self::NonSeekable(inner, ref mut index) => {
                let result = inner.write(bytes);

                if let Ok(written) = result {
                    *index += written as u64;
                }

                result
            }
            Self::Seekable(inner) => inner.write(bytes),
        }
    }

    fn flush(&mut self) -> std::io::Result<()> {
        match self {
            Self::NonSeekable(inner, ..) => inner.flush(),
            Self::Seekable(inner) => inner.flush(),
        }
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Seek for Writer<WO, WS> {
    fn seek(&mut self, seek: SeekFrom) -> std::io::Result<u64> {
        match self {
            Self::NonSeekable(_, index) => {
                if let SeekFrom::Current(0) = seek {
                    Ok(*index)
                } else {
                    Err(std::io::Error::new(
                        ErrorKind::Other,
                        "Seeking not supported",
                    ))
                }
            }
            Self::Seekable(inner) => inner.seek(seek),
        }
    }
}

/// Used to implement muxing operations.
pub trait Muxer: Send {
    /// Configures a muxer.
    fn configure(&mut self) -> Result<()>;
    /// Writes a stream header into a data structure implementing
    /// the `Write` trait.
    fn write_header<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
    ) -> Result<()>;
    /// Writes a stream packet into a data structure implementing
    /// the `Write` trait.
    fn write_packet<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
        pkt: Arc<Packet>,
    ) -> Result<()>;
    /// Writes a stream trailer into a data structure implementing
    /// the `Write` trait.
    fn write_trailer<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
    ) -> Result<()>;

    /// Sets global media file information for a muxer.
    fn set_global_info(&mut self, info: GlobalInfo) -> Result<()>;
    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
}

/// Auxiliary structure to encapsulate a muxer object and
/// its additional data.
pub struct Context<M: Muxer + Send, WO: WriteOwned, WS: WriteSeek> {
    muxer: M,
    writer: Writer<WO, WS>,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Box<dyn Any + Send + Sync>>,
}

impl<M: Muxer + Send, WO: WriteOwned, WS: WriteSeek> Context<M, WO, WS> {
    /// Creates a new `Context` instance.
    pub fn new(muxer: M, writer: Writer<WO, WS>) -> Self {
        Context {
            muxer,
            writer,
            user_private: None,
        }
    }

    /// Configures a muxer.
    pub fn configure(&mut self) -> Result<()> {
        self.muxer.configure()
    }

    /// Writes a stream header to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_header(&mut self) -> Result<()> {
        self.muxer.write_header(&mut self.writer)
    }

    /// Writes a stream packet to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_packet(&mut self, pkt: Arc<Packet>) -> Result<()> {
        self.muxer.write_packet(&mut self.writer, pkt)
    }

    /// Writes a stream trailer to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_trailer(&mut self) -> Result<()> {
        self.muxer.write_trailer(&mut self.writer)?;
        self.writer.flush()?;

        Ok(())
    }

    /// Sets global media file information for a muxer.
    pub fn set_global_info(&mut self, info: GlobalInfo) -> Result<()> {
        self.muxer.set_global_info(info)
    }

    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        self.muxer.set_option(key, val.into())
    }

    /// Returns the underlying writer.
    pub fn writer(&self) -> &Writer<WO, WS> {
        &self.writer
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own muxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Muxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new muxer.
pub trait Descriptor {
    type OutputMuxer: Muxer + Send;

    /// Creates a new muxer for the requested format.
    fn create(&self) -> Self::OutputMuxer;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;
}

/// Used to look for a specific format.
pub trait Lookup<T: Descriptor + ?Sized> {
    /// Retrieves a specific format by name.
    fn by_name(&self, name: &str) -> Option<&'static T>;
}

impl<T: Descriptor + ?Sized> Lookup<T> for [&'static T] {
    fn by_name(&self, name: &str) -> Option<&'static T> {
        self.iter().find(|&&d| d.describe().name == name).copied()
    }
}

#[cfg(test)]
mod test {
    use std::io::Cursor;

    use super::*;

    const DUMMY_HEADER_LENGTH: usize = 12;
    const DUMMY_PACKET_LENGTH: usize = 2;
    const DUMMY_PACKETS_NUMBER: usize = 2;
    const DUMMY_TRAILER_LENGTH: usize = 13;

    struct DummyDes {
        d: Descr,
    }

    struct DummyMuxer {}

    impl DummyMuxer {
        pub fn new() -> Self {
            Self {}
        }
    }

    impl Muxer for DummyMuxer {
        fn configure(&mut self) -> Result<()> {
            Ok(())
        }

        fn write_header<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
        ) -> Result<()> {
            let buf = b"Dummy header";
            out.write_all(buf.as_slice()).unwrap();
            Ok(())
        }

        fn write_packet<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
            pkt: Arc<Packet>,
        ) -> Result<()> {
            out.write_all(&pkt.data).unwrap();
            Ok(())
        }

        fn write_trailer<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
        ) -> Result<()> {
            let buf = b"Dummy trailer";
            out.write_all(buf.as_slice()).unwrap();
            Ok(())
        }

        fn set_global_info(&mut self, _info: GlobalInfo) -> Result<()> {
            Ok(())
        }

        fn set_option<'a>(&mut self, _key: &str, _val: Value<'a>) -> Result<()> {
            Ok(())
        }
    }

    impl Descriptor for DummyDes {
        type OutputMuxer = DummyMuxer;

        fn create(&self) -> Self::OutputMuxer {
            DummyMuxer {}
        }
        fn describe(&self) -> &Descr {
            &self.d
        }
    }

    const DUMMY_DES: &dyn Descriptor<OutputMuxer = DummyMuxer> = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy mux",
            extensions: &["mx", "mux"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn lookup() {
        let muxers: &[&dyn Descriptor<OutputMuxer = DummyMuxer>] = &[DUMMY_DES];

        muxers.by_name("dummy").unwrap();
    }

    fn run_muxer<WO: WriteOwned, WS: WriteSeek>(
        writer: Writer<WO, WS>,
    ) -> Context<DummyMuxer, WO, WS> {
        let mux = DummyMuxer::new();

        let mut muxer = Context::new(mux, writer);

        muxer.configure().unwrap();
        muxer.write_header().unwrap();

        // Write zeroed packets of a certain size
        for _ in 0..DUMMY_PACKETS_NUMBER {
            let packet = Packet::zeroed(DUMMY_PACKET_LENGTH);
            muxer.write_packet(Arc::new(packet)).unwrap();
        }

        muxer.write_trailer().unwrap();
        muxer
    }

    fn check_underlying_buffer(buffer: &[u8]) {
        assert_eq!(
            buffer.get(..DUMMY_HEADER_LENGTH).unwrap(),
            b"Dummy header".as_slice()
        );

        assert_eq!(
            buffer
                // Get only packets, without header and trailer data
                .get(
                    DUMMY_HEADER_LENGTH
                        ..DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
                )
                .unwrap(),
            &[0, 0, 0, 0]
        );

        assert_eq!(
            buffer
                // Skip header and packets
                .get(DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)..)
                .unwrap(),
            b"Dummy trailer".as_slice()
        );
    }

    #[test]
    fn non_seekable_muxer() {
        let muxer = run_muxer(Writer::from_nonseekable(Vec::new()));
        let (buffer, index) = muxer.writer().non_seekable_object().unwrap();
        debug_assert!(!muxer.writer().is_seekable());
        check_underlying_buffer(buffer);
        assert_eq!(
            index as usize,
            DUMMY_HEADER_LENGTH
                + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
                + DUMMY_TRAILER_LENGTH
        );
    }

    #[test]
    fn seekable_muxer() {
        let muxer = run_muxer(Writer::from_seekable(Cursor::new(Vec::new())));
        let buffer = muxer.writer().seekable_object().unwrap().get_ref();
        debug_assert!(muxer.writer().is_seekable());
        check_underlying_buffer(buffer);
    }
}
<commit_msg>format: Remove Send trait from muxer context<commit_after>use crate::common::*;
use crate::data::packet::Packet;
use crate::data::value::*;
use std::any::Any;
use std::io::{Cursor, ErrorKind, Seek, SeekFrom, Write};
use std::sync::Arc;

use crate::error::*;

/// A trait for a non-seekable object.
pub trait WriteOwned: Write {}
/// A trait for a seekable object.
pub trait WriteSeek: Write + Seek {}

impl<T: Write> WriteOwned for T {}
impl<T: Write + Seek> WriteSeek for T {}

/// Runtime wrapper around either a [`Write`] or a [`WriteSeek`] trait object
/// which supports querying for seek support.
pub enum Writer<WO = Cursor<Vec<u8>>, WS = Cursor<Vec<u8>>> {
    NonSeekable(WO, u64),
    Seekable(WS),
}

impl<WO: WriteOwned> Writer<WO, Cursor<Vec<u8>>> {
    /// Creates a [`Writer`] from an object that implements the [`Write`] trait.
    pub fn from_nonseekable(inner: WO) -> Self {
        Self::NonSeekable(inner, 0)
    }
}

impl<WS: WriteSeek> Writer<Cursor<Vec<u8>>, WS> {
    /// Creates a [`Writer`] from an object that implements both
    /// [`Write`] and [`Seek`] traits.
    pub fn from_seekable(inner: WS) -> Self {
        Self::Seekable(inner)
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Writer<WO, WS> {
    /// Returns whether the [`Writer`] can seek within the source.
    pub fn is_seekable(&self) -> bool {
        matches!(self, Self::Seekable(_))
    }

    /// Returns stream position.
    pub fn position(&mut self) -> Result<u64> {
        match self {
            Self::NonSeekable(_, index) => Ok(*index),
            Self::Seekable(ref mut inner) => inner.stream_position().map_err(|e| e.into()),
        }
    }

    /// Returns a reference to the non-seekable object whether is present.
    pub fn non_seekable_object(&self) -> Option<(&WO, u64)> {
        if let Self::NonSeekable(inner, index) = self {
            Some((inner, *index))
        } else {
            None
        }
    }

    /// Returns a reference to the seekable object whether is present.
    pub fn seekable_object(&self) -> Option<&WS> {
        if let Self::Seekable(inner) = self {
            Some(inner)
        } else {
            None
        }
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Write for Writer<WO, WS> {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        match self {
            Self::NonSeekable(inner, ref mut index) => {
                let result = inner.write(bytes);

                if let Ok(written) = result {
                    *index += written as u64;
                }

                result
            }
            Self::Seekable(inner) => inner.write(bytes),
        }
    }

    fn flush(&mut self) -> std::io::Result<()> {
        match self {
            Self::NonSeekable(inner, ..) => inner.flush(),
            Self::Seekable(inner) => inner.flush(),
        }
    }
}

impl<WO: WriteOwned, WS: WriteSeek> Seek for Writer<WO, WS> {
    fn seek(&mut self, seek: SeekFrom) -> std::io::Result<u64> {
        match self {
            Self::NonSeekable(_, index) => {
                if let SeekFrom::Current(0) = seek {
                    Ok(*index)
                } else {
                    Err(std::io::Error::new(
                        ErrorKind::Other,
                        "Seeking not supported",
                    ))
                }
            }
            Self::Seekable(inner) => inner.seek(seek),
        }
    }
}

/// Used to implement muxing operations.
pub trait Muxer: Send {
    /// Configures a muxer.
    fn configure(&mut self) -> Result<()>;
    /// Writes a stream header into a data structure implementing
    /// the `Write` trait.
    fn write_header<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
    ) -> Result<()>;
    /// Writes a stream packet into a data structure implementing
    /// the `Write` trait.
    fn write_packet<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
        pkt: Arc<Packet>,
    ) -> Result<()>;
    /// Writes a stream trailer into a data structure implementing
    /// the `Write` trait.
    fn write_trailer<WO: WriteOwned, WS: WriteSeek>(
        &mut self,
        out: &mut Writer<WO, WS>,
    ) -> Result<()>;

    /// Sets global media file information for a muxer.
    fn set_global_info(&mut self, info: GlobalInfo) -> Result<()>;
    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
}

/// Auxiliary structure to encapsulate a muxer object and
/// its additional data.
pub struct Context<M: Muxer + Send, WO: WriteOwned, WS: WriteSeek> {
    muxer: M,
    writer: Writer<WO, WS>,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Box<dyn Any + Send + Sync>>,
}

impl<M: Muxer, WO: WriteOwned, WS: WriteSeek> Context<M, WO, WS> {
    /// Creates a new `Context` instance.
    pub fn new(muxer: M, writer: Writer<WO, WS>) -> Self {
        Context {
            muxer,
            writer,
            user_private: None,
        }
    }

    /// Configures a muxer.
    pub fn configure(&mut self) -> Result<()> {
        self.muxer.configure()
    }

    /// Writes a stream header to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_header(&mut self) -> Result<()> {
        self.muxer.write_header(&mut self.writer)
    }

    /// Writes a stream packet to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_packet(&mut self, pkt: Arc<Packet>) -> Result<()> {
        self.muxer.write_packet(&mut self.writer, pkt)
    }

    /// Writes a stream trailer to an internal buffer and returns how many
    /// bytes were written or an error.
    pub fn write_trailer(&mut self) -> Result<()> {
        self.muxer.write_trailer(&mut self.writer)?;
        self.writer.flush()?;

        Ok(())
    }

    /// Sets global media file information for a muxer.
    pub fn set_global_info(&mut self, info: GlobalInfo) -> Result<()> {
        self.muxer.set_global_info(info)
    }

    /// Sets a muxer option.
    ///
    /// This method should be called as many times as the number of options
    /// present in a muxer.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        self.muxer.set_option(key, val.into())
    }

    /// Returns the underlying writer.
    pub fn writer(&self) -> &Writer<WO, WS> {
        &self.writer
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own muxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Muxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new muxer.
pub trait Descriptor {
    type OutputMuxer: Muxer + Send;

    /// Creates a new muxer for the requested format.
    fn create(&self) -> Self::OutputMuxer;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;
}

/// Used to look for a specific format.
pub trait Lookup<T: Descriptor + ?Sized> {
    /// Retrieves a specific format by name.
    fn by_name(&self, name: &str) -> Option<&'static T>;
}

impl<T: Descriptor + ?Sized> Lookup<T> for [&'static T] {
    fn by_name(&self, name: &str) -> Option<&'static T> {
        self.iter().find(|&&d| d.describe().name == name).copied()
    }
}

#[cfg(test)]
mod test {
    use std::io::Cursor;

    use super::*;

    const DUMMY_HEADER_LENGTH: usize = 12;
    const DUMMY_PACKET_LENGTH: usize = 2;
    const DUMMY_PACKETS_NUMBER: usize = 2;
    const DUMMY_TRAILER_LENGTH: usize = 13;

    struct DummyDes {
        d: Descr,
    }

    struct DummyMuxer {}

    impl DummyMuxer {
        pub fn new() -> Self {
            Self {}
        }
    }

    impl Muxer for DummyMuxer {
        fn configure(&mut self) -> Result<()> {
            Ok(())
        }

        fn write_header<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
        ) -> Result<()> {
            let buf = b"Dummy header";
            out.write_all(buf.as_slice()).unwrap();
            Ok(())
        }

        fn write_packet<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
            pkt: Arc<Packet>,
        ) -> Result<()> {
            out.write_all(&pkt.data).unwrap();
            Ok(())
        }

        fn write_trailer<WO: WriteOwned, WS: WriteSeek>(
            &mut self,
            out: &mut Writer<WO, WS>,
        ) -> Result<()> {
            let buf = b"Dummy trailer";
            out.write_all(buf.as_slice()).unwrap();
            Ok(())
        }

        fn set_global_info(&mut self, _info: GlobalInfo) -> Result<()> {
            Ok(())
        }

        fn set_option<'a>(&mut self, _key: &str, _val: Value<'a>) -> Result<()> {
            Ok(())
        }
    }

    impl Descriptor for DummyDes {
        type OutputMuxer = DummyMuxer;

        fn create(&self) -> Self::OutputMuxer {
            DummyMuxer {}
        }
        fn describe(&self) -> &Descr {
            &self.d
        }
    }

    const DUMMY_DES: &dyn Descriptor<OutputMuxer = DummyMuxer> = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy mux",
            extensions: &["mx", "mux"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn lookup() {
        let muxers: &[&dyn Descriptor<OutputMuxer = DummyMuxer>] = &[DUMMY_DES];

        muxers.by_name("dummy").unwrap();
    }

    fn run_muxer<WO: WriteOwned, WS: WriteSeek>(
        writer: Writer<WO, WS>,
    ) -> Context<DummyMuxer, WO, WS> {
        let mux = DummyMuxer::new();

        let mut muxer = Context::new(mux, writer);

        muxer.configure().unwrap();
        muxer.write_header().unwrap();

        // Write zeroed packets of a certain size
        for _ in 0..DUMMY_PACKETS_NUMBER {
            let packet = Packet::zeroed(DUMMY_PACKET_LENGTH);
            muxer.write_packet(Arc::new(packet)).unwrap();
        }

        muxer.write_trailer().unwrap();
        muxer
    }

    fn check_underlying_buffer(buffer: &[u8]) {
        assert_eq!(
            buffer.get(..DUMMY_HEADER_LENGTH).unwrap(),
            b"Dummy header".as_slice()
        );

        assert_eq!(
            buffer
                // Get only packets, without header and trailer data
                .get(
                    DUMMY_HEADER_LENGTH
                        ..DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
                )
                .unwrap(),
            &[0, 0, 0, 0]
        );

        assert_eq!(
            buffer
                // Skip header and packets
                .get(DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)..)
                .unwrap(),
            b"Dummy trailer".as_slice()
        );
    }

    #[test]
    fn non_seekable_muxer() {
        let muxer = run_muxer(Writer::from_nonseekable(Vec::new()));
        let (buffer, index) = muxer.writer().non_seekable_object().unwrap();
        debug_assert!(!muxer.writer().is_seekable());
        check_underlying_buffer(buffer);
        assert_eq!(
            index as usize,
            DUMMY_HEADER_LENGTH
                + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
                + DUMMY_TRAILER_LENGTH
        );
    }

    #[test]
    fn seekable_muxer() {
        let muxer = run_muxer(Writer::from_seekable(Cursor::new(Vec::new())));
        let buffer = muxer.writer().seekable_object().unwrap().get_ref();
        debug_assert!(muxer.writer().is_seekable());
        check_underlying_buffer(buffer);
    }
}
<|endoftext|>


<commit_before>//! Axis enum for indexing three-dimensional structures.

#![allow(unused)]
use crate::{Point3, Vector3};
use std::fmt::{Display, Formatter, Result};
use std::ops::{Index, IndexMut};

struct MyType<T>(T);

/// An `Axis` in a three-dimensional coordinate system.
/// Used to access `Vector3`/`Point3` structs via index.
///
/// # Examples
/// ```
/// use bvh::axis::Axis;
///
/// let mut position = [1.0, 0.5, 42.0];
/// position[Axis::Y] *= 4.0;
///
/// assert_eq!(position[Axis::Y], 2.0);
/// ```
///
/// [`Point3`] and [`Vector3`] are also indexable using `Axis`.
///
/// ```
/// extern crate bvh;
///
/// use bvh::axis::Axis;
/// use bvh::Point3;
///
/// # fn main() {
/// let mut position: Point3 = Point3::new(1.0, 2.0, 3.0);
/// position[Axis::X] = 1000.0;
///
/// assert_eq!(position[Axis::X], 1000.0);
/// # }
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Axis {
    /// Index of the X axis.
    X = 0,

    /// Index of the Y axis.
    Y = 1,

    /// Index of the Z axis.
    Z = 2,
}

/// Display implementation for `Axis`.
impl Display for Axis {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(
            f,
            "{}",
            match *self {
                Axis::X => "x",
                Axis::Y => "y",
                Axis::Z => "z",
            }
        )
    }
}

/// Make slices indexable by `Axis`.
impl Index<Axis> for [f32] {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        &self[axis as usize]
    }
}

/// Make `Point3` indexable by `Axis`.
impl Index<Axis> for Point3 {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}

/// Make `Vector3` indexable by `Axis`.
impl Index<Axis> for MyType<Vector3> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.0.x,
            Axis::Y => &self.0.y,
            Axis::Z => &self.0.z,
        }
    }
}

/// Make slices mutably accessible by `Axis`.
impl IndexMut<Axis> for [f32] {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        &mut self[axis as usize]
    }
}

/// Make `Point3` mutably accessible by `Axis`.
impl IndexMut<Axis> for Point3 {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        match axis {
            Axis::X => &mut self.x,
            Axis::Y => &mut self.y,
            Axis::Z => &mut self.z,
        }
    }
}

/// Make `Vector3` mutably accessible by `Axis`.
impl IndexMut<Axis> for MyType<Vector3> {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        match axis {
            Axis::X => &mut self.0.x,
            Axis::Y => &mut self.0.y,
            Axis::Z => &mut self.0.z,
        }
    }
}

#[cfg(test)]
mod test {
    use crate::axis::Axis;
    use proptest::prelude::*;

    proptest! {
        // Test whether accessing arrays by index is the same as accessing them by `Axis`.
        #[test]
        fn test_index_by_axis(tpl: (f32, f32, f32)) {
            let a = [tpl.0, tpl.1, tpl.2];

            assert!((a[0] - a[Axis::X]).abs() < f32::EPSILON && (a[1] - a[Axis::Y]).abs() < f32::EPSILON && (a[2] - a[Axis::Z]).abs() < f32::EPSILON);
        }

        // Test whether arrays can be mutably set, by indexing via `Axis`.
        #[test]
        fn test_set_by_axis(tpl: (f32, f32, f32)) {
            let mut a = [0.0, 0.0, 0.0];

            a[Axis::X] = tpl.0;
            a[Axis::Y] = tpl.1;
            a[Axis::Z] = tpl.2;

            assert!((a[0] - tpl.0).abs() < f32::EPSILON && (a[1] - tpl.1).abs() < f32::EPSILON && (a[2] - tpl.2).abs() < f32::EPSILON);
        }
    }
}
<commit_msg>Make clippy happy<commit_after>//! Axis enum for indexing three-dimensional structures.

#![allow(unused)]
use crate::{Point3, Vector3};
use std::fmt::{Display, Formatter, Result};
use std::ops::{Index, IndexMut};

struct MyType<T>(T);

/// An `Axis` in a three-dimensional coordinate system.
/// Used to access `Vector3`/`Point3` structs via index.
///
/// # Examples
/// ```
/// use bvh::axis::Axis;
///
/// let mut position = [1.0, 0.5, 42.0];
/// position[Axis::Y] *= 4.0;
///
/// assert_eq!(position[Axis::Y], 2.0);
/// ```
///
/// [`Point3`] and [`Vector3`] are also indexable using `Axis`.
///
/// ```
/// extern crate bvh;
///
/// use bvh::axis::Axis;
/// use bvh::Point3;
///
/// # fn main() {
/// let mut position: Point3 = Point3::new(1.0, 2.0, 3.0);
/// position[Axis::X] = 1000.0;
///
/// assert_eq!(position[Axis::X], 1000.0);
/// # }
/// ```
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Axis {
    /// Index of the X axis.
    X = 0,

    /// Index of the Y axis.
    Y = 1,

    /// Index of the Z axis.
    Z = 2,
}

/// Display implementation for `Axis`.
impl Display for Axis {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(
            f,
            "{}",
            match *self {
                Axis::X => "x",
                Axis::Y => "y",
                Axis::Z => "z",
            }
        )
    }
}

/// Make slices indexable by `Axis`.
impl Index<Axis> for [f32] {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        &self[axis as usize]
    }
}

/// Make `Point3` indexable by `Axis`.
impl Index<Axis> for Point3 {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
            Axis::Z => &self.z,
        }
    }
}

/// Make `Vector3` indexable by `Axis`.
impl Index<Axis> for MyType<Vector3> {
    type Output = f32;

    fn index(&self, axis: Axis) -> &f32 {
        match axis {
            Axis::X => &self.0.x,
            Axis::Y => &self.0.y,
            Axis::Z => &self.0.z,
        }
    }
}

/// Make slices mutably accessible by `Axis`.
impl IndexMut<Axis> for [f32] {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        &mut self[axis as usize]
    }
}

/// Make `Point3` mutably accessible by `Axis`.
impl IndexMut<Axis> for Point3 {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        match axis {
            Axis::X => &mut self.x,
            Axis::Y => &mut self.y,
            Axis::Z => &mut self.z,
        }
    }
}

/// Make `Vector3` mutably accessible by `Axis`.
impl IndexMut<Axis> for MyType<Vector3> {
    fn index_mut(&mut self, axis: Axis) -> &mut f32 {
        match axis {
            Axis::X => &mut self.0.x,
            Axis::Y => &mut self.0.y,
            Axis::Z => &mut self.0.z,
        }
    }
}

#[cfg(test)]
mod test {
    use crate::axis::Axis;
    use proptest::prelude::*;

    proptest! {
        // Test whether accessing arrays by index is the same as accessing them by `Axis`.
        #[test]
        fn test_index_by_axis(tpl: (f32, f32, f32)) {
            let a = [tpl.0, tpl.1, tpl.2];

            assert!((a[0] - a[Axis::X]).abs() < f32::EPSILON && (a[1] - a[Axis::Y]).abs() < f32::EPSILON && (a[2] - a[Axis::Z]).abs() < f32::EPSILON);
        }

        // Test whether arrays can be mutably set, by indexing via `Axis`.
        #[test]
        fn test_set_by_axis(tpl: (f32, f32, f32)) {
            let mut a = [0.0, 0.0, 0.0];

            a[Axis::X] = tpl.0;
            a[Axis::Y] = tpl.1;
            a[Axis::Z] = tpl.2;

            assert!((a[0] - tpl.0).abs() < f32::EPSILON && (a[1] - tpl.1).abs() < f32::EPSILON && (a[2] - tpl.2).abs() < f32::EPSILON);
        }
    }
}
<|endoftext|>


<commit_before>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A [`Conf`](struct.Conf.html) struct is used to create a config file
//! which specifies hardware setup stuff, mostly video display settings.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the [`Context`](../struct.Context.html) is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.
//! If no file is found, it will create a `Conf` object from the settings
//! passed to the [`ContextBuilder`](../struct.ContextBuilder.html).

use std::convert::TryFrom;
use std::io;

use crate::error::{GameError, GameResult};

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode.
    Windowed,
    /// True fullscreen, which used to be preferred 'cause it can have
    /// small performance benefits over windowed fullscreen.
    ///
    /// Also it allows us to set different resolutions.
    True,
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop,
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with [`graphics::set_mode()`](../graphics/fn.set_mode.html).
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// WindowMode {
///     width: 800.0,
///     height: 600.0,
///     maximized: false,
///     fullscreen_type: FullscreenType::Windowed,
///     borderless: false,
///     min_width: 0.0,
///     max_width: 0.0,
///     min_height: 0.0,
///     max_height: 0.0,
///     resizable: false,
///     visible: true,
/// }
/// # , WindowMode::default());}
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq)]
pub struct WindowMode {
    /// Window width
    #[default = 800.0]
    pub width: f32,
    /// Window height
    #[default = 600.0]
    pub height: f32,
    /// Whether or not to maximize the window
    #[default = false]
    pub maximized: bool,
    /// Fullscreen type
    #[default(FullscreenType::Windowed)]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to show window decorations
    #[default = false]
    pub borderless: bool,
    /// Minimum width for resizable windows; 0 means no limit
    #[default = 0.0]
    pub min_width: f32,
    /// Minimum height for resizable windows; 0 means no limit
    #[default = 0.0]
    pub min_height: f32,
    /// Maximum width for resizable windows; 0 means no limit
    #[default = 0.0]
    pub max_width: f32,
    /// Maximum height for resizable windows; 0 means no limit
    #[default = 0.0]
    pub max_height: f32,
    /// Whether or not the window is resizable
    #[default = false]
    pub resizable: bool,
    /// Whether this window should displayed (true) or hidden (false)
    #[default = true]
    pub visible: bool,
}

impl WindowMode {
    /// Set default window size, or screen resolution in true fullscreen mode.
    pub fn dimensions(mut self, width: f32, height: f32) -> Self {
        self.width = width;
        self.height = height;
        self
    }

    /// Set whether the window should be maximized.
    pub fn maximized(mut self, maximized: bool) -> Self {
        self.maximized = maximized;
        self
    }

    /// Set the fullscreen type.
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set whether a window should be borderless in windowed mode.
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set minimum window dimensions for windowed mode.
    pub fn min_dimensions(mut self, width: f32, height: f32) -> Self {
        self.min_width = width;
        self.min_height = height;
        self
    }

    /// Set maximum window dimensions for windowed mode.
    pub fn max_dimensions(mut self, width: f32, height: f32) -> Self {
        self.max_width = width;
        self.max_height = height;
        self
    }

    /// Set resizable.
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set visibility
    pub fn visible(mut self, visible: bool) -> Self {
        self.visible = visible;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// WindowSetup {
///     title: "An easy, good game".to_owned(),
///     samples: NumSamples::Zero,
///     vsync: true,
///     icon: "".to_owned(),
///     srgb: true,
/// }
/// # , WindowSetup::default()); }
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq)]
pub struct WindowSetup {
    /// The window title.
    #[default(String::from("An easy, good game"))]
    pub title: String,
    /// Number of samples to use for multisample anti-aliasing.
    #[default(NumSamples::One)]
    pub samples: NumSamples,
    /// Whether or not to enable vsync.
    #[default = true]
    pub vsync: bool,
    /// A file path to the window's icon.
    /// It takes a path rooted in the `resources` directory (see the [`filesystem`](../filesystem/index.html)
    /// module for details), and an empty string results in a blank/default icon.
    #[default(String::new())]
    pub icon: String,
    /// Whether or not to enable sRGB (gamma corrected color)
    /// handling on the display.
    #[default = true]
    pub srgb: bool,
}

impl WindowSetup {
    /// Set window title.
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set number of samples to use for multisample anti-aliasing.
    pub fn samples(mut self, samples: NumSamples) -> Self {
        self.samples = samples;
        self
    }

    /// Set whether vsync is enabled.
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set sRGB color mode.
    pub fn srgb(mut self, active: bool) -> Self {
        self.srgb = active;
        self
    }
}

/// Possible backends.
/// Currently, only OpenGL and OpenGL ES Core specs are supported,
/// but this lets you specify which to use as well as the version numbers.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// Backend::OpenGL {
///     major: 3,
///     minor: 2,
/// }
/// # , Backend::default()); }
/// ```
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't).
    #[default]
    #[allow(clippy::upper_case_acronyms)]
    OpenGL {
        /// OpenGL major version
        #[default = 3]
        major: u8,
        /// OpenGL minor version
        #[default = 2]
        minor: u8,
    },
    /// OpenGL ES, defaults to 3.0.  Used for phones and other mobile
    /// devices.  Using something older
    /// than 3.0 starts to running into sticky limitations, particularly
    /// with instanced drawing (used for `SpriteBatch`), but might be
    /// possible.
    #[allow(clippy::upper_case_acronyms)]
    OpenGLES {
        /// OpenGL ES major version
        #[default = 3]
        major: u8,
        /// OpenGL ES minor version
        #[default = 0]
        minor: u8,
    },
}

impl Backend {
    /// Set requested OpenGL/OpenGL ES version.
    pub fn version(self, new_major: u8, new_minor: u8) -> Self {
        match self {
            Backend::OpenGL { .. } => Backend::OpenGL {
                major: new_major,
                minor: new_minor,
            },
            Backend::OpenGLES { .. } => Backend::OpenGLES {
                major: new_major,
                minor: new_minor,
            },
        }
    }

    /// Use OpenGL
    pub fn gl(self) -> Self {
        match self {
            Backend::OpenGLES { major, minor } => Backend::OpenGL { major, minor },
            gl => gl,
        }
    }

    /// Use OpenGL ES
    pub fn gles(self) -> Self {
        match self {
            Backend::OpenGL { major, minor } => Backend::OpenGLES { major, minor },
            es => es,
        }
    }
}

/// The possible number of samples for multisample anti-aliasing.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl TryFrom<u8> for NumSamples {
    type Error = GameError;
    fn try_from(i: u8) -> Result<Self, Self::Error> {
        match i {
            1 => Ok(NumSamples::One),
            2 => Ok(NumSamples::Two),
            4 => Ok(NumSamples::Four),
            8 => Ok(NumSamples::Eight),
            16 => Ok(NumSamples::Sixteen),
            _ => Err(GameError::ConfigError(String::from(
                "Invalid number of samples",
            ))),
        }
    }
}

impl Into<u8> for NumSamples {
    fn into(self) -> u8 {
        self as u8
    }
}

/// Defines which submodules to enable in ggez.
/// If one tries to use a submodule that is not enabled,
/// it will panic.  Currently, not all subsystems can be
/// disabled.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// ModuleConf {
///     gamepad: true,
///     audio: true,
/// }
/// # , ModuleConf::default()); }
/// ```
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, SmartDefault)]
pub struct ModuleConf {
    /// The gamepad input module.
    #[default = true]
    pub gamepad: bool,

    /// The audio module.
    #[default = true]
    pub audio: bool,
}

impl ModuleConf {
    /// Sets whether or not to enable the gamepad input module.
    pub fn gamepad(mut self, gamepad: bool) -> Self {
        self.gamepad = gamepad;
        self
    }

    /// Sets whether or not to enable the audio module.
    pub fn audio(mut self, audio: bool) -> Self {
        self.audio = audio;
        self
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::default(),
///     modules: ModuleConf::default(),
/// }
/// # , Conf::default()); }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault, Clone)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Graphics backend configuration
    pub backend: Backend,
    /// Which modules to enable.
    pub modules: ModuleConf,
}

impl Conf {
    /// Same as `Conf::default()`
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        let _ = file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }

    /// Sets the window mode
    pub fn window_mode(mut self, window_mode: WindowMode) -> Self {
        self.window_mode = window_mode;
        self
    }

    /// Sets the backend
    pub fn backend(mut self, backend: Backend) -> Self {
        self.backend = backend;
        self
    }

    /// Sets the backend
    pub fn modules(mut self, modules: ModuleConf) -> Self {
        self.modules = modules;
        self
    }
}

#[cfg(test)]
mod tests {
    use crate::conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn headless_encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<commit_msg>Use `From` instead of `Into` for `NumSamples`<commit_after>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A [`Conf`](struct.Conf.html) struct is used to create a config file
//! which specifies hardware setup stuff, mostly video display settings.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the [`Context`](../struct.Context.html) is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.
//! If no file is found, it will create a `Conf` object from the settings
//! passed to the [`ContextBuilder`](../struct.ContextBuilder.html).

use std::convert::TryFrom;
use std::io;

use crate::error::{GameError, GameResult};

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode.
    Windowed,
    /// True fullscreen, which used to be preferred 'cause it can have
    /// small performance benefits over windowed fullscreen.
    ///
    /// Also it allows us to set different resolutions.
    True,
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop,
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with [`graphics::set_mode()`](../graphics/fn.set_mode.html).
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// WindowMode {
///     width: 800.0,
///     height: 600.0,
///     maximized: false,
///     fullscreen_type: FullscreenType::Windowed,
///     borderless: false,
///     min_width: 0.0,
///     max_width: 0.0,
///     min_height: 0.0,
///     max_height: 0.0,
///     resizable: false,
///     visible: true,
/// }
/// # , WindowMode::default());}
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq)]
pub struct WindowMode {
    /// Window width
    #[default = 800.0]
    pub width: f32,
    /// Window height
    #[default = 600.0]
    pub height: f32,
    /// Whether or not to maximize the window
    #[default = false]
    pub maximized: bool,
    /// Fullscreen type
    #[default(FullscreenType::Windowed)]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to show window decorations
    #[default = false]
    pub borderless: bool,
    /// Minimum width for resizable windows; 0 means no limit
    #[default = 0.0]
    pub min_width: f32,
    /// Minimum height for resizable windows; 0 means no limit
    #[default = 0.0]
    pub min_height: f32,
    /// Maximum width for resizable windows; 0 means no limit
    #[default = 0.0]
    pub max_width: f32,
    /// Maximum height for resizable windows; 0 means no limit
    #[default = 0.0]
    pub max_height: f32,
    /// Whether or not the window is resizable
    #[default = false]
    pub resizable: bool,
    /// Whether this window should displayed (true) or hidden (false)
    #[default = true]
    pub visible: bool,
}

impl WindowMode {
    /// Set default window size, or screen resolution in true fullscreen mode.
    pub fn dimensions(mut self, width: f32, height: f32) -> Self {
        self.width = width;
        self.height = height;
        self
    }

    /// Set whether the window should be maximized.
    pub fn maximized(mut self, maximized: bool) -> Self {
        self.maximized = maximized;
        self
    }

    /// Set the fullscreen type.
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set whether a window should be borderless in windowed mode.
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set minimum window dimensions for windowed mode.
    pub fn min_dimensions(mut self, width: f32, height: f32) -> Self {
        self.min_width = width;
        self.min_height = height;
        self
    }

    /// Set maximum window dimensions for windowed mode.
    pub fn max_dimensions(mut self, width: f32, height: f32) -> Self {
        self.max_width = width;
        self.max_height = height;
        self
    }

    /// Set resizable.
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set visibility
    pub fn visible(mut self, visible: bool) -> Self {
        self.visible = visible;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// WindowSetup {
///     title: "An easy, good game".to_owned(),
///     samples: NumSamples::Zero,
///     vsync: true,
///     icon: "".to_owned(),
///     srgb: true,
/// }
/// # , WindowSetup::default()); }
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq)]
pub struct WindowSetup {
    /// The window title.
    #[default(String::from("An easy, good game"))]
    pub title: String,
    /// Number of samples to use for multisample anti-aliasing.
    #[default(NumSamples::One)]
    pub samples: NumSamples,
    /// Whether or not to enable vsync.
    #[default = true]
    pub vsync: bool,
    /// A file path to the window's icon.
    /// It takes a path rooted in the `resources` directory (see the [`filesystem`](../filesystem/index.html)
    /// module for details), and an empty string results in a blank/default icon.
    #[default(String::new())]
    pub icon: String,
    /// Whether or not to enable sRGB (gamma corrected color)
    /// handling on the display.
    #[default = true]
    pub srgb: bool,
}

impl WindowSetup {
    /// Set window title.
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set number of samples to use for multisample anti-aliasing.
    pub fn samples(mut self, samples: NumSamples) -> Self {
        self.samples = samples;
        self
    }

    /// Set whether vsync is enabled.
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set sRGB color mode.
    pub fn srgb(mut self, active: bool) -> Self {
        self.srgb = active;
        self
    }
}

/// Possible backends.
/// Currently, only OpenGL and OpenGL ES Core specs are supported,
/// but this lets you specify which to use as well as the version numbers.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// Backend::OpenGL {
///     major: 3,
///     minor: 2,
/// }
/// # , Backend::default()); }
/// ```
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't).
    #[default]
    #[allow(clippy::upper_case_acronyms)]
    OpenGL {
        /// OpenGL major version
        #[default = 3]
        major: u8,
        /// OpenGL minor version
        #[default = 2]
        minor: u8,
    },
    /// OpenGL ES, defaults to 3.0.  Used for phones and other mobile
    /// devices.  Using something older
    /// than 3.0 starts to running into sticky limitations, particularly
    /// with instanced drawing (used for `SpriteBatch`), but might be
    /// possible.
    #[allow(clippy::upper_case_acronyms)]
    OpenGLES {
        /// OpenGL ES major version
        #[default = 3]
        major: u8,
        /// OpenGL ES minor version
        #[default = 0]
        minor: u8,
    },
}

impl Backend {
    /// Set requested OpenGL/OpenGL ES version.
    pub fn version(self, new_major: u8, new_minor: u8) -> Self {
        match self {
            Backend::OpenGL { .. } => Backend::OpenGL {
                major: new_major,
                minor: new_minor,
            },
            Backend::OpenGLES { .. } => Backend::OpenGLES {
                major: new_major,
                minor: new_minor,
            },
        }
    }

    /// Use OpenGL
    pub fn gl(self) -> Self {
        match self {
            Backend::OpenGLES { major, minor } => Backend::OpenGL { major, minor },
            gl => gl,
        }
    }

    /// Use OpenGL ES
    pub fn gles(self) -> Self {
        match self {
            Backend::OpenGL { major, minor } => Backend::OpenGLES { major, minor },
            es => es,
        }
    }
}

/// The possible number of samples for multisample anti-aliasing.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl TryFrom<u8> for NumSamples {
    type Error = GameError;
    fn try_from(i: u8) -> Result<Self, Self::Error> {
        match i {
            1 => Ok(NumSamples::One),
            2 => Ok(NumSamples::Two),
            4 => Ok(NumSamples::Four),
            8 => Ok(NumSamples::Eight),
            16 => Ok(NumSamples::Sixteen),
            _ => Err(GameError::ConfigError(String::from(
                "Invalid number of samples",
            ))),
        }
    }
}

impl From<NumSamples> for u8 {
    fn from(ns: NumSamples) -> u8 {
        ns as u8
    }
}

/// Defines which submodules to enable in ggez.
/// If one tries to use a submodule that is not enabled,
/// it will panic.  Currently, not all subsystems can be
/// disabled.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// ModuleConf {
///     gamepad: true,
///     audio: true,
/// }
/// # , ModuleConf::default()); }
/// ```
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, SmartDefault)]
pub struct ModuleConf {
    /// The gamepad input module.
    #[default = true]
    pub gamepad: bool,

    /// The audio module.
    #[default = true]
    pub audio: bool,
}

impl ModuleConf {
    /// Sets whether or not to enable the gamepad input module.
    pub fn gamepad(mut self, gamepad: bool) -> Self {
        self.gamepad = gamepad;
        self
    }

    /// Sets whether or not to enable the audio module.
    pub fn audio(mut self, audio: bool) -> Self {
        self.audio = audio;
        self
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust
/// # use ggez::conf::*;
/// # fn main() { assert_eq!(
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::default(),
///     modules: ModuleConf::default(),
/// }
/// # , Conf::default()); }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault, Clone)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Graphics backend configuration
    pub backend: Backend,
    /// Which modules to enable.
    pub modules: ModuleConf,
}

impl Conf {
    /// Same as `Conf::default()`
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        let _ = file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }

    /// Sets the window mode
    pub fn window_mode(mut self, window_mode: WindowMode) -> Self {
        self.window_mode = window_mode;
        self
    }

    /// Sets the backend
    pub fn backend(mut self, backend: Backend) -> Self {
        self.backend = backend;
        self
    }

    /// Sets the backend
    pub fn modules(mut self, modules: ModuleConf) -> Self {
        self.modules = modules;
        self
    }
}

#[cfg(test)]
mod tests {
    use crate::conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn headless_encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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.

/*! Solver configuration, contains backend solver specific info. */

use std::fmt ;

use common::UnexSmtRes ;

use self::SolverStyle::* ;

/** A configuration item is either a keyword or unsupported. */
pub type ConfItem = Result<& 'static str, UnexSmtRes> ;

/** Value of an unsupported configuration item. */
#[inline(always)]
fn unsupported() -> ConfItem { Err(UnexSmtRes::Unsupported) }
/** Keyword for a configuration item. */
#[inline(always)]
fn supported(keyword: & 'static str) -> ConfItem { Ok(keyword) }

/** Solver styles. */
#[derive(Debug, Clone)]
pub enum SolverStyle {
  /** Z3-style smt solver. */
  Z3,
  /** CVC4-style smt solver. */
  CVC4,
}

impl SolverStyle {
  /** Default configuration for a solver style. */
  pub fn default(self) -> SolverConf {
    let cmd = self.cmd() ;
    match self {
      Z3 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "-in", "-smt2"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: supported("check-sat"),
      },
      CVC4 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "--smtlib-strict", "-qqqqq", "--interactive"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: unsupported(),
      },
    }
  }
  /** Default command for a solver style. */
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3".to_string(), CVC4 => "cvc4".to_string(),
    }
  }
}

impl fmt::Display for SolverStyle {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    match * self {
      Z3 => write!(fmt, "z3"),
      CVC4 => write!(fmt, "cvc4"),
    }
  }
}

/** Configuration and solver specific info. */
pub struct SolverConf {
  /** Solver style. */
  style: SolverStyle,
  /** Solver command. */
  cmd: String,
  /** Options to call the solver with. */
  options: Vec<& 'static str>,
  /** Parse success. */
  parse_success: bool,
  /** Triggers unsat-core production. */
  unsat_cores: bool,
  /** Keyword for check-sat with assumptions. */
  check_sat_assuming: ConfItem,
}

impl SolverConf {
  /** Creates a new z3-like solver configuration. */
  #[inline(always)]
  pub fn z3() -> Self { Z3.default() }

  /** Creates a new CVC4-like solver configuration. */
  #[inline(always)]
  pub fn cvc4() -> Self { CVC4.default() }

  /** Solver style. */
  #[inline(always)]
  pub fn style(& self) -> & SolverStyle { & self.style }

  /** Solver command. */
  #[inline(always)]
  pub fn get_cmd(& self) -> & str { & self.cmd }

  /** Options of the configuration. */
  #[inline(always)]
  pub fn get_options(& self) -> & [& 'static str] { & self.options }

  /** Indicates if parse success is active. */
  #[inline(always)]
  pub fn get_parse_success(& self) -> bool { self.parse_success }

  /** Keyword for check-sat with assumptions. */
  #[inline(always)]
  pub fn get_check_sat_assuming(& self) -> & ConfItem {
    & self.check_sat_assuming
  }

  /** Adds an option to the configuration. */
  #[inline(always)]
  pub fn option(mut self, o: & 'static str) -> Self {
    self.options.push(o) ;
    self
  }

  /** Sets the command for the solver. */
  #[inline(always)]
  pub fn cmd(mut self, cmd: String) -> Self {
    self.cmd = cmd ;
    self
  }

  /** Activates parse sucess. */
  #[inline(always)]
  #[cfg(not(no_parse_success))]
  pub fn print_success(mut self) -> Self {
    self.parse_success = true ;
    self
  }

  /** Activates unsat-core production. */
  #[inline(always)]
  pub fn unsat_cores(mut self) -> Self {
    self.unsat_cores = true ;
    self
  }

  // /** Creates a solver instance. */
  // #[inline(always)]
  // pub fn mk<Parser>(
  //   self, cmd: Command, parser: Parser
  // ) -> io::Result<Solver<Parser>> {
  //   Solver::mk(cmd, self, parser)
  // }
}<commit_msg>Helper function on solver style.<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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.

/*! Solver configuration, contains backend solver specific info. */

use std::fmt ;

use common::UnexSmtRes ;

use self::SolverStyle::* ;

/** A configuration item is either a keyword or unsupported. */
pub type ConfItem = Result<& 'static str, UnexSmtRes> ;

/** Value of an unsupported configuration item. */
#[inline(always)]
fn unsupported() -> ConfItem { Err(UnexSmtRes::Unsupported) }
/** Keyword for a configuration item. */
#[inline(always)]
fn supported(keyword: & 'static str) -> ConfItem { Ok(keyword) }

/** Solver styles. */
#[derive(Debug, Clone)]
pub enum SolverStyle {
  /** Z3-style smt solver. */
  Z3,
  /** CVC4-style smt solver. */
  CVC4,
}

impl SolverStyle {
  /** Default configuration for a solver style. */
  pub fn default(self) -> SolverConf {
    let cmd = self.cmd() ;
    match self {
      Z3 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "-in", "-smt2"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: supported("check-sat"),
      },
      CVC4 => SolverConf {
        style: self,
        cmd: cmd,
        options: vec![
          "--smtlib-strict", "-qqqqq", "--interactive"
        ],
        parse_success: false,
        unsat_cores: false,
        check_sat_assuming: unsupported(),
      },
    }
  }
  /** A solver style from a string. */
  pub fn of_str(s: & str) -> Option<SolverStyle> {
    match s {
      "z3" | "Z3" => Some(Z3),
      "cvc4" | "CVC4" => Some(CVC4),
      _ => None,
    }
  }
  /** Legal string representations of solver styles. */
  pub fn str_keys() -> Vec<& 'static str> {
    vec![ "z3", "Z3", "cvc4", "CVC4" ]
  }
  /** Default command for a solver style. */
  pub fn cmd(& self) -> String {
    match * self {
      Z3 => "z3".to_string(), CVC4 => "cvc4".to_string(),
    }
  }
}

impl fmt::Display for SolverStyle {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    match * self {
      Z3 => write!(fmt, "z3"),
      CVC4 => write!(fmt, "cvc4"),
    }
  }
}

/** Configuration and solver specific info. */
pub struct SolverConf {
  /** Solver style. */
  style: SolverStyle,
  /** Solver command. */
  cmd: String,
  /** Options to call the solver with. */
  options: Vec<& 'static str>,
  /** Parse success. */
  parse_success: bool,
  /** Triggers unsat-core production. */
  unsat_cores: bool,
  /** Keyword for check-sat with assumptions. */
  check_sat_assuming: ConfItem,
}

impl SolverConf {
  /** Creates a new z3-like solver configuration. */
  #[inline(always)]
  pub fn z3() -> Self { Z3.default() }

  /** Creates a new CVC4-like solver configuration. */
  #[inline(always)]
  pub fn cvc4() -> Self { CVC4.default() }

  /** Solver style. */
  #[inline(always)]
  pub fn style(& self) -> & SolverStyle { & self.style }

  /** Solver command. */
  #[inline(always)]
  pub fn get_cmd(& self) -> & str { & self.cmd }

  /** Options of the configuration. */
  #[inline(always)]
  pub fn get_options(& self) -> & [& 'static str] { & self.options }

  /** Indicates if parse success is active. */
  #[inline(always)]
  pub fn get_parse_success(& self) -> bool { self.parse_success }

  /** Keyword for check-sat with assumptions. */
  #[inline(always)]
  pub fn get_check_sat_assuming(& self) -> & ConfItem {
    & self.check_sat_assuming
  }

  /** Adds an option to the configuration. */
  #[inline(always)]
  pub fn option(mut self, o: & 'static str) -> Self {
    self.options.push(o) ;
    self
  }

  /** Sets the command for the solver. */
  #[inline(always)]
  pub fn cmd(mut self, cmd: String) -> Self {
    self.cmd = cmd ;
    self
  }

  /** Activates parse sucess. */
  #[inline(always)]
  #[cfg(not(no_parse_success))]
  pub fn print_success(mut self) -> Self {
    self.parse_success = true ;
    self
  }

  /** Activates unsat-core production. */
  #[inline(always)]
  pub fn unsat_cores(mut self) -> Self {
    self.unsat_cores = true ;
    self
  }

  // /** Creates a solver instance. */
  // #[inline(always)]
  // pub fn mk<Parser>(
  //   self, cmd: Command, parser: Parser
  // ) -> io::Result<Solver<Parser>> {
  //   Solver::mk(cmd, self, parser)
  // }
}<|endoftext|>