<commit_before>use std::thread;
use std::sync::mpsc::{self, sync_channel};
use std::io::{Write, ErrorKind};

use mio::*;
use mio::tcp::{TcpStream, Shutdown};

use ladspa::{PluginDescriptor, Plugin, PortConnection, Data};
use ladspa::{Port, PortDescriptor};
use ladspa::{PROP_NONE, HINT_INTEGER, DefaultValue};

use super::BASE_PORT;
use super::packet::{BUFFER_SIZE, BYTE_BUFFER_SIZE, Packet};

const CLIENT: Token = Token(1);

pub struct Transmitter {
    channel: u16,
    data_tx: Option<mpsc::SyncSender<Packet>>,
    notify_tx: Option<Sender<<PacketTransmitter as Handler>::Message>>,
    lbuffer: Vec<Data>,
    rbuffer: Vec<Data>,
    time: u64,
}

impl Transmitter {
    pub fn new(_: &PluginDescriptor, _: u64) -> Box<Plugin + Send> {
        Box::new(Transmitter {
            channel: 0,
            data_tx: None,
            notify_tx: None,
            lbuffer: Vec::new(),
            rbuffer: Vec::new(),
            time: 0,
        })
    }

    pub fn get_descriptor() -> PluginDescriptor {
        PluginDescriptor {
            unique_id: 5877,
            label: "feedback_tx",
            properties: PROP_NONE,
            name: "Feedback Transmitter",
            maker: "Noah Weninger",
            copyright: "None",
            ports: vec![Port {
                            name: "Left Audio In",
                            desc: PortDescriptor::AudioInput,
                            ..Default::default()
                        },
                        Port {
                            name: "Right Audio In",
                            desc: PortDescriptor::AudioInput,
                            ..Default::default()
                        },
                        Port {
                            name: "Left Audio Out",
                            desc: PortDescriptor::AudioOutput,
                            ..Default::default()
                        },
                        Port {
                            name: "Right Audio Out",
                            desc: PortDescriptor::AudioOutput,
                            ..Default::default()
                        },
                        Port {
                            name: "Channel",
                            desc: PortDescriptor::ControlInput,
                            hint: Some(HINT_INTEGER),
                            default: Some(DefaultValue::Value0),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(255_f32),
                        },
                        Port {
                            name: "Dry",
                            desc: PortDescriptor::ControlInput,
                            hint: None,
                            default: Some(DefaultValue::Value1),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(1_f32),
                        },
                        Port {
                            name: "Send",
                            desc: PortDescriptor::ControlInput,
                            hint: None,
                            default: Some(DefaultValue::Value1),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(1_f32),
                        }],
            new: Transmitter::new,
        }
    }

    fn init_client(&mut self) {
        let (data_tx, data_rx) = sync_channel(16);
        self.data_tx = Some(data_tx);

        let channel = self.channel;
        let mut event_loop = EventLoop::new().unwrap();
        self.notify_tx = Some(event_loop.channel());
        thread::spawn(move || {
            let addr = format!("127.0.0.1:{}", BASE_PORT + channel).parse().unwrap();
            let client = TcpStream::connect(&addr).unwrap();
            client.set_nodelay(true).unwrap();
            event_loop.register(&client, CLIENT).unwrap();
            event_loop.run(&mut PacketTransmitter {
                          socket: client,
                          data_rx: data_rx,
                      })
                      .unwrap();
        });
    }

    fn kill_client(&mut self) {
        let _ = self.notify_tx.as_ref().unwrap().send(());
    }
}

impl Plugin for Transmitter {
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]) {
        let inputl = ports[0].unwrap_audio();
        let inputr = ports[1].unwrap_audio();
        let mut outputl = ports[2].unwrap_audio_mut();
        let mut outputr = ports[3].unwrap_audio_mut();

        let channel = *ports[4].unwrap_control() as u16;
        let dry = ports[5].unwrap_control();
        let wet = ports[6].unwrap_control();

        if channel != self.channel {
            self.channel = channel;
            println!("set channel {}", self.channel);
            self.kill_client();
            self.init_client();
            return;
        }

        let mut need_reboot = false;
        let mut i = 0;
        while i < sample_count {
            while self.lbuffer.len() < BUFFER_SIZE && i < sample_count {
                self.lbuffer.push(inputl[i]*(*wet));
                self.rbuffer.push(inputr[i]*(*wet));

                outputl[i] = inputl[i]*(*dry);
                outputr[i] = inputr[i]*(*dry);

                i += 1;
            }

            if self.lbuffer.len() == BUFFER_SIZE {
                let packet = Packet::new(&self.lbuffer, &self.rbuffer, self.time);
                self.time += BUFFER_SIZE as u64;

                need_reboot |= self.data_tx.as_ref().unwrap().send(packet).is_err();

                self.lbuffer.clear();
                self.rbuffer.clear();
            }
        }
        if need_reboot {
            println!("transmit failed, rebooting");
            self.kill_client();
            self.init_client();
        }
    }

    fn activate(&mut self) {
        println!("activate {}", self.channel);
        self.lbuffer.clear();
        self.rbuffer.clear();
        self.time = 0;
        self.init_client();
    }

    fn deactivate(&mut self) {
        println!("deactivate {}", self.channel);
        self.kill_client();
    }
}

struct PacketTransmitter {
    socket: TcpStream,
    data_rx: mpsc::Receiver<Packet>,
}

impl Handler for PacketTransmitter {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            CLIENT => {
                println!("client accept");
                'outer: loop {
                    assert!(events.is_writable());
                    let packet = match self.data_rx.recv() {
                        Ok(p) => p,
                        Err(_) => {
                            println!("err recieving packet from ladspa, channel is dead!");
                            event_loop.shutdown();
                            break;
                        }
                    };
                    let mut write_offset = 0;
                    loop {
                        match self.socket.write(&packet.as_bytes()[write_offset..]) {
                            Ok(num_written) => {
                                //println!("client wrote {}", num_written);
                                write_offset += num_written;
                                assert!(write_offset <= BYTE_BUFFER_SIZE);
                                if write_offset == BYTE_BUFFER_SIZE {
                                    break;
                                }
                                if num_written == 0 {
                                    println!("wrote zero bytes");
                                    event_loop.shutdown();
                                    break 'outer;
                                }
                            }
                            Err(e) => {
                                if e.kind() == ErrorKind::WouldBlock {
                                    continue;
                                }
                                println!("error writing to socket: {}", e);
                                event_loop.shutdown();
                                break 'outer;
                            }
                        }
                    }
                }
            }
            _ => panic!("Received unknown token"),
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, _: Self::Message) {
        let _ = self.socket.shutdown(Shutdown::Both);
        event_loop.shutdown();
    }
}
<commit_msg>factor<commit_after>use std::thread;
use std::sync::mpsc::{self, sync_channel};
use std::io::{Write, ErrorKind};

use mio::*;
use mio::tcp::{TcpStream, Shutdown};

use ladspa::{PluginDescriptor, Plugin, PortConnection, Data};
use ladspa::{Port, PortDescriptor};
use ladspa::{PROP_NONE, HINT_INTEGER, DefaultValue};

use super::BASE_PORT;
use super::packet::{BUFFER_SIZE, BYTE_BUFFER_SIZE, Packet};

const CLIENT: Token = Token(1);

pub struct Transmitter {
    channel: u16,
    data_tx: Option<mpsc::SyncSender<Packet>>,
    notify_tx: Option<Sender<<PacketTransmitter as Handler>::Message>>,
    lbuffer: Vec<Data>,
    rbuffer: Vec<Data>,
    time: u64,
}

impl Transmitter {
    pub fn new(_: &PluginDescriptor, _: u64) -> Box<Plugin + Send> {
        Box::new(Transmitter {
            channel: 0,
            data_tx: None,
            notify_tx: None,
            lbuffer: Vec::new(),
            rbuffer: Vec::new(),
            time: 0,
        })
    }

    pub fn get_descriptor() -> PluginDescriptor {
        PluginDescriptor {
            unique_id: 5877,
            label: "feedback_tx",
            properties: PROP_NONE,
            name: "Feedback Transmitter",
            maker: "Noah Weninger",
            copyright: "None",
            ports: vec![Port {
                            name: "Left Audio In",
                            desc: PortDescriptor::AudioInput,
                            ..Default::default()
                        },
                        Port {
                            name: "Right Audio In",
                            desc: PortDescriptor::AudioInput,
                            ..Default::default()
                        },
                        Port {
                            name: "Left Audio Out",
                            desc: PortDescriptor::AudioOutput,
                            ..Default::default()
                        },
                        Port {
                            name: "Right Audio Out",
                            desc: PortDescriptor::AudioOutput,
                            ..Default::default()
                        },
                        Port {
                            name: "Channel",
                            desc: PortDescriptor::ControlInput,
                            hint: Some(HINT_INTEGER),
                            default: Some(DefaultValue::Value0),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(255_f32),
                        },
                        Port {
                            name: "Dry",
                            desc: PortDescriptor::ControlInput,
                            hint: None,
                            default: Some(DefaultValue::Value1),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(1_f32),
                        },
                        Port {
                            name: "Send",
                            desc: PortDescriptor::ControlInput,
                            hint: None,
                            default: Some(DefaultValue::Value1),
                            lower_bound: Some(0_f32),
                            upper_bound: Some(1_f32),
                        }],
            new: Transmitter::new,
        }
    }

    fn init_client(&mut self) {
        let (data_tx, data_rx) = sync_channel(16);
        self.data_tx = Some(data_tx);

        let channel = self.channel;
        let mut event_loop = EventLoop::new().unwrap();
        self.notify_tx = Some(event_loop.channel());
        thread::spawn(move || {
            let addr = format!("127.0.0.1:{}", BASE_PORT + channel).parse().unwrap();
            let client = TcpStream::connect(&addr).unwrap();
            client.set_nodelay(true).unwrap();
            event_loop.register(&client, CLIENT).unwrap();
            event_loop.run(&mut PacketTransmitter {
                          socket: client,
                          data_rx: data_rx,
                      })
                      .unwrap();
        });
    }

    fn kill_client(&mut self) {
        let _ = self.notify_tx.as_ref().unwrap().send(());
    }

    fn restart_client(&mut self) {
        self.kill_client();
        self.init_client();
    }

    fn set_channel(&mut self, channel: u16) {
        if channel != self.channel {
            self.channel = channel;
            println!("set channel {}", self.channel);
            self.restart_client();
            return;
        }
    }
}

impl Plugin for Transmitter {
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]) {
        let inputl = ports[0].unwrap_audio();
        let inputr = ports[1].unwrap_audio();
        let mut outputl = ports[2].unwrap_audio_mut();
        let mut outputr = ports[3].unwrap_audio_mut();

        let channel = *ports[4].unwrap_control() as u16;
        let dry = ports[5].unwrap_control();
        let wet = ports[6].unwrap_control();

        self.set_channel(channel);

        let mut need_reboot = false;
        let mut i = 0;
        while i < sample_count {
            while self.lbuffer.len() < BUFFER_SIZE && i < sample_count {
                self.lbuffer.push(inputl[i]*(*wet));
                self.rbuffer.push(inputr[i]*(*wet));

                outputl[i] = inputl[i]*(*dry);
                outputr[i] = inputr[i]*(*dry);

                i += 1;
            }

            if self.lbuffer.len() == BUFFER_SIZE {
                let packet = Packet::new(&self.lbuffer, &self.rbuffer, self.time);
                self.time += BUFFER_SIZE as u64;

                need_reboot |= self.data_tx.as_ref().unwrap().send(packet).is_err();

                self.lbuffer.clear();
                self.rbuffer.clear();
            }
        }
        if need_reboot {
            println!("transmit failed, rebooting");
            self.restart_client();
        }
    }

    fn activate(&mut self) {
        println!("activate {}", self.channel);
        self.lbuffer.clear();
        self.rbuffer.clear();
        self.time = 0;
        self.init_client();
    }

    fn deactivate(&mut self) {
        println!("deactivate {}", self.channel);
        self.kill_client();
    }
}

struct PacketTransmitter {
    socket: TcpStream,
    data_rx: mpsc::Receiver<Packet>,
}

impl Handler for PacketTransmitter {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            CLIENT => {
                println!("client accept");
                'outer: loop {
                    assert!(events.is_writable());
                    let packet = match self.data_rx.recv() {
                        Ok(p) => p,
                        Err(_) => {
                            println!("err recieving packet from ladspa, channel is dead!");
                            event_loop.shutdown();
                            break;
                        }
                    };
                    let mut write_offset = 0;
                    loop {
                        match self.socket.write(&packet.as_bytes()[write_offset..]) {
                            Ok(num_written) => {
                                //println!("client wrote {}", num_written);
                                write_offset += num_written;
                                assert!(write_offset <= BYTE_BUFFER_SIZE);
                                if write_offset == BYTE_BUFFER_SIZE {
                                    break;
                                }
                                if num_written == 0 {
                                    println!("wrote zero bytes");
                                    event_loop.shutdown();
                                    break 'outer;
                                }
                            }
                            Err(e) => {
                                if e.kind() == ErrorKind::WouldBlock {
                                    continue;
                                }
                                println!("error writing to socket: {}", e);
                                event_loop.shutdown();
                                break 'outer;
                            }
                        }
                    }
                }
            }
            _ => panic!("Received unknown token"),
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, _: Self::Message) {
        let _ = self.socket.shutdown(Shutdown::Both);
        event_loop.shutdown();
    }
}
<|endoftext|>


<commit_before>//! Tests specific definitions
use std::io::{self, Sink, Write};
use std::iter::IntoIterator;
use std::slice::Iter;
use std::vec::IntoIter;

#[cfg(windows)]
use winapi;

use Result;
use config::Config;
use consts::KeyPress;
use error::ReadlineError;
use line_buffer::LineBuffer;
use super::{Position, RawMode, RawReader, Renderer, Term};

pub type Mode = ();

impl RawMode for Mode {
    fn disable_raw_mode(&self) -> Result<()> {
        Ok(())
    }
}

impl<'a> RawReader for Iter<'a, KeyPress> {
    fn next_key(&mut self) -> Result<KeyPress> {
        match self.next() {
            Some(key) => Ok(*key),
            None => Err(ReadlineError::Eof),
        }
    }
    #[cfg(unix)]
    fn next_char(&mut self) -> Result<char> {
        unimplemented!();
    }
}

impl RawReader for IntoIter<KeyPress> {
    fn next_key(&mut self) -> Result<KeyPress> {
        match self.next() {
            Some(key) => Ok(key),
            None => Err(ReadlineError::Eof),
        }
    }
    #[cfg(unix)]
    fn next_char(&mut self) -> Result<char> {
        unimplemented!();
    }
}

impl Renderer for Sink {
    fn move_cursor(&mut self, _: Position, _: Position) -> Result<()> {
        Ok(())
    }

    fn refresh_line(&mut self,
                    prompt: &str,
                    prompt_size: Position,
                    line: &LineBuffer,
                    _: usize,
                    _: usize)
                    -> Result<(Position, Position)> {
        try!(self.write_all(prompt.as_bytes()));
        try!(self.write_all(line.as_bytes()));
        Ok((prompt_size, prompt_size))
    }

    /// Characters with 2 column width are correctly handled (not splitted).
    fn calculate_position(&self, _: &str, orig: Position) -> Position {
        orig
    }

    fn write_and_flush(&mut self, buf: &[u8]) -> Result<()> {
        try!(self.write_all(buf));
        try!(self.flush());
        Ok(())
    }

    fn beep(&mut self) -> Result<()> {
        Ok(())
    }

    /// Clear the screen. Used to handle ctrl+l
    fn clear_screen(&mut self) -> Result<()> {
        Ok(())
    }

    /// Check if a SIGWINCH signal has been received
    fn sigwinch(&self) -> bool {
        false
    }
    fn update_size(&mut self) {}
    fn get_columns(&self) -> usize {
        80
    }
    fn get_rows(&self) -> usize {
        24
    }
}

pub type Terminal = DummyTerminal;

#[derive(Clone,Debug)]
pub struct DummyTerminal {
    pub keys: Vec<KeyPress>,
}

impl Term for DummyTerminal {
    type Reader = IntoIter<KeyPress>;
    type Writer = Sink;
    type Mode = Mode;

    fn new() -> DummyTerminal {
        DummyTerminal { keys: Vec::new() }
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    fn is_unsupported(&self) -> bool {
        false
    }

    /// check if stdin is connected to a terminal.
    fn is_stdin_tty(&self) -> bool {
        true
    }

    // Interactive loop:

    fn enable_raw_mode(&self) -> Result<Mode> {
        Ok(())
    }

    /// Create a RAW reader
    fn create_reader(&self, _: &Config) -> Result<IntoIter<KeyPress>> {
        Ok(self.keys.clone().into_iter())
    }

    fn create_writer(&self) -> Sink {
        io::sink()
    }
}

#[cfg(unix)]
pub fn suspend() -> Result<()> {
    Ok(())
}
<commit_msg>Fix warning on windows<commit_after>//! Tests specific definitions
use std::io::{self, Sink, Write};
use std::iter::IntoIterator;
use std::slice::Iter;
use std::vec::IntoIter;

use Result;
use config::Config;
use consts::KeyPress;
use error::ReadlineError;
use line_buffer::LineBuffer;
use super::{Position, RawMode, RawReader, Renderer, Term};

pub type Mode = ();

impl RawMode for Mode {
    fn disable_raw_mode(&self) -> Result<()> {
        Ok(())
    }
}

impl<'a> RawReader for Iter<'a, KeyPress> {
    fn next_key(&mut self) -> Result<KeyPress> {
        match self.next() {
            Some(key) => Ok(*key),
            None => Err(ReadlineError::Eof),
        }
    }
    #[cfg(unix)]
    fn next_char(&mut self) -> Result<char> {
        unimplemented!();
    }
}

impl RawReader for IntoIter<KeyPress> {
    fn next_key(&mut self) -> Result<KeyPress> {
        match self.next() {
            Some(key) => Ok(key),
            None => Err(ReadlineError::Eof),
        }
    }
    #[cfg(unix)]
    fn next_char(&mut self) -> Result<char> {
        unimplemented!();
    }
}

impl Renderer for Sink {
    fn move_cursor(&mut self, _: Position, _: Position) -> Result<()> {
        Ok(())
    }

    fn refresh_line(&mut self,
                    prompt: &str,
                    prompt_size: Position,
                    line: &LineBuffer,
                    _: usize,
                    _: usize)
                    -> Result<(Position, Position)> {
        try!(self.write_all(prompt.as_bytes()));
        try!(self.write_all(line.as_bytes()));
        Ok((prompt_size, prompt_size))
    }

    /// Characters with 2 column width are correctly handled (not splitted).
    fn calculate_position(&self, _: &str, orig: Position) -> Position {
        orig
    }

    fn write_and_flush(&mut self, buf: &[u8]) -> Result<()> {
        try!(self.write_all(buf));
        try!(self.flush());
        Ok(())
    }

    fn beep(&mut self) -> Result<()> {
        Ok(())
    }

    /// Clear the screen. Used to handle ctrl+l
    fn clear_screen(&mut self) -> Result<()> {
        Ok(())
    }

    /// Check if a SIGWINCH signal has been received
    fn sigwinch(&self) -> bool {
        false
    }
    fn update_size(&mut self) {}
    fn get_columns(&self) -> usize {
        80
    }
    fn get_rows(&self) -> usize {
        24
    }
}

pub type Terminal = DummyTerminal;

#[derive(Clone,Debug)]
pub struct DummyTerminal {
    pub keys: Vec<KeyPress>,
}

impl Term for DummyTerminal {
    type Reader = IntoIter<KeyPress>;
    type Writer = Sink;
    type Mode = Mode;

    fn new() -> DummyTerminal {
        DummyTerminal { keys: Vec::new() }
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    fn is_unsupported(&self) -> bool {
        false
    }

    /// check if stdin is connected to a terminal.
    fn is_stdin_tty(&self) -> bool {
        true
    }

    // Interactive loop:

    fn enable_raw_mode(&self) -> Result<Mode> {
        Ok(())
    }

    /// Create a RAW reader
    fn create_reader(&self, _: &Config) -> Result<IntoIter<KeyPress>> {
        Ok(self.keys.clone().into_iter())
    }

    fn create_writer(&self) -> Sink {
        io::sink()
    }
}

#[cfg(unix)]
pub fn suspend() -> Result<()> {
    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt::Write as fmt_Write;
use std::fmt;

use Message;
use reflect::ReflectFieldRef;
use reflect::ReflectValueRef;
use reflect::ReflectRepeatedRef;
use json::float;

struct Printer {
    buf: String,
}

trait JsonFloat : fmt::Display {
    fn is_nan(&self) -> bool;
    fn is_pos_infinity(&self) -> bool;
    fn is_neg_infinity(&self) -> bool;

    fn write_to_json(&self, w: &mut String) -> fmt::Result {
        if self.is_nan() {
            write!(w, "{}", float::PROTOBUF_JSON_NAN)
        } else if self.is_pos_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_INF)
        } else if self.is_neg_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_MINUS_INF)
        } else {
            write!(w, "{}", self)
        }
    }
}

impl JsonFloat for f32 {
    fn is_nan(&self) -> bool {
        self.is_nan()
    }

    fn is_pos_infinity(&self) -> bool {
        self.is_infinite() && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        self.is_infinite() && self < &0.0
    }
}

impl JsonFloat for f64 {
    fn is_nan(&self) -> bool {
        self.is_nan()
    }

    fn is_pos_infinity(&self) -> bool {
        self.is_infinite() && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        self.is_infinite() && self < &0.0
    }
}

impl Printer {
    fn print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result {
        if *first {
            *first = false;
            Ok(())
        } else {
            write!(self.buf, ", ")
        }
    }

    fn print_value(&mut self, value: &ReflectValueRef) -> fmt::Result {
        match value {
            ReflectValueRef::U32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::U64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::F32(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::F64(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::Bool(v) => write!(self.buf, "{}", v),
            ReflectValueRef::String(v) => unimplemented!(),
            ReflectValueRef::Bytes(v) => unimplemented!(),
            // TODO: option to output JSON as number
            ReflectValueRef::Enum(v) => write!(self.buf, "{}", v.name()),
            ReflectValueRef::Message(v) => self.print_message(*v),
        }
    }

    fn print_repeated(&mut self, repeated: ReflectRepeatedRef) -> fmt::Result {
        unimplemented!()
    }

    fn print_message(&mut self, message: &Message) -> fmt::Result {
        let descriptor = message.descriptor();

        write!(self.buf, "{{")?;

        let mut first = true;

        for field in descriptor.fields() {
            match field.get_reflect(message) {
                ReflectFieldRef::Optional(None) => {}
                ReflectFieldRef::Optional(Some(v)) => {
                    self.print_comma_but_first(&mut first)?;
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_value(&v)?;
                }
                ReflectFieldRef::Repeated(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                }
                ReflectFieldRef::Map(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                }
            }
            unimplemented!();
        }

        write!(self.buf, "}}")?;
        Ok(())
    }
}

pub fn print_to_string(message: &Message) -> String {
    let mut printer = Printer {
        buf: String::new()
    };
    printer.print_message(message).unwrap();
    printer.buf
}
<commit_msg>Fix recursion<commit_after>use std::fmt::Write as fmt_Write;
use std::fmt;

use Message;
use reflect::ReflectFieldRef;
use reflect::ReflectValueRef;
use reflect::ReflectRepeatedRef;
use json::float;
use std::f32;
use std::f64;

struct Printer {
    buf: String,
}

trait JsonFloat : fmt::Display {
    fn is_nan(&self) -> bool;
    fn is_pos_infinity(&self) -> bool;
    fn is_neg_infinity(&self) -> bool;

    fn write_to_json(&self, w: &mut String) -> fmt::Result {
        if self.is_nan() {
            write!(w, "{}", float::PROTOBUF_JSON_NAN)
        } else if self.is_pos_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_INF)
        } else if self.is_neg_infinity() {
            write!(w, "{}", float::PROTOBUF_JSON_MINUS_INF)
        } else {
            write!(w, "{}", self)
        }
    }
}

impl JsonFloat for f32 {
    fn is_nan(&self) -> bool {
        f32::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f32::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f32::is_infinite(*self) && self < &0.0
    }
}

impl JsonFloat for f64 {
    fn is_nan(&self) -> bool {
        f64::is_nan(*self)
    }

    fn is_pos_infinity(&self) -> bool {
        f64::is_infinite(*self) && self > &0.0
    }

    fn is_neg_infinity(&self) -> bool {
        f64::is_infinite(*self) && self < &0.0
    }
}

impl Printer {
    fn print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result {
        if *first {
            *first = false;
            Ok(())
        } else {
            write!(self.buf, ", ")
        }
    }

    fn print_value(&mut self, value: &ReflectValueRef) -> fmt::Result {
        match value {
            ReflectValueRef::U32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::U64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I32(v) => write!(self.buf, "{}", v),
            ReflectValueRef::I64(v) => write!(self.buf, "{}", v),
            ReflectValueRef::F32(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::F64(v) => v.write_to_json(&mut self.buf),
            ReflectValueRef::Bool(v) => write!(self.buf, "{}", v),
            ReflectValueRef::String(v) => unimplemented!(),
            ReflectValueRef::Bytes(v) => unimplemented!(),
            // TODO: option to output JSON as number
            ReflectValueRef::Enum(v) => write!(self.buf, "{}", v.name()),
            ReflectValueRef::Message(v) => self.print_message(*v),
        }
    }

    fn print_repeated(&mut self, repeated: ReflectRepeatedRef) -> fmt::Result {
        unimplemented!()
    }

    fn print_message(&mut self, message: &Message) -> fmt::Result {
        let descriptor = message.descriptor();

        write!(self.buf, "{{")?;

        let mut first = true;

        for field in descriptor.fields() {
            match field.get_reflect(message) {
                ReflectFieldRef::Optional(None) => {}
                ReflectFieldRef::Optional(Some(v)) => {
                    self.print_comma_but_first(&mut first)?;
                    write!(self.buf, "{}: ", field.json_name())?;
                    self.print_value(&v)?;
                }
                ReflectFieldRef::Repeated(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                }
                ReflectFieldRef::Map(v) => {
                    write!(self.buf, "{}: ", field.json_name())?;
                }
            }
            unimplemented!();
        }

        write!(self.buf, "}}")?;
        Ok(())
    }
}

pub fn print_to_string(message: &Message) -> String {
    let mut printer = Printer {
        buf: String::new()
    };
    printer.print_message(message).unwrap();
    printer.buf
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bitflags;

extern crate fsevent_sys as fsevent;
extern crate libc;

use fsevent::core_foundation as cf;
use fsevent::fsevent as fs;

use std::slice;
use std::mem::transmute;
use std::slice::from_raw_parts_mut;
use std::str::from_utf8;
use std::ffi::CStr;
use std::convert::AsRef;

use std::sync::mpsc::{Sender};

pub const NULL: cf::CFRef = cf::NULL;

pub struct FsEvent {
  paths: cf::CFMutableArrayRef,
  since_when: fs::FSEventStreamEventId,
  latency: cf::CFTimeInterval,
  flags: fs::FSEventStreamCreateFlags,
  sender: Sender<Event>,
}

#[derive(Debug)]
pub struct Event {
  pub event_id: u64,
  pub flag: StreamFlags,
  pub path: String,
}

pub type FsEventCallback = fn(Vec<Event>);

bitflags! {
  flags StreamFlags: u32 {
    const NONE = 0x00000000,
    const MUST_SCAN_SUBDIRS = 0x00000001,
    const USER_DROPPED = 0x00000002,
    const KERNEL_DROPPED = 0x00000004,
    const IDS_WRAPPED = 0x00000008,
    const HISTORY_DONE = 0x00000010,
    const ROOT_CHANGED = 0x00000020,
    const MOUNT = 0x00000040,
    const UNMOUNT = 0x00000080,
    const ITEM_CREATED = 0x00000100,
    const ITEM_REMOVED = 0x00000200,
    const INOTE_META_MOD = 0x00000400,
    const ITEM_RENAMED = 0x00000800,
    const ITEM_MODIFIED = 0x00001000,
    const FINDER_INFO_MOD = 0x00002000,
    const ITEM_CHANGE_OWNER = 0x00004000,
    const ITEM_XATTR_MOD = 0x00008000,
    const IS_FILE = 0x00010000,
    const IS_DIR = 0x00020000,
    const IS_SYMLIMK = 0x00040000,
  }
}

pub fn is_api_available() -> (bool, String) {
  let ma = cf::system_version_major();
  let mi = cf::system_version_minor();

  if ma == 10 && mi < 5 {
    return (false, "This version of OSX does not support the FSEvent library, cannot proceed".to_string());
  }
  return (true, "ok".to_string());
}

fn default_stream_context(info: *const FsEvent) -> fs::FSEventStreamContext {
  let ptr = info as *mut libc::c_void;
  let stream_context = fs::FSEventStreamContext{
    version: 0,
    info: ptr,
    retain: cf::NULL,
    copy_description: cf::NULL
  };

  stream_context
}

impl FsEvent {
  pub fn new(sender: Sender<Event>) -> FsEvent {
    let fsevent: FsEvent;

    unsafe {
      fsevent = FsEvent{
        paths: cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks),
        since_when: fs::kFSEventStreamEventIdSinceNow,
        latency: 0.1,
        flags: fs::kFSEventStreamCreateFlagFileEvents,
        sender: sender,
      };
    }
    fsevent
  }

  // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c
  pub fn append_path(&self,source: &str) {
    unsafe {
      let cf_path = cf::str_path_to_cfstring_ref(source);
      cf::CFArrayAppendValue(self.paths, cf_path);
      cf::CFRelease(cf_path);
    }
  }
  pub fn observe(&self) {
    let stream_context = default_stream_context(self);

    let cb = callback as *mut _;

    unsafe {
      let stream = fs::FSEventStreamCreate(cf::kCFAllocatorDefault,
       cb,
       &stream_context,
       self.paths,
       self.since_when,
       self.latency,
       self.flags);

      // fs::FSEventStreamShow(stream);

      fs::FSEventStreamScheduleWithRunLoop(stream,
        cf::CFRunLoopGetCurrent(),
        cf::kCFRunLoopDefaultMode);

      fs::FSEventStreamStart(stream);
      cf::CFRunLoopRun();

      fs::FSEventStreamFlushSync(stream);
      fs::FSEventStreamStop(stream);

    }
  }
}

#[allow(unused_variables)]
pub fn callback(
    stream_ref: fs::FSEventStreamRef,
    info: *mut libc::c_void,
    num_events: libc::size_t,      // size_t numEvents
    event_paths: *const *const libc::c_char, // void *eventPaths
    event_flags: *mut libc::c_void, // const FSEventStreamEventFlags eventFlags[]
    event_ids: *mut libc::c_void,  // const FSEventStreamEventId eventIds[]
  ) {
  let num = num_events as usize;
  let e_ptr = event_flags as *mut u32;
  let i_ptr = event_ids as *mut u64;
  let fs_event = info as *mut FsEvent;

  unsafe {
    let paths: &[*const libc::c_char] = std::mem::transmute(slice::from_raw_parts(event_paths, num));
    let flags = from_raw_parts_mut(e_ptr, num);
    let ids = from_raw_parts_mut(i_ptr, num);

    for p in (0..num) {
      let i = CStr::from_ptr(paths[p]).to_bytes();
      let flag: StreamFlags = StreamFlags::from_bits(flags[p] as u32)
      .expect(format!("Unable to decode StreamFlags: {}", flags[p] as u32).as_ref());

      let path = from_utf8(i).ok().expect("Invalid UTF8 string.");
      let event = Event{event_id: ids[p], flag: flag, path: path.to_string()};
      let _s = (*fs_event).sender.send(event);
    }
  }
}
<commit_msg>Display trait for the event<commit_after>#[macro_use] extern crate bitflags;

extern crate fsevent_sys as fsevent;
extern crate libc;

use fsevent::core_foundation as cf;
use fsevent::fsevent as fs;

use std::slice;
use std::mem::transmute;
use std::slice::from_raw_parts_mut;
use std::str::from_utf8;
use std::ffi::CStr;
use std::convert::AsRef;

use std::sync::mpsc::{Sender};

pub const NULL: cf::CFRef = cf::NULL;

pub struct FsEvent {
  paths: cf::CFMutableArrayRef,
  since_when: fs::FSEventStreamEventId,
  latency: cf::CFTimeInterval,
  flags: fs::FSEventStreamCreateFlags,
  sender: Sender<Event>,
}

#[derive(Debug)]
pub struct Event {
  pub event_id: u64,
  pub flag: StreamFlags,
  pub path: String,
}

pub type FsEventCallback = fn(Vec<Event>);

bitflags! {
  flags StreamFlags: u32 {
    const NONE = 0x00000000,
    const MUST_SCAN_SUBDIRS = 0x00000001,
    const USER_DROPPED = 0x00000002,
    const KERNEL_DROPPED = 0x00000004,
    const IDS_WRAPPED = 0x00000008,
    const HISTORY_DONE = 0x00000010,
    const ROOT_CHANGED = 0x00000020,
    const MOUNT = 0x00000040,
    const UNMOUNT = 0x00000080,
    const ITEM_CREATED = 0x00000100,
    const ITEM_REMOVED = 0x00000200,
    const INOTE_META_MOD = 0x00000400,
    const ITEM_RENAMED = 0x00000800,
    const ITEM_MODIFIED = 0x00001000,
    const FINDER_INFO_MOD = 0x00002000,
    const ITEM_CHANGE_OWNER = 0x00004000,
    const ITEM_XATTR_MOD = 0x00008000,
    const IS_FILE = 0x00010000,
    const IS_DIR = 0x00020000,
    const IS_SYMLIMK = 0x00040000,
  }
}

impl std::fmt::Display for StreamFlags {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    if self.contains(MUST_SCAN_SUBDIRS) {
      let _d = write!(f, "MUST_SCAN_SUBDIRS ");
    }
    if self.contains(USER_DROPPED) {
      let _d = write!(f, "USER_DROPPED ");
    }
    if self.contains(KERNEL_DROPPED) {
      let _d = write!(f, "KERNEL_DROPPED ");
    }
    if self.contains(IDS_WRAPPED) {
      let _d = write!(f, "IDS_WRAPPED ");
    }
    if self.contains(HISTORY_DONE) {
      let _d = write!(f, "HISTORY_DONE ");
    }
    if self.contains(ROOT_CHANGED) {
      let _d = write!(f, "ROOT_CHANGED ");
    }
    if self.contains(MOUNT) {
      let _d = write!(f, "MOUNT ");
    }
    if self.contains(UNMOUNT) {
      let _d = write!(f, "UNMOUNT ");
    }
    if self.contains(ITEM_CREATED) {
      let _d = write!(f, "ITEM_CREATED ");
    }
    if self.contains(ITEM_REMOVED) {
      let _d = write!(f, "ITEM_REMOVED ");
    }
    if self.contains(INOTE_META_MOD) {
      let _d = write!(f, "INOTE_META_MOD ");
    }
    if self.contains(ITEM_RENAMED) {
      let _d = write!(f, "ITEM_RENAMED ");
    }
    if self.contains(ITEM_MODIFIED) {
      let _d = write!(f, "ITEM_MODIFIED ");
    }
    if self.contains(FINDER_INFO_MOD) {
      let _d = write!(f, "FINDER_INFO_MOD ");
    }
    if self.contains(ITEM_CHANGE_OWNER) {
      let _d = write!(f, "ITEM_CHANGE_OWNER ");
    }
    if self.contains(ITEM_XATTR_MOD) {
      let _d = write!(f, "ITEM_XATTR_MOD ");
    }
    if self.contains(IS_FILE) {
      let _d = write!(f, "IS_FILE ");
    }
    if self.contains(IS_DIR) {
      let _d = write!(f, "IS_DIR ");
    }
    if self.contains(IS_SYMLIMK) {
      let _d = write!(f, "IS_SYMLIMK ");
    }
    write!(f, "")
  }
}

pub fn is_api_available() -> (bool, String) {
  let ma = cf::system_version_major();
  let mi = cf::system_version_minor();

  if ma == 10 && mi < 5 {
    return (false, "This version of OSX does not support the FSEvent library, cannot proceed".to_string());
  }
  return (true, "ok".to_string());
}

fn default_stream_context(info: *const FsEvent) -> fs::FSEventStreamContext {
  let ptr = info as *mut libc::c_void;
  let stream_context = fs::FSEventStreamContext{
    version: 0,
    info: ptr,
    retain: cf::NULL,
    copy_description: cf::NULL
  };

  stream_context
}

impl FsEvent {
  pub fn new(sender: Sender<Event>) -> FsEvent {
    let fsevent: FsEvent;

    unsafe {
      fsevent = FsEvent{
        paths: cf::CFArrayCreateMutable(cf::kCFAllocatorDefault, 0, &cf::kCFTypeArrayCallBacks),
        since_when: fs::kFSEventStreamEventIdSinceNow,
        latency: 0.0,
        flags: fs::kFSEventStreamCreateFlagFileEvents | fs::kFSEventStreamCreateFlagNoDefer,
        sender: sender,
      };
    }
    fsevent
  }

  // https://github.com/thibaudgg/rb-fsevent/blob/master/ext/fsevent_watch/main.c
  pub fn append_path(&self,source: &str) {
    unsafe {
      let cf_path = cf::str_path_to_cfstring_ref(source);
      cf::CFArrayAppendValue(self.paths, cf_path);
      cf::CFRelease(cf_path);
    }
  }
  pub fn observe(&self) {
    let stream_context = default_stream_context(self);

    let cb = callback as *mut _;

    unsafe {
      let stream = fs::FSEventStreamCreate(cf::kCFAllocatorDefault,
       cb,
       &stream_context,
       self.paths,
       self.since_when,
       self.latency,
       self.flags);

      // fs::FSEventStreamShow(stream);

      fs::FSEventStreamScheduleWithRunLoop(stream,
        cf::CFRunLoopGetCurrent(),
        cf::kCFRunLoopDefaultMode);

      fs::FSEventStreamStart(stream);
      cf::CFRunLoopRun();

      fs::FSEventStreamFlushSync(stream);
      fs::FSEventStreamStop(stream);

    }
  }
}

#[allow(unused_variables)]
pub fn callback(
    stream_ref: fs::FSEventStreamRef,
    info: *mut libc::c_void,
    num_events: libc::size_t,      // size_t numEvents
    event_paths: *const *const libc::c_char, // void *eventPaths
    event_flags: *mut libc::c_void, // const FSEventStreamEventFlags eventFlags[]
    event_ids: *mut libc::c_void,  // const FSEventStreamEventId eventIds[]
  ) {
  let num = num_events as usize;
  let e_ptr = event_flags as *mut u32;
  let i_ptr = event_ids as *mut u64;
  let fs_event = info as *mut FsEvent;

  unsafe {
    let paths: &[*const libc::c_char] = std::mem::transmute(slice::from_raw_parts(event_paths, num));
    let flags = from_raw_parts_mut(e_ptr, num);
    let ids = from_raw_parts_mut(i_ptr, num);

    for p in (0..num) {
      let i = CStr::from_ptr(paths[p]).to_bytes();
      let flag: StreamFlags = StreamFlags::from_bits(flags[p] as u32)
      .expect(format!("Unable to decode StreamFlags: {}", flags[p] as u32).as_ref());
      // println!("{}: {}", ids[p], flag);

      let path = from_utf8(i).ok().expect("Invalid UTF8 string.");
      let event = Event{event_id: ids[p], flag: flag, path: path.to_string()};
      let _s = (*fs_event).sender.send(event);
    }
  }
}
<|endoftext|>


<commit_before>use parking_lot::{Mutex, MutexGuard};
use std::sync::Arc;

#[derive(Clone, Default)]
pub(crate) struct ConsumerStatus(Arc<Mutex<ConsumerStatusInner>>);

impl ConsumerStatus {
    pub(crate) fn state(&self) -> ConsumerState {
        self.lock().state()
    }

    pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, ConsumerStatusInner>> {
        self.0.try_lock()
    }

    pub(crate) fn lock(&self) -> MutexGuard<'_, ConsumerStatusInner> {
        self.0.lock()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConsumerState {
    Active,
    ActiveWithDelegate,
    Canceled,
}

impl Default for ConsumerState {
    fn default() -> Self {
        Self::Active
    }
}

#[derive(Default)]
pub(crate) struct ConsumerStatusInner {
    state: ConsumerState,
}

impl ConsumerStatusInner {
    pub(crate) fn state(&self) -> ConsumerState {
        self.state
    }

    pub(crate) fn set_delegate(&mut self) {
        if self.state == ConsumerState::Active {
            self.state = ConsumerState::ActiveWithDelegate;
        }
    }

    pub(crate) fn cancel(&mut self) {
        self.state = ConsumerState::Canceled;
    }
}
<commit_msg>ConsumerStatus: make inner a tuple<commit_after>use parking_lot::{Mutex, MutexGuard};
use std::sync::Arc;

#[derive(Clone, Default)]
pub(crate) struct ConsumerStatus(Arc<Mutex<ConsumerStatusInner>>);

impl ConsumerStatus {
    pub(crate) fn state(&self) -> ConsumerState {
        self.lock().state()
    }

    pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, ConsumerStatusInner>> {
        self.0.try_lock()
    }

    pub(crate) fn lock(&self) -> MutexGuard<'_, ConsumerStatusInner> {
        self.0.lock()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConsumerState {
    Active,
    ActiveWithDelegate,
    Canceled,
}

impl Default for ConsumerState {
    fn default() -> Self {
        Self::Active
    }
}

#[derive(Default)]
pub(crate) struct ConsumerStatusInner(ConsumerState);

impl ConsumerStatusInner {
    pub(crate) fn state(&self) -> ConsumerState {
        self.0
    }

    pub(crate) fn set_delegate(&mut self) {
        if self.0 == ConsumerState::Active {
            self.0 = ConsumerState::ActiveWithDelegate;
        }
    }

    pub(crate) fn cancel(&mut self) {
        self.0 = ConsumerState::Canceled;
    }
}
<|endoftext|>


<commit_before>use uuid::Uuid;
use std::collections::BTreeMap;
use std::fmt::Write;
use std::rc::Rc;

use action::Action;
use Conditions;
use message::{Message};
use state::State;
use TimerEvent;
use context::base::BaseContext;
use context::event::EventHandler;
use dispatcher::request::{Request, InternalRequest};

#[derive(Debug)]
pub struct MapContext {
    base: BaseContext,
    map: BTreeMap<String, State>,
    format_buffer: String
}

impl MapContext {
    pub fn new(uuid: Uuid, conditions: Conditions) -> MapContext {
        MapContext {
            base: BaseContext::new(uuid, conditions),
            map: BTreeMap::new(),
            format_buffer: String::new()
        }
    }

    pub fn on_event(&mut self, event: InternalRequest) {
        if let Request::Message(event) = event {
            self.on_message(event);
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent) {
        for (_, mut state) in self.map.iter_mut() {
            self.base.on_timer(event, &mut state);

        }
        self.remove_closed_states();
    }

    pub fn actions_mut(&mut self) -> &mut Vec<Box<Action + 'static>> {
        self.base.actions_mut()
    }

    fn get_closed_state_ids(&self) -> Vec<String> {
        self.map.iter().filter_map(|(id, state)| {
            if !state.is_open() {
                Some(id.clone())
            } else {
                None
            }
        }).collect::<Vec<String>>()
    }

    fn remove_closed_states(&mut self) {
        for id in self.get_closed_state_ids() {
            let _ = self.map.remove(&id);
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        self.format_context_id(&event);
        self.update_state(event);
        self.format_buffer.clear();
        self.remove_closed_states();
    }

    fn update_state(&mut self, event: Rc<Message>) {
        let id = self.format_buffer.clone();
        let state = self.map.entry(id).or_insert(State::new());
        self.base.on_message(event, state);
    }

    pub fn is_open(&mut self) -> bool {
        !self.map.is_empty()
    }

    fn format_context_id(&mut self, message: &Message) {
        let empty = String::new();
        let _ = self.format_buffer.write_str(message.get("HOST").unwrap_or(&empty));
        let _ = self.format_buffer.write_str(":");
        let _ = self.format_buffer.write_str(message.get("PROGRAM").unwrap_or(&empty));
        let _ = self.format_buffer.write_str(":");
        let _ = self.format_buffer.write_str(message.get("PID").unwrap_or(&empty));
    }

    pub fn patterns(&self) -> &[String] {
        &self.base.conditions().patterns
    }
}

impl EventHandler<InternalRequest> for MapContext {
    fn handlers(&self) -> &[String] {
        self.patterns()
    }
    fn handle_event(&mut self, event: InternalRequest) {
        self.on_event(event);
    }
}

impl From<MapContext> for Box<EventHandler<InternalRequest>> {
    fn from(context: MapContext) -> Box<EventHandler<InternalRequest>> {
        Box::new(context)
    }
}
<commit_msg>MapContext: implement From<BaseContext><commit_after>use uuid::Uuid;
use std::collections::BTreeMap;
use std::fmt::Write;
use std::rc::Rc;

use action::Action;
use Conditions;
use message::{Message};
use state::State;
use TimerEvent;
use context::base::BaseContext;
use context::event::EventHandler;
use dispatcher::request::{Request, InternalRequest};

#[derive(Debug)]
pub struct MapContext {
    base: BaseContext,
    map: BTreeMap<String, State>,
    format_buffer: String
}

impl MapContext {
    pub fn new(uuid: Uuid, conditions: Conditions) -> MapContext {
        MapContext {
            base: BaseContext::new(uuid, conditions),
            map: BTreeMap::new(),
            format_buffer: String::new()
        }
    }

    pub fn on_event(&mut self, event: InternalRequest) {
        if let Request::Message(event) = event {
            self.on_message(event);
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent) {
        for (_, mut state) in self.map.iter_mut() {
            self.base.on_timer(event, &mut state);

        }
        self.remove_closed_states();
    }

    pub fn actions_mut(&mut self) -> &mut Vec<Box<Action + 'static>> {
        self.base.actions_mut()
    }

    fn get_closed_state_ids(&self) -> Vec<String> {
        self.map.iter().filter_map(|(id, state)| {
            if !state.is_open() {
                Some(id.clone())
            } else {
                None
            }
        }).collect::<Vec<String>>()
    }

    fn remove_closed_states(&mut self) {
        for id in self.get_closed_state_ids() {
            let _ = self.map.remove(&id);
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        self.format_context_id(&event);
        self.update_state(event);
        self.format_buffer.clear();
        self.remove_closed_states();
    }

    fn update_state(&mut self, event: Rc<Message>) {
        let id = self.format_buffer.clone();
        let state = self.map.entry(id).or_insert(State::new());
        self.base.on_message(event, state);
    }

    pub fn is_open(&mut self) -> bool {
        !self.map.is_empty()
    }

    fn format_context_id(&mut self, message: &Message) {
        let empty = String::new();
        let _ = self.format_buffer.write_str(message.get("HOST").unwrap_or(&empty));
        let _ = self.format_buffer.write_str(":");
        let _ = self.format_buffer.write_str(message.get("PROGRAM").unwrap_or(&empty));
        let _ = self.format_buffer.write_str(":");
        let _ = self.format_buffer.write_str(message.get("PID").unwrap_or(&empty));
    }

    pub fn patterns(&self) -> &[String] {
        &self.base.conditions().patterns
    }
}

impl From<BaseContext> for MapContext {
    fn from(context: BaseContext) -> MapContext {
        MapContext {
            base: context,
            map: BTreeMap::new(),
            format_buffer: String::new()
        }
    }
}

impl EventHandler<InternalRequest> for MapContext {
    fn handlers(&self) -> &[String] {
        self.patterns()
    }
    fn handle_event(&mut self, event: InternalRequest) {
        self.on_event(event);
    }
}

impl From<MapContext> for Box<EventHandler<InternalRequest>> {
    fn from(context: MapContext) -> Box<EventHandler<InternalRequest>> {
        Box::new(context)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2020, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use num_derive::*;

use crate::partition::BlockSize;
use crate::serialize::{Deserialize, Serialize};

use std::fmt;

// NOTE: Add Structures at the end.
/// Contains the speed settings.
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SpeedSettings {
  /// Enables inter-frames to have multiple reference frames.
  ///
  /// Enabled is slower.
  pub multiref: bool,
  /// Enables fast deblocking filter.
  pub fast_deblock: bool,
  /// Enables reduced transform set.
  ///
  /// Enabled is faster.
  pub reduced_tx_set: bool,
  /// Enables using transform-domain distortion instead of pixel-domain.
  ///
  /// Enabled is faster.
  pub tx_domain_distortion: bool,
  /// Enables using transform-domain rate estimation.
  ///
  /// Enabled is faster.
  pub tx_domain_rate: bool,
  /// Enables bottom-up encoding, rather than top-down.
  ///
  /// Enabled is slower.
  pub encode_bottomup: bool,
  /// Enables searching transform size and type with RDO.
  ///
  /// Enabled is slower.
  pub rdo_tx_decision: bool,
  /// Prediction modes to search.
  ///
  /// Complex settings are slower.
  pub prediction_modes: PredictionModesSetting,
  /// Enables searching near motion vectors during RDO.
  ///
  /// Enabled is slower.
  pub include_near_mvs: bool,
  /// Disables scene-cut detection.
  ///
  /// Enabled is faster.
  pub no_scene_detection: bool,
  /// Fast scene detection mode, uses simple SAD instead of encoder cost estimates.
  pub fast_scene_detection: bool,
  /// Enables CDEF.
  pub cdef: bool,
  /// Enables LRF.
  pub lrf: bool,
  /// The amount of search done for self guided restoration.
  pub sgr_complexity: SGRComplexityLevel,
  /// Use SATD instead of SAD for subpixel search.
  ///
  /// Enabled is slower.
  pub use_satd_subpel: bool,
  /// Use non-square partition type everywhere
  ///
  /// Enabled is slower.
  pub non_square_partition: bool,

  /// Search level for segmentation.
  ///
  /// Full search is at least twice as slow.
  pub segmentation: SegmentationLevel,

  /// Enable tx split for inter mode block.
  pub enable_inter_tx_split: bool,

  /// Use fine directional intra prediction
  pub fine_directional_intra: bool,

  // NOTE: put enums and basic type fields above
  /// Range of partition sizes that can be used. Larger ranges are slower.
  ///
  /// Must be based on square block sizes, so e.g. 8×4 isn't allowed here.
  pub partition_range: PartitionRange,
}

impl Default for SpeedSettings {
  /// This is currently used exclusively for feature testing and comparison.
  /// It is set to the slowest settings possible.
  fn default() -> Self {
    SpeedSettings {
      partition_range: PartitionRange::new(
        BlockSize::BLOCK_4X4,
        BlockSize::BLOCK_64X64,
      ),
      multiref: true,
      fast_deblock: false,
      reduced_tx_set: false,
      tx_domain_distortion: false,
      tx_domain_rate: false,
      encode_bottomup: true,
      rdo_tx_decision: true,
      prediction_modes: PredictionModesSetting::ComplexAll,
      include_near_mvs: true,
      no_scene_detection: false,
      fast_scene_detection: false,
      cdef: true,
      lrf: false,
      sgr_complexity: SGRComplexityLevel::Full,
      use_satd_subpel: true,
      non_square_partition: true,
      segmentation: SegmentationLevel::Full,
      enable_inter_tx_split: false,
      fine_directional_intra: false,
    }
  }
}

impl SpeedSettings {
  /// Set the speed setting according to a numeric speed preset.
  ///
  /// The speed settings vary depending on speed value from 0 to 10.
  /// - 10 (fastest): fixed block size 32x32, reduced TX set, fast deblock, fast scenechange detection.
  /// - 9: min block size 32x32, reduced TX set, fast deblock.
  /// - 8: min block size 8x8, reduced TX set, fast deblock.
  /// - 7: min block size 8x8, reduced TX set.
  /// - 6 (default): min block size 8x8, reduced TX set, complex pred modes for keyframes.
  /// - 5: min block size 8x8, complex pred modes for keyframes, RDO TX decision.
  /// - 4: min block size 8x8, complex pred modes for keyframes, RDO TX decision, full SGR search.
  /// - 3: min block size 8x8, complex pred modes for keyframes, RDO TX decision, include near MVs,
  ///        full SGR search.
  /// - 2: min block size 4x4, complex pred modes, RDO TX decision, include near MVs,
  ///        full SGR search.
  /// - 1: min block size 4x4, complex pred modes, RDO TX decision, include near MVs,
  ///        bottom-up encoding, full SGR search.
  /// - 0 (slowest): min block size 4x4, complex pred modes, RDO TX decision, include near MVs,
  ///        bottom-up encoding with non-square partitions everywhere, full SGR search.
  pub fn from_preset(speed: usize) -> Self {
    SpeedSettings {
      partition_range: Self::partition_range_preset(speed),
      multiref: Self::multiref_preset(speed),
      fast_deblock: Self::fast_deblock_preset(speed),
      reduced_tx_set: Self::reduced_tx_set_preset(speed),
      tx_domain_distortion: Self::tx_domain_distortion_preset(speed),
      tx_domain_rate: Self::tx_domain_rate_preset(speed),
      encode_bottomup: Self::encode_bottomup_preset(speed),
      rdo_tx_decision: Self::rdo_tx_decision_preset(speed),
      prediction_modes: Self::prediction_modes_preset(speed),
      include_near_mvs: Self::include_near_mvs_preset(speed),
      no_scene_detection: Self::no_scene_detection_preset(speed),
      fast_scene_detection: Self::fast_scene_detection_preset(speed),
      cdef: Self::cdef_preset(speed),
      lrf: Self::lrf_preset(speed),
      sgr_complexity: Self::sgr_complexity_preset(speed),
      use_satd_subpel: Self::use_satd_subpel(speed),
      non_square_partition: Self::non_square_partition_preset(speed),
      segmentation: Self::segmentation_preset(speed),
      enable_inter_tx_split: Self::enable_inter_tx_split_preset(speed),
      fine_directional_intra: Self::fine_directional_intra_preset(speed),
    }
  }

  /// This preset is set this way because 8x8 with reduced TX set is faster but with equivalent
  /// or better quality compared to 16x16 (to which reduced TX set does not apply).
  fn partition_range_preset(speed: usize) -> PartitionRange {
    if speed <= 2 {
      PartitionRange::new(BlockSize::BLOCK_4X4, BlockSize::BLOCK_64X64)
    } else if speed <= 8 {
      PartitionRange::new(BlockSize::BLOCK_8X8, BlockSize::BLOCK_64X64)
    } else if speed <= 9 {
      PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_64X64)
    } else {
      PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_32X32)
    }
  }

  /// Multiref is enabled automatically if low_latency is false.
  ///
  /// If low_latency is true, enabling multiref allows using multiple
  /// backwards references. low_latency false enables both forward and
  /// backwards references.
  const fn multiref_preset(speed: usize) -> bool {
    speed <= 7
  }

  const fn fast_deblock_preset(speed: usize) -> bool {
    speed >= 8
  }

  const fn reduced_tx_set_preset(speed: usize) -> bool {
    speed >= 6
  }

  /// TX domain distortion is always faster, with no significant quality change
  const fn tx_domain_distortion_preset(_speed: usize) -> bool {
    true
  }

  const fn tx_domain_rate_preset(_speed: usize) -> bool {
    false
  }

  const fn encode_bottomup_preset(speed: usize) -> bool {
    speed <= 1
  }

  /// Set default rdo-lookahead-frames for different speed settings
  pub fn rdo_lookahead_frames(speed: usize) -> usize {
    match speed {
      9..=10 => 10,
      6..=8 => 20,
      3..=5 => 30,
      0..=2 => 40,
      _ => 40,
    }
  }

  const fn rdo_tx_decision_preset(speed: usize) -> bool {
    speed <= 5
  }

  fn prediction_modes_preset(speed: usize) -> PredictionModesSetting {
    if speed <= 2 {
      PredictionModesSetting::ComplexAll
    } else if speed <= 6 {
      PredictionModesSetting::ComplexKeyframes
    } else {
      PredictionModesSetting::Simple
    }
  }

  const fn include_near_mvs_preset(speed: usize) -> bool {
    speed <= 3
  }

  const fn no_scene_detection_preset(_speed: usize) -> bool {
    false
  }

  const fn fast_scene_detection_preset(speed: usize) -> bool {
    speed == 10
  }

  const fn cdef_preset(_speed: usize) -> bool {
    true
  }

  const fn lrf_preset(speed: usize) -> bool {
    speed <= 9
  }

  fn sgr_complexity_preset(speed: usize) -> SGRComplexityLevel {
    if speed <= 4 {
      SGRComplexityLevel::Full
    } else {
      SGRComplexityLevel::Reduced
    }
  }

  const fn use_satd_subpel(speed: usize) -> bool {
    speed <= 9
  }

  const fn non_square_partition_preset(speed: usize) -> bool {
    speed == 0
  }

  fn segmentation_preset(speed: usize) -> SegmentationLevel {
    if speed == 0 {
      SegmentationLevel::Full
    } else {
      SegmentationLevel::Simple
    }
  }

  // FIXME: With unknown reasons, inter_tx_split does not work if reduced_tx_set is false
  const fn enable_inter_tx_split_preset(speed: usize) -> bool {
    speed >= 9
  }

  fn fine_directional_intra_preset(_speed: usize) -> bool {
    true
  }
}

/// Range of block sizes to use.
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PartitionRange {
  pub(crate) min: BlockSize,
  pub(crate) max: BlockSize,
}

impl PartitionRange {
  /// Creates a new partition range with min and max partition sizes.
  pub fn new(min: BlockSize, max: BlockSize) -> Self {
    assert!(max >= min);
    // Topdown search checks the min block size for PARTITION_SPLIT only, so
    // the min block size must be square.
    assert!(min.is_sqr());
    // Rectangular max partition sizes have not been tested.
    assert!(max.is_sqr());

    Self { min, max }
  }
}

/// Prediction modes to search.
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum PredictionModesSetting {
  /// Only simple prediction modes.
  Simple,
  /// Search all prediction modes on key frames and simple modes on other
  /// frames.
  ComplexKeyframes,
  /// Search all prediction modes on all frames.
  ComplexAll,
}

impl fmt::Display for PredictionModesSetting {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        PredictionModesSetting::Simple => "Simple",
        PredictionModesSetting::ComplexKeyframes => "Complex-KFs",
        PredictionModesSetting::ComplexAll => "Complex-All",
      }
    )
  }
}

/// Search level for self guided restoration
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum SGRComplexityLevel {
  /// Search all sgr parameters
  Full,
  /// Search a reduced set of sgr parameters
  Reduced,
}

impl fmt::Display for SGRComplexityLevel {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        SGRComplexityLevel::Full => "Full",
        SGRComplexityLevel::Reduced => "Reduced",
      }
    )
  }
}

/// Search level for segmentation
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum SegmentationLevel {
  /// No segmentation is signalled.
  Disabled,
  /// Segmentation index is derived from source statistics.
  Simple,
  /// Search all segmentation indices.
  Full,
}

impl fmt::Display for SegmentationLevel {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        SegmentationLevel::Disabled => "Disabled",
        SegmentationLevel::Simple => "Simple",
        SegmentationLevel::Full => "Full",
      }
    )
  }
}
<commit_msg>Reconfigure speed level 2 to be level 3 with bottom-up partitioning<commit_after>// Copyright (c) 2020, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use num_derive::*;

use crate::partition::BlockSize;
use crate::serialize::{Deserialize, Serialize};

use std::fmt;

// NOTE: Add Structures at the end.
/// Contains the speed settings.
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SpeedSettings {
  /// Enables inter-frames to have multiple reference frames.
  ///
  /// Enabled is slower.
  pub multiref: bool,
  /// Enables fast deblocking filter.
  pub fast_deblock: bool,
  /// Enables reduced transform set.
  ///
  /// Enabled is faster.
  pub reduced_tx_set: bool,
  /// Enables using transform-domain distortion instead of pixel-domain.
  ///
  /// Enabled is faster.
  pub tx_domain_distortion: bool,
  /// Enables using transform-domain rate estimation.
  ///
  /// Enabled is faster.
  pub tx_domain_rate: bool,
  /// Enables bottom-up encoding, rather than top-down.
  ///
  /// Enabled is slower.
  pub encode_bottomup: bool,
  /// Enables searching transform size and type with RDO.
  ///
  /// Enabled is slower.
  pub rdo_tx_decision: bool,
  /// Prediction modes to search.
  ///
  /// Complex settings are slower.
  pub prediction_modes: PredictionModesSetting,
  /// Enables searching near motion vectors during RDO.
  ///
  /// Enabled is slower.
  pub include_near_mvs: bool,
  /// Disables scene-cut detection.
  ///
  /// Enabled is faster.
  pub no_scene_detection: bool,
  /// Fast scene detection mode, uses simple SAD instead of encoder cost estimates.
  pub fast_scene_detection: bool,
  /// Enables CDEF.
  pub cdef: bool,
  /// Enables LRF.
  pub lrf: bool,
  /// The amount of search done for self guided restoration.
  pub sgr_complexity: SGRComplexityLevel,
  /// Use SATD instead of SAD for subpixel search.
  ///
  /// Enabled is slower.
  pub use_satd_subpel: bool,
  /// Use non-square partition type everywhere
  ///
  /// Enabled is slower.
  pub non_square_partition: bool,

  /// Search level for segmentation.
  ///
  /// Full search is at least twice as slow.
  pub segmentation: SegmentationLevel,

  /// Enable tx split for inter mode block.
  pub enable_inter_tx_split: bool,

  /// Use fine directional intra prediction
  pub fine_directional_intra: bool,

  // NOTE: put enums and basic type fields above
  /// Range of partition sizes that can be used. Larger ranges are slower.
  ///
  /// Must be based on square block sizes, so e.g. 8×4 isn't allowed here.
  pub partition_range: PartitionRange,
}

impl Default for SpeedSettings {
  /// This is currently used exclusively for feature testing and comparison.
  /// It is set to the slowest settings possible.
  fn default() -> Self {
    SpeedSettings {
      partition_range: PartitionRange::new(
        BlockSize::BLOCK_4X4,
        BlockSize::BLOCK_64X64,
      ),
      multiref: true,
      fast_deblock: false,
      reduced_tx_set: false,
      tx_domain_distortion: false,
      tx_domain_rate: false,
      encode_bottomup: true,
      rdo_tx_decision: true,
      prediction_modes: PredictionModesSetting::ComplexAll,
      include_near_mvs: true,
      no_scene_detection: false,
      fast_scene_detection: false,
      cdef: true,
      lrf: false,
      sgr_complexity: SGRComplexityLevel::Full,
      use_satd_subpel: true,
      non_square_partition: true,
      segmentation: SegmentationLevel::Full,
      enable_inter_tx_split: false,
      fine_directional_intra: false,
    }
  }
}

impl SpeedSettings {
  /// Set the speed setting according to a numeric speed preset.
  ///
  /// The speed settings vary depending on speed value from 0 to 10.
  /// - 10 (fastest): fixed block size 32x32, reduced TX set, fast deblock, fast scenechange detection.
  /// - 9: min block size 32x32, reduced TX set, fast deblock.
  /// - 8: min block size 8x8, reduced TX set, fast deblock.
  /// - 7: min block size 8x8, reduced TX set.
  /// - 6 (default): min block size 8x8, reduced TX set, complex pred modes for keyframes.
  /// - 5: min block size 8x8, complex pred modes for keyframes, RDO TX decision.
  /// - 4: min block size 8x8, complex pred modes for keyframes, RDO TX decision, full SGR search.
  /// - 3: min block size 8x8, complex pred modes for keyframes, RDO TX decision, include near MVs,
  ///        full SGR search.
  /// - 2: min block size 8x8, complex pred modes for keyframes, RDO TX decision, include near MVs,
  ///        bottom-up encoding, full SGR search.
  /// - 1: min block size 4x4, complex pred modes, RDO TX decision, include near MVs,
  ///        bottom-up encoding, full SGR search.
  /// - 0 (slowest): min block size 4x4, complex pred modes, RDO TX decision, include near MVs,
  ///        bottom-up encoding with non-square partitions everywhere, full SGR search.
  pub fn from_preset(speed: usize) -> Self {
    SpeedSettings {
      partition_range: Self::partition_range_preset(speed),
      multiref: Self::multiref_preset(speed),
      fast_deblock: Self::fast_deblock_preset(speed),
      reduced_tx_set: Self::reduced_tx_set_preset(speed),
      tx_domain_distortion: Self::tx_domain_distortion_preset(speed),
      tx_domain_rate: Self::tx_domain_rate_preset(speed),
      encode_bottomup: Self::encode_bottomup_preset(speed),
      rdo_tx_decision: Self::rdo_tx_decision_preset(speed),
      prediction_modes: Self::prediction_modes_preset(speed),
      include_near_mvs: Self::include_near_mvs_preset(speed),
      no_scene_detection: Self::no_scene_detection_preset(speed),
      fast_scene_detection: Self::fast_scene_detection_preset(speed),
      cdef: Self::cdef_preset(speed),
      lrf: Self::lrf_preset(speed),
      sgr_complexity: Self::sgr_complexity_preset(speed),
      use_satd_subpel: Self::use_satd_subpel(speed),
      non_square_partition: Self::non_square_partition_preset(speed),
      segmentation: Self::segmentation_preset(speed),
      enable_inter_tx_split: Self::enable_inter_tx_split_preset(speed),
      fine_directional_intra: Self::fine_directional_intra_preset(speed),
    }
  }

  /// This preset is set this way because 8x8 with reduced TX set is faster but with equivalent
  /// or better quality compared to 16x16 (to which reduced TX set does not apply).
  fn partition_range_preset(speed: usize) -> PartitionRange {
    if speed <= 1 {
      PartitionRange::new(BlockSize::BLOCK_4X4, BlockSize::BLOCK_64X64)
    } else if speed <= 8 {
      PartitionRange::new(BlockSize::BLOCK_8X8, BlockSize::BLOCK_64X64)
    } else if speed <= 9 {
      PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_64X64)
    } else {
      PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_32X32)
    }
  }

  /// Multiref is enabled automatically if low_latency is false.
  ///
  /// If low_latency is true, enabling multiref allows using multiple
  /// backwards references. low_latency false enables both forward and
  /// backwards references.
  const fn multiref_preset(speed: usize) -> bool {
    speed <= 7
  }

  const fn fast_deblock_preset(speed: usize) -> bool {
    speed >= 8
  }

  const fn reduced_tx_set_preset(speed: usize) -> bool {
    speed >= 6
  }

  /// TX domain distortion is always faster, with no significant quality change
  const fn tx_domain_distortion_preset(_speed: usize) -> bool {
    true
  }

  const fn tx_domain_rate_preset(_speed: usize) -> bool {
    false
  }

  const fn encode_bottomup_preset(speed: usize) -> bool {
    speed <= 2
  }

  /// Set default rdo-lookahead-frames for different speed settings
  pub fn rdo_lookahead_frames(speed: usize) -> usize {
    match speed {
      9..=10 => 10,
      6..=8 => 20,
      2..=5 => 30,
      0..=1 => 40,
      _ => 40,
    }
  }

  const fn rdo_tx_decision_preset(speed: usize) -> bool {
    speed <= 5
  }

  fn prediction_modes_preset(speed: usize) -> PredictionModesSetting {
    if speed <= 1 {
      PredictionModesSetting::ComplexAll
    } else if speed <= 6 {
      PredictionModesSetting::ComplexKeyframes
    } else {
      PredictionModesSetting::Simple
    }
  }

  const fn include_near_mvs_preset(speed: usize) -> bool {
    speed <= 3
  }

  const fn no_scene_detection_preset(_speed: usize) -> bool {
    false
  }

  const fn fast_scene_detection_preset(speed: usize) -> bool {
    speed == 10
  }

  const fn cdef_preset(_speed: usize) -> bool {
    true
  }

  const fn lrf_preset(speed: usize) -> bool {
    speed <= 9
  }

  fn sgr_complexity_preset(speed: usize) -> SGRComplexityLevel {
    if speed <= 4 {
      SGRComplexityLevel::Full
    } else {
      SGRComplexityLevel::Reduced
    }
  }

  const fn use_satd_subpel(speed: usize) -> bool {
    speed <= 9
  }

  const fn non_square_partition_preset(speed: usize) -> bool {
    speed == 0
  }

  fn segmentation_preset(speed: usize) -> SegmentationLevel {
    if speed == 0 {
      SegmentationLevel::Full
    } else {
      SegmentationLevel::Simple
    }
  }

  // FIXME: With unknown reasons, inter_tx_split does not work if reduced_tx_set is false
  const fn enable_inter_tx_split_preset(speed: usize) -> bool {
    speed >= 9
  }

  fn fine_directional_intra_preset(_speed: usize) -> bool {
    true
  }
}

/// Range of block sizes to use.
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PartitionRange {
  pub(crate) min: BlockSize,
  pub(crate) max: BlockSize,
}

impl PartitionRange {
  /// Creates a new partition range with min and max partition sizes.
  pub fn new(min: BlockSize, max: BlockSize) -> Self {
    assert!(max >= min);
    // Topdown search checks the min block size for PARTITION_SPLIT only, so
    // the min block size must be square.
    assert!(min.is_sqr());
    // Rectangular max partition sizes have not been tested.
    assert!(max.is_sqr());

    Self { min, max }
  }
}

/// Prediction modes to search.
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum PredictionModesSetting {
  /// Only simple prediction modes.
  Simple,
  /// Search all prediction modes on key frames and simple modes on other
  /// frames.
  ComplexKeyframes,
  /// Search all prediction modes on all frames.
  ComplexAll,
}

impl fmt::Display for PredictionModesSetting {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        PredictionModesSetting::Simple => "Simple",
        PredictionModesSetting::ComplexKeyframes => "Complex-KFs",
        PredictionModesSetting::ComplexAll => "Complex-All",
      }
    )
  }
}

/// Search level for self guided restoration
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum SGRComplexityLevel {
  /// Search all sgr parameters
  Full,
  /// Search a reduced set of sgr parameters
  Reduced,
}

impl fmt::Display for SGRComplexityLevel {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        SGRComplexityLevel::Full => "Full",
        SGRComplexityLevel::Reduced => "Reduced",
      }
    )
  }
}

/// Search level for segmentation
#[derive(
  Clone,
  Copy,
  Debug,
  PartialOrd,
  PartialEq,
  FromPrimitive,
  Serialize,
  Deserialize,
)]
pub enum SegmentationLevel {
  /// No segmentation is signalled.
  Disabled,
  /// Segmentation index is derived from source statistics.
  Simple,
  /// Search all segmentation indices.
  Full,
}

impl fmt::Display for SegmentationLevel {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    write!(
      f,
      "{}",
      match self {
        SegmentationLevel::Disabled => "Disabled",
        SegmentationLevel::Simple => "Simple",
        SegmentationLevel::Full => "Full",
      }
    )
  }
}
<|endoftext|>


<commit_before>// xfail-pretty

// An example of the bank protocol from eholk's blog post.
//
// http://theincredibleholk.wordpress.com/2012/07/06/rusty-pipes/

import pipes::try_recv;

type username = ~str;
type password = ~str;
type money = float;
type amount = float;

proto! bank {
    login:send {
        login(username, password) -> login_response
    }

    login_response:recv {
        ok -> connected,
        invalid -> login
    }

    connected:send {
        deposit(money) -> connected,
        withdrawal(amount) -> withdrawal_response
    }

    withdrawal_response:recv {
        money(money) -> connected,
        insufficient_funds -> connected
    }
}

macro_rules! move {
    { $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
}

fn switch<T: send, U>(+endp: pipes::recv_packet<T>,
                      f: fn(+option<T>) -> U) -> U {
    f(pipes::try_recv(endp))
}

fn move<T>(-x: T) -> T { x }

macro_rules! follow {
    {
        $($message:path($($x: ident),+) => $next:ident $e:expr)+
    } => (
        |m| alt move(m) {
          $(some($message($($x,)* next)) {
            let $next = move!{next};
            $e })+
          _ { fail }
        }
    );

    {
        $($message:path => $next:ident $e:expr)+
    } => (
        |m| alt move(m) {
            $(some($message(next)) {
                let $next = move!{next};
                $e })+
                _ { fail }
        }
    )
}

/*
fn client_follow(+bank: bank::client::login) {
    import bank::*;

    let bank = client::login(bank, ~"theincredibleholk", ~"1234");
    let bank = switch(bank, follow! {
        ok => connected { connected }
        invalid => _next { fail ~"bank closed the connected" }
    });

    /* // potential alternate syntax
    let bank = recv_alt! {
        bank => {
            | ok -> connected { connected }
            | invalid -> _next { fail }
        }
        bank2 => {
            | foo -> _n { fail }
        }
    }
    */

    let bank = client::deposit(bank, 100.00);
    let bank = client::withdrawal(bank, 50.00);
    alt try_recv(bank) {
      some(money(m, _)) {
        io::println(~"Yay! I got money!");
      }
      some(insufficient_funds(_)) {
        fail ~"someone stole my money"
      }
      none {
        fail ~"bank closed the connection"
      }
    }
}
*/

fn bank_client(+bank: bank::client::login) {
    import bank::*;

    let bank = client::login(bank, ~"theincredibleholk", ~"1234");
    let bank = alt try_recv(bank) {
      some(ok(connected)) {
        move!{connected}
      }
      some(invalid(_)) { fail ~"login unsuccessful" }
      none { fail ~"bank closed the connection" }
    };

    let bank = client::deposit(bank, 100.00);
    let bank = client::withdrawal(bank, 50.00);
    alt try_recv(bank) {
      some(money(m, _)) {
        io::println(~"Yay! I got money!");
      }
      some(insufficient_funds(_)) {
        fail ~"someone stole my money"
      }
      none {
        fail ~"bank closed the connection"
      }
    }
}

fn main() {
}<commit_msg>test: Fix broken test that used "move" as an identifier<commit_after>// xfail-pretty

// An example of the bank protocol from eholk's blog post.
//
// http://theincredibleholk.wordpress.com/2012/07/06/rusty-pipes/

import pipes::try_recv;

type username = ~str;
type password = ~str;
type money = float;
type amount = float;

proto! bank {
    login:send {
        login(username, password) -> login_response
    }

    login_response:recv {
        ok -> connected,
        invalid -> login
    }

    connected:send {
        deposit(money) -> connected,
        withdrawal(amount) -> withdrawal_response
    }

    withdrawal_response:recv {
        money(money) -> connected,
        insufficient_funds -> connected
    }
}

macro_rules! move_it {
    { $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
}

fn switch<T: send, U>(+endp: pipes::recv_packet<T>,
                      f: fn(+option<T>) -> U) -> U {
    f(pipes::try_recv(endp))
}

fn move_it<T>(-x: T) -> T { x }

macro_rules! follow {
    {
        $($message:path($($x: ident),+) => $next:ident $e:expr)+
    } => (
        |m| alt move_it(m) {
          $(some($message($($x,)* next)) {
            let $next = move_it!{next};
            $e })+
          _ { fail }
        }
    );

    {
        $($message:path => $next:ident $e:expr)+
    } => (
        |m| alt move_it(m) {
            $(some($message(next)) {
                let $next = move_it!{next};
                $e })+
                _ { fail }
        }
    )
}

/*
fn client_follow(+bank: bank::client::login) {
    import bank::*;

    let bank = client::login(bank, ~"theincredibleholk", ~"1234");
    let bank = switch(bank, follow! {
        ok => connected { connected }
        invalid => _next { fail ~"bank closed the connected" }
    });

    /* // potential alternate syntax
    let bank = recv_alt! {
        bank => {
            | ok -> connected { connected }
            | invalid -> _next { fail }
        }
        bank2 => {
            | foo -> _n { fail }
        }
    }
    */

    let bank = client::deposit(bank, 100.00);
    let bank = client::withdrawal(bank, 50.00);
    alt try_recv(bank) {
      some(money(m, _)) {
        io::println(~"Yay! I got money!");
      }
      some(insufficient_funds(_)) {
        fail ~"someone stole my money"
      }
      none {
        fail ~"bank closed the connection"
      }
    }
}
*/

fn bank_client(+bank: bank::client::login) {
    import bank::*;

    let bank = client::login(bank, ~"theincredibleholk", ~"1234");
    let bank = alt try_recv(bank) {
      some(ok(connected)) {
        move_it!{connected}
      }
      some(invalid(_)) { fail ~"login unsuccessful" }
      none { fail ~"bank closed the connection" }
    };

    let bank = client::deposit(bank, 100.00);
    let bank = client::withdrawal(bank, 50.00);
    alt try_recv(bank) {
      some(money(m, _)) {
        io::println(~"Yay! I got money!");
      }
      some(insufficient_funds(_)) {
        fail ~"someone stole my money"
      }
      none {
        fail ~"bank closed the connection"
      }
    }
}

fn main() {
}
<|endoftext|>