<commit_before>//! Create new `Streams` connected to external inputs.

use std::rc::Rc;
use std::cell::RefCell;
use std::default::Default;

use progress::frontier::Antichain;
use progress::{Operate, Timestamp};
use progress::nested::subgraph::Source;
use progress::count_map::CountMap;
use progress::timestamp::RootTimestamp;
use progress::nested::product::Product;

use timely_communication::Allocate;
use {Data, Push};
use dataflow::channels::Content;
use dataflow::channels::pushers::{Tee, Counter};

use dataflow::{Stream, Scope};
use dataflow::scopes::{Child, Root};

// TODO : This is an exogenous input, but it would be nice to wrap a Subgraph in something
// TODO : more like a harness, with direct access to its inputs.

// NOTE : This only takes a &self, not a &mut self, which works but is a bit weird.
// NOTE : Experiments with &mut indicate that the borrow of 'a lives for too long.
// NOTE : Might be able to fix with another lifetime parameter, say 'c: 'a.

/// Create a new `Stream` and `Handle` through which to supply input.
pub trait Input<'a, A: Allocate, T: Timestamp+Ord> {
    /// Create a new `Stream` and `Handle` through which to supply input.
    ///
    /// The `new_input` method returns a pair `(Handle, Stream)` where the `Stream` can be used
    /// immediately for timely dataflow construction, and the `Handle` is later used to introduce
    /// data into the timely dataflow computation.
    ///
    /// The `Handle` also provides a means to indicate
    /// to timely dataflow that the input has advanced beyond certain timestamps, allowing timely
    /// to issue progress notifications.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         stream.inspect(|x| println!("hello {:?}", x));
    ///         input
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    fn new_input<D: Data>(&mut self) -> (Handle<T, D>, Stream<Child<'a, Root<A>, T>, D>);

    /// Create a new stream from a supplied interactive handle.
    ///
    /// This method creates a new timely stream whose data are supplied interactively through the `handle`
    /// argument. Each handle may be used multiple times (or not at all), and will clone data as appropriate
    /// if it as attached to more than one stream.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    /// use timely::dataflow::operators::input::Handle;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = Handle::new();
    ///     worker.dataflow(|scope| {
    ///         scope.input_from(&mut input)
    ///              .inspect(|x| println!("hello {:?}", x));
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    fn input_from<D: Data>(&mut self, handle: &mut Handle<T, D>) -> Stream<Child<'a, Root<A>, T>, D>;
}

impl<'a, A: Allocate, T: Timestamp+Ord> Input<'a, A, T> for Child<'a, Root<A>, T> {
    fn new_input<D: Data>(&mut self) -> (Handle<T, D>, Stream<Child<'a, Root<A>, T>, D>) {
        let mut handle = Handle::new();
        let stream = self.input_from(&mut handle);
        (handle, stream)
    }

    fn input_from<D: Data>(&mut self, handle: &mut Handle<T, D>) -> Stream<Child<'a, Root<A>, T>, D> {

        let (output, registrar) = Tee::<Product<RootTimestamp, T>, D>::new();
        let produced = Rc::new(RefCell::new(CountMap::new()));
        let counter = Counter::new(output, produced.clone());

        let progress = Rc::new(RefCell::new(CountMap::new()));

        handle.register(counter, progress.clone());

        let copies = self.peers();

        let index = self.add_operator(Operator {
            progress: progress.clone(),
            messages: produced.clone(),
            copies:   copies,
        });

        Stream::new(Source { index: index, port: 0 }, registrar, self.clone())
    }
}

struct Operator<T:Timestamp+Ord> {
    progress:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    messages:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // messages sent since last asked
    copies:     usize,
}

impl<T:Timestamp+Ord> Operate<Product<RootTimestamp, T>> for Operator<T> {
    fn name(&self) -> String { "Input".to_owned() }
    fn inputs(&self) -> usize { 0 }
    fn outputs(&self) -> usize { 1 }

    fn get_internal_summary(&mut self) -> (Vec<Vec<Antichain<<Product<RootTimestamp, T> as Timestamp>::Summary>>>,
                                           Vec<CountMap<Product<RootTimestamp, T>>>) {
        let mut map = CountMap::new();
        map.update(&Default::default(), self.copies as i64);
        (Vec::new(), vec![map])
    }

    fn pull_internal_progress(&mut self,_messages_consumed: &mut [CountMap<Product<RootTimestamp, T>>],
                                         frontier_progress: &mut [CountMap<Product<RootTimestamp, T>>],
                                         messages_produced: &mut [CountMap<Product<RootTimestamp, T>>]) -> bool
    {
        self.messages.borrow_mut().drain_into(&mut messages_produced[0]);
        self.progress.borrow_mut().drain_into(&mut frontier_progress[0]);
        false
    }

    fn notify_me(&self) -> bool { false }
}

/// A handle to an input `Stream`, used to introduce data to a timely dataflow computation.
pub struct Handle<T: Timestamp, D: Data> {
    progress: Vec<Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>>,
    pushers: Vec<Counter<Product<RootTimestamp, T>, D, Tee<Product<RootTimestamp, T>, D>>>,
    buffer1: Vec<D>,
    buffer2: Vec<D>,
    now_at: Product<RootTimestamp, T>,
}

impl<T:Timestamp, D: Data> Handle<T, D> {

    /// Allocates a new input handle, from which one can create timely streams.
    pub fn new() -> Self {
        Handle {
            progress: Vec::new(),
            pushers: Vec::new(),
            buffer1: Vec::with_capacity(Content::<D>::default_length()),
            buffer2: Vec::with_capacity(Content::<D>::default_length()),
            now_at: Default::default(),
        }
    }

    fn register(
        &mut self,
        pusher: Counter<Product<RootTimestamp, T>, D, Tee<Product<RootTimestamp, T>, D>>,
        progress: Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>
    ) {
        // flush current contents, so new registrant does not see existing data.
        if !self.buffer1.is_empty() { self.flush(); }

        // we need to produce an appropriate update to the capabilities for `progress`, in case a
        // user has decided to drive the handle around a bit before registering it.
        progress.borrow_mut().update(&Default::default(), -1);
        progress.borrow_mut().update(&self.now_at, 1);

        self.progress.push(progress);
        self.pushers.push(pusher);
    }

    // flushes our buffer at each of the destinations. there can be more than one; clone if needed.
    fn flush(&mut self) {
        for index in 0 .. self.pushers.len() {
            if index < self.pushers.len() - 1 {
                self.buffer2.extend_from_slice(&self.buffer1[..]);
                Content::push_at(&mut self.buffer2, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer2.is_empty());
            }
            else {
                Content::push_at(&mut self.buffer1, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer1.is_empty());
            }
        }
        self.buffer1.clear();
    }

    // closes the current epoch, flushing if needed, shutting if needed, and updating the frontier.
    fn close_epoch(&mut self) {
        if !self.buffer1.is_empty() { self.flush(); }
        for pusher in self.pushers.iter_mut() {
            pusher.done();
        }
        for progress in self.progress.iter() {
            progress.borrow_mut().update(&self.now_at, -1);
        }
    }

    #[inline(always)]
    /// Sends one record into the corresponding timely dataflow `Stream`, at the current epoch.
    pub fn send(&mut self, data: D) {
        // assert!(self.buffer.capacity() == Content::<D>::default_length());
        self.buffer1.push(data);
        if self.buffer1.len() == self.buffer1.capacity() {
            self.flush();
        }
    }

    /// Sends a batch of records into the corresponding timely dataflow `Stream`, at the current epoch.
    ///
    /// This method flushes single elements previously sent with `send`, to keep the insertion order.
    pub fn send_batch(&mut self, buffer: &mut Vec<D>) {

        // flush buffered elements to ensure local fifo.
        if !self.buffer1.is_empty() { self.flush(); }

        // push buffer (or clone of buffer) at each destination.
        for index in 0 .. self.pushers.len() {
            if index < self.pushers.len() - 1 {
                self.buffer2.extend_from_slice(&buffer[..]);
                Content::push_at(&mut self.buffer2, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer2.is_empty());
            }
            else {
                Content::push_at(buffer, self.now_at.clone(), &mut self.pushers[index]);
                assert!(buffer.is_empty());
            }
        }
        buffer.clear();
    }

    /// Advances the current epoch to `next`.
    ///
    /// This method allows timely dataflow to issue progress notifications as it can now determine
    /// that this input can no longer produce data at earlier timestamps.
    pub fn advance_to(&mut self, next: T) {
        assert!(self.now_at.inner.less_equal(&next));
        self.close_epoch();
        self.now_at = RootTimestamp::new(next);
        for progress in self.progress.iter() {
            progress.borrow_mut().update(&self.now_at, 1);
        }
    }

    /// Closes the input.
    ///
    /// This method allows timely dataflow to issue all progress notifications blocked by this input
    /// and to begin to shut down operators, as this input can no longer produce data.
    pub fn close(self) { }

    /// Reports the current epoch.
    pub fn epoch(&self) -> &T {
        &self.now_at.inner
    }

    /// Reports the current timestamp.
    pub fn time(&self) -> &Product<RootTimestamp, T> {
        &self.now_at
    }
}

impl<T:Timestamp, D: Data> Drop for Handle<T, D> {
    fn drop(&mut self) {
        self.close_epoch();
    }
}
<commit_msg>inherent to_stream for input handle<commit_after>//! Create new `Streams` connected to external inputs.

use std::rc::Rc;
use std::cell::RefCell;
use std::default::Default;

use progress::frontier::Antichain;
use progress::{Operate, Timestamp};
use progress::nested::subgraph::Source;
use progress::count_map::CountMap;
use progress::timestamp::RootTimestamp;
use progress::nested::product::Product;

use timely_communication::Allocate;
use {Data, Push};
use dataflow::channels::Content;
use dataflow::channels::pushers::{Tee, Counter};

use dataflow::{Stream, Scope};
use dataflow::scopes::{Child, Root};

// TODO : This is an exogenous input, but it would be nice to wrap a Subgraph in something
// TODO : more like a harness, with direct access to its inputs.

// NOTE : This only takes a &self, not a &mut self, which works but is a bit weird.
// NOTE : Experiments with &mut indicate that the borrow of 'a lives for too long.
// NOTE : Might be able to fix with another lifetime parameter, say 'c: 'a.

/// Create a new `Stream` and `Handle` through which to supply input.
pub trait Input<'a, A: Allocate, T: Timestamp+Ord> {
    /// Create a new `Stream` and `Handle` through which to supply input.
    ///
    /// The `new_input` method returns a pair `(Handle, Stream)` where the `Stream` can be used
    /// immediately for timely dataflow construction, and the `Handle` is later used to introduce
    /// data into the timely dataflow computation.
    ///
    /// The `Handle` also provides a means to indicate
    /// to timely dataflow that the input has advanced beyond certain timestamps, allowing timely
    /// to issue progress notifications.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = worker.dataflow(|scope| {
    ///         let (input, stream) = scope.new_input();
    ///         stream.inspect(|x| println!("hello {:?}", x));
    ///         input
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    fn new_input<D: Data>(&mut self) -> (Handle<T, D>, Stream<Child<'a, Root<A>, T>, D>);

    /// Create a new stream from a supplied interactive handle.
    ///
    /// This method creates a new timely stream whose data are supplied interactively through the `handle`
    /// argument. Each handle may be used multiple times (or not at all), and will clone data as appropriate
    /// if it as attached to more than one stream.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    /// use timely::dataflow::operators::input::Handle;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = Handle::new();
    ///     worker.dataflow(|scope| {
    ///         scope.input_from(&mut input)
    ///              .inspect(|x| println!("hello {:?}", x));
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    fn input_from<D: Data>(&mut self, handle: &mut Handle<T, D>) -> Stream<Child<'a, Root<A>, T>, D>;
}

impl<'a, A: Allocate, T: Timestamp+Ord> Input<'a, A, T> for Child<'a, Root<A>, T> {
    fn new_input<D: Data>(&mut self) -> (Handle<T, D>, Stream<Child<'a, Root<A>, T>, D>) {
        let mut handle = Handle::new();
        let stream = self.input_from(&mut handle);
        (handle, stream)
    }

    fn input_from<D: Data>(&mut self, handle: &mut Handle<T, D>) -> Stream<Child<'a, Root<A>, T>, D> {

        let (output, registrar) = Tee::<Product<RootTimestamp, T>, D>::new();
        let produced = Rc::new(RefCell::new(CountMap::new()));
        let counter = Counter::new(output, produced.clone());

        let progress = Rc::new(RefCell::new(CountMap::new()));

        handle.register(counter, progress.clone());

        let copies = self.peers();

        let index = self.add_operator(Operator {
            progress: progress.clone(),
            messages: produced.clone(),
            copies:   copies,
        });

        Stream::new(Source { index: index, port: 0 }, registrar, self.clone())
    }
}

struct Operator<T:Timestamp+Ord> {
    progress:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    messages:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // messages sent since last asked
    copies:     usize,
}

impl<T:Timestamp+Ord> Operate<Product<RootTimestamp, T>> for Operator<T> {
    fn name(&self) -> String { "Input".to_owned() }
    fn inputs(&self) -> usize { 0 }
    fn outputs(&self) -> usize { 1 }

    fn get_internal_summary(&mut self) -> (Vec<Vec<Antichain<<Product<RootTimestamp, T> as Timestamp>::Summary>>>,
                                           Vec<CountMap<Product<RootTimestamp, T>>>) {
        let mut map = CountMap::new();
        map.update(&Default::default(), self.copies as i64);
        (Vec::new(), vec![map])
    }

    fn pull_internal_progress(&mut self,_messages_consumed: &mut [CountMap<Product<RootTimestamp, T>>],
                                         frontier_progress: &mut [CountMap<Product<RootTimestamp, T>>],
                                         messages_produced: &mut [CountMap<Product<RootTimestamp, T>>]) -> bool
    {
        self.messages.borrow_mut().drain_into(&mut messages_produced[0]);
        self.progress.borrow_mut().drain_into(&mut frontier_progress[0]);
        false
    }

    fn notify_me(&self) -> bool { false }
}

/// A handle to an input `Stream`, used to introduce data to a timely dataflow computation.
pub struct Handle<T: Timestamp, D: Data> {
    progress: Vec<Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>>,
    pushers: Vec<Counter<Product<RootTimestamp, T>, D, Tee<Product<RootTimestamp, T>, D>>>,
    buffer1: Vec<D>,
    buffer2: Vec<D>,
    now_at: Product<RootTimestamp, T>,
}

impl<T:Timestamp, D: Data> Handle<T, D> {

    /// Allocates a new input handle, from which one can create timely streams.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    /// use timely::dataflow::operators::input::Handle;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = Handle::new();
    ///     worker.dataflow(|scope| {
    ///         scope.input_from(&mut input)
    ///              .inspect(|x| println!("hello {:?}", x));
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    pub fn new() -> Self {
        Handle {
            progress: Vec::new(),
            pushers: Vec::new(),
            buffer1: Vec::with_capacity(Content::<D>::default_length()),
            buffer2: Vec::with_capacity(Content::<D>::default_length()),
            now_at: Default::default(),
        }
    }

    /// Creates an input stream from the handle in the supplied scope.
    ///
    /// #Examples
    /// ```
    /// use timely::*;
    /// use timely::dataflow::operators::{Input, Inspect};
    /// use timely::dataflow::operators::input::Handle;
    ///
    /// // construct and execute a timely dataflow
    /// timely::execute(Configuration::Thread, |worker| {
    ///
    ///     // add an input and base computation off of it
    ///     let mut input = Handle::new();
    ///     worker.dataflow(|scope| {
    ///         input.to_stream(scope)
    ///              .inspect(|x| println!("hello {:?}", x));
    ///     });
    ///
    ///     // introduce input, advance computation
    ///     for round in 0..10 {
    ///         input.send(round);
    ///         input.advance_to(round + 1);
    ///         worker.step();
    ///     }
    /// });
    /// ```
    pub fn to_stream<'a, A: Allocate>(&mut self, scope: &mut Child<'a, Root<A>, T>) -> Stream<Child<'a, Root<A>, T>, D>
    where T: Ord {
        scope.input_from(self)
    }

    fn register(
        &mut self,
        pusher: Counter<Product<RootTimestamp, T>, D, Tee<Product<RootTimestamp, T>, D>>,
        progress: Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>
    ) {
        // flush current contents, so new registrant does not see existing data.
        if !self.buffer1.is_empty() { self.flush(); }

        // we need to produce an appropriate update to the capabilities for `progress`, in case a
        // user has decided to drive the handle around a bit before registering it.
        progress.borrow_mut().update(&Default::default(), -1);
        progress.borrow_mut().update(&self.now_at, 1);

        self.progress.push(progress);
        self.pushers.push(pusher);
    }

    // flushes our buffer at each of the destinations. there can be more than one; clone if needed.
    fn flush(&mut self) {
        for index in 0 .. self.pushers.len() {
            if index < self.pushers.len() - 1 {
                self.buffer2.extend_from_slice(&self.buffer1[..]);
                Content::push_at(&mut self.buffer2, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer2.is_empty());
            }
            else {
                Content::push_at(&mut self.buffer1, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer1.is_empty());
            }
        }
        self.buffer1.clear();
    }

    // closes the current epoch, flushing if needed, shutting if needed, and updating the frontier.
    fn close_epoch(&mut self) {
        if !self.buffer1.is_empty() { self.flush(); }
        for pusher in self.pushers.iter_mut() {
            pusher.done();
        }
        for progress in self.progress.iter() {
            progress.borrow_mut().update(&self.now_at, -1);
        }
    }

    #[inline(always)]
    /// Sends one record into the corresponding timely dataflow `Stream`, at the current epoch.
    pub fn send(&mut self, data: D) {
        // assert!(self.buffer.capacity() == Content::<D>::default_length());
        self.buffer1.push(data);
        if self.buffer1.len() == self.buffer1.capacity() {
            self.flush();
        }
    }

    /// Sends a batch of records into the corresponding timely dataflow `Stream`, at the current epoch.
    ///
    /// This method flushes single elements previously sent with `send`, to keep the insertion order.
    pub fn send_batch(&mut self, buffer: &mut Vec<D>) {

        // flush buffered elements to ensure local fifo.
        if !self.buffer1.is_empty() { self.flush(); }

        // push buffer (or clone of buffer) at each destination.
        for index in 0 .. self.pushers.len() {
            if index < self.pushers.len() - 1 {
                self.buffer2.extend_from_slice(&buffer[..]);
                Content::push_at(&mut self.buffer2, self.now_at.clone(), &mut self.pushers[index]);
                assert!(self.buffer2.is_empty());
            }
            else {
                Content::push_at(buffer, self.now_at.clone(), &mut self.pushers[index]);
                assert!(buffer.is_empty());
            }
        }
        buffer.clear();
    }

    /// Advances the current epoch to `next`.
    ///
    /// This method allows timely dataflow to issue progress notifications as it can now determine
    /// that this input can no longer produce data at earlier timestamps.
    pub fn advance_to(&mut self, next: T) {
        assert!(self.now_at.inner.less_equal(&next));
        self.close_epoch();
        self.now_at = RootTimestamp::new(next);
        for progress in self.progress.iter() {
            progress.borrow_mut().update(&self.now_at, 1);
        }
    }

    /// Closes the input.
    ///
    /// This method allows timely dataflow to issue all progress notifications blocked by this input
    /// and to begin to shut down operators, as this input can no longer produce data.
    pub fn close(self) { }

    /// Reports the current epoch.
    pub fn epoch(&self) -> &T {
        &self.now_at.inner
    }

    /// Reports the current timestamp.
    pub fn time(&self) -> &Product<RootTimestamp, T> {
        &self.now_at
    }
}

impl<T:Timestamp, D: Data> Drop for Handle<T, D> {
    fn drop(&mut self) {
        self.close_epoch();
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

use homectl_types::{device::DeviceState, utils::cct_to_rgb};
use palette::{Hsl, Hsv};

pub fn hsv_to_css_hsl_str(hsv: &Option<Hsv>) -> String {
    let hsv = hsv.unwrap_or_else(|| Hsv::new(0.0, 0.0, 1.0));
    let hsl: Hsl = hsv.into();

    format!(
        "hsl({}, {}%, {}%)",
        hsl.hue.to_positive_degrees().floor(),
        (hsl.saturation * 100.0).floor(),
        (hsl.lightness * 100.0).floor()
    )
}

pub fn scale_hsv_value_to_display(hsv: Hsv) -> Hsv {
    let value = (hsv.value + 1.0) / 2.0;
    Hsv::new(hsv.hue, hsv.saturation, value)
}

pub fn get_device_state_color(state: &DeviceState) -> Option<Hsv> {
    match (state.get_color(), state.get_cct()) {
        (Some(color), _) => Some(color),
        (_, Some(cct)) => {
            let rgb = cct_to_rgb(cct.get_cct());
            let hsv: Hsv = rgb.into();
            Some(hsv)
        }
        (_, _) => None,
    }
}

pub fn cmp_hsv(a: &Hsv, b: &Hsv) -> Ordering {
    let a = hsv_to_css_hsl_str(&Some(*a));
    let b = hsv_to_css_hsl_str(&Some(*b));

    a.cmp(&b)
}

pub const ARROW_STYLES: &str = tw("text-right mr-2 leading-4 text-4xl flex-1");

/// Annotates tailwindcss utilities to be picked up by editor tooling.
pub const fn tw(class: &str) -> &str {
    class
}
<commit_msg>Sort color gradients by hue<commit_after>use std::cmp::Ordering;

use homectl_types::{device::DeviceState, utils::cct_to_rgb};
use palette::{Hsl, Hsv};

pub fn hsv_to_css_hsl_str(hsv: &Option<Hsv>) -> String {
    let hsv = hsv.unwrap_or_else(|| Hsv::new(0.0, 0.0, 1.0));
    let hsl: Hsl = hsv.into();

    format!(
        "hsl({}, {}%, {}%)",
        hsl.hue.to_positive_degrees().floor(),
        (hsl.saturation * 100.0).floor(),
        (hsl.lightness * 100.0).floor()
    )
}

pub fn scale_hsv_value_to_display(hsv: Hsv) -> Hsv {
    let value = (hsv.value + 1.0) / 2.0;
    Hsv::new(hsv.hue, hsv.saturation, value)
}

pub fn get_device_state_color(state: &DeviceState) -> Option<Hsv> {
    match (state.get_color(), state.get_cct()) {
        (Some(color), _) => Some(color),
        (_, Some(cct)) => {
            let rgb = cct_to_rgb(cct.get_cct());
            let hsv: Hsv = rgb.into();
            Some(hsv)
        }
        (_, _) => None,
    }
}

pub fn cmp_hsv(a: &Hsv, b: &Hsv) -> Ordering {
    a.hue
        .to_positive_degrees()
        .partial_cmp(&b.hue.to_positive_degrees())
        .unwrap_or(Ordering::Greater)
}

pub const ARROW_STYLES: &str = tw("text-right mr-2 leading-4 text-4xl flex-1");

/// Annotates tailwindcss utilities to be picked up by editor tooling.
pub const fn tw(class: &str) -> &str {
    class
}
<|endoftext|>


<commit_before><commit_msg>Make low priority transaction support optional.<commit_after><|endoftext|>


<commit_before>/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    // TODO: make this use one of the enums
    /// Type of the data, see the cfitsio documentation
    pub data_type: String,
}

#[derive(Debug, Clone)]
pub struct ColumnDataDescription {
    pub repeat: usize,
    pub width: usize,
    pub typ: ColumnDataType,
}

impl ColumnDataDescription {
    pub fn new(typ: ColumnDataType) -> Self {
        ColumnDataDescription {
            repeat: 1,
            width: 1,
            typ: typ,
        }
    }

    /* XXX These two methods force a call to clone which is wasteful of memory. I do not know if
     * this means that memory is leaked, or that destructors are needlessly called (I suspect the
     * latter) but it is fairly wasteful. On the other hand, it's unlikely this sort of thing will
     * be called in performance-critical code, and is more likely a one-dime definition. I will
     * leave it for now - SRW 2017-03-07
     * */
    pub fn repeats(&mut self, repeat: usize) -> Self {
        // TODO check that repeat >= 1
        self.repeat = repeat;
        self.clone()
    }

    pub fn width(&mut self, width: usize) -> Self {
        // TODO check that width >= 1
        self.width = width;
        self.clone()
    }
}

#[derive(Debug, Clone, Copy)]
pub enum ColumnDataType {
    Int,
}

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

    #[test]
    fn test_column_data_descriptions_builder_pattern() {
        let desc = ColumnDataDescription::new(ColumnDataType::Int)
            .width(100)
            .repeats(5);
        assert_eq!(desc.repeat, 5);
        assert_eq!(desc.width, 100);
    }
}
<commit_msg>Start hooking up From impls<commit_after>/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    // TODO: make this use one of the enums
    /// Type of the data, see the cfitsio documentation
    pub data_type: String,
}

#[derive(Debug, Clone)]
pub struct ColumnDataDescription {
    pub repeat: usize,
    pub width: usize,
    pub typ: ColumnDataType,
}

impl ColumnDataDescription {
    pub fn new(typ: ColumnDataType) -> Self {
        ColumnDataDescription {
            repeat: 1,
            width: 1,
            typ: typ,
        }
    }

    /* XXX These two methods force a call to clone which is wasteful of memory. I do not know if
     * this means that memory is leaked, or that destructors are needlessly called (I suspect the
     * latter) but it is fairly wasteful. On the other hand, it's unlikely this sort of thing will
     * be called in performance-critical code, and is more likely a one-dime definition. I will
     * leave it for now - SRW 2017-03-07
     * */
    pub fn repeats(&mut self, repeat: usize) -> Self {
        // TODO check that repeat >= 1
        self.repeat = repeat;
        self.clone()
    }

    pub fn width(&mut self, width: usize) -> Self {
        // TODO check that width >= 1
        self.width = width;
        self.clone()
    }
}

impl From<ColumnDataDescription> for String {
    fn from(orig: ColumnDataDescription) -> String {
        match orig.typ {
            ColumnDataType::Text => {
                if orig.width > 1 {
                    format!("{repeat}{data_type}{width}",
                            data_type=String::from(orig.typ),
                            repeat=orig.repeat,
                            width=orig.width)
                } else {
                    format!("{repeat}{data_type}",
                            data_type=String::from(orig.typ),
                            repeat=orig.repeat)
                }
            },
            _ => {
                format!("{repeat}{data_type}",
                        data_type=String::from(orig.typ),
                        repeat=orig.repeat)
            },
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum ColumnDataType {
    Int,
    Float,
    Text,
}

impl From<ColumnDataType> for String {
    fn from(orig: ColumnDataType) -> String {
        use self::ColumnDataType::*;

        match orig {
            Int => "J",
            Float => "E",
            Text => "A",
        }.to_string()
    }
}

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

    #[test]
    fn test_column_data_descriptions_builder_pattern() {
        let desc = ColumnDataDescription::new(ColumnDataType::Int)
            .width(100)
            .repeats(5);
        assert_eq!(desc.repeat, 5);
        assert_eq!(desc.width, 100);
    }

    #[test]
    fn from_impls() {
        {
            let desc = ColumnDataDescription::new(ColumnDataType::Int)
                .repeats(5);
            assert_eq!(String::from(desc), "5J");
        }

        {
            let desc = ColumnDataDescription::new(ColumnDataType::Float);
            assert_eq!(String::from(desc), "1E");
        }

        {
            let desc = ColumnDataDescription::new(ColumnDataType::Text)
                .width(100);
            assert_eq!(String::from(desc), "1A100");
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::process::{exit, Command, ExitStatus};
use std::{env, fs, io};

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str) -> String {
        [self.name, "_", project, ".json"].join("")
    }
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the target projects directory");
        exit(1);
    }
    let projects_directory = &args[1];

    // to add a new metric to the test suite, simply define it in this list:
    let metrics: Vec<Metric> = vec![Metric {
        name: "parse",
        prepare: "rm -rf target/",
        cmd: "dbt parse --no-version-check",
    }];

    // list out all projects
    let path = Path::new(&projects_directory);
    let project_entries = fs::read_dir(path).unwrap();

    let results: Result<Vec<ExitStatus>, io::Error> = project_entries
        .map(|entry| {
            metrics
                .clone()
                .into_iter()
                .map(|metric| {
                    let path = entry.as_ref().unwrap().path();
                    let project_name = &path.file_name().and_then(|x| x.to_str()).unwrap();

                    Command::new("hyperfine")
                        .current_dir(&path)
                        // warms filesystem caches by running the command first without counting it.
                        // alternatively we could clear them before each run
                        .arg("--warmup")
                        .arg("1")
                        .arg("--prepare")
                        .arg(metric.prepare)
                        .arg([metric.cmd, " --profiles-dir ", "../../project_config/"].join(""))
                        .arg("--export-json")
                        .arg([&projects_directory, "/", &metric.outfile(project_name)].join(""))
                        // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                        .arg("--show-output")
                        .status() // use spawn() here instead for more information
                })
                .collect::<Vec<Result<ExitStatus, io::Error>>>()
        })
        .flatten()
        .collect();

    // only exit with status code 0 if everything ran as expected
    match results {
        // if dispatch of any of the commands failed, panic with that error
        Err(e) => panic!("{:?}", e),
        Ok(statuses) => {
            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => exit(nonzero),
                }
            }
            // everything ran as expected
            exit(0);
        }
    }
}
<commit_msg>fix results output dir<commit_after>use std::path::Path;
use std::process::{exit, Command, ExitStatus};
use std::{env, fs, io};

#[derive(Debug, Clone)]
struct Metric<'a> {
    name: &'a str,
    prepare: &'a str,
    cmd: &'a str,
}

impl Metric<'_> {
    fn outfile(&self, project: &str) -> String {
        [self.name, "_", project, ".json"].join("")
    }
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the target projects directory");
        exit(1);
    }
    let projects_directory = &args[1];

    // to add a new metric to the test suite, simply define it in this list:
    let metrics: Vec<Metric> = vec![Metric {
        name: "parse",
        prepare: "rm -rf target/",
        cmd: "dbt parse --no-version-check",
    }];

    // list out all projects
    let path = Path::new(&projects_directory);
    let project_entries = fs::read_dir(path).unwrap();

    let results: Result<Vec<ExitStatus>, io::Error> = project_entries
        .map(|entry| {
            metrics
                .clone()
                .into_iter()
                .map(|metric| {
                    let path = entry.as_ref().unwrap().path();
                    let project_name = &path.file_name().and_then(|x| x.to_str()).unwrap();

                    Command::new("hyperfine")
                        .current_dir(&path)
                        // warms filesystem caches by running the command first without counting it.
                        // alternatively we could clear them before each run
                        .arg("--warmup")
                        .arg("1")
                        .arg("--prepare")
                        .arg(metric.prepare)
                        .arg([metric.cmd, " --profiles-dir ", "../../project_config/"].join(""))
                        .arg("--export-json")
                        .arg(["../../results/", &metric.outfile(project_name)].join(""))
                        // this prevents capture dbt output. Noisy, but good for debugging when tests fail.
                        .arg("--show-output")
                        .status() // use spawn() here instead for more information
                })
                .collect::<Vec<Result<ExitStatus, io::Error>>>()
        })
        .flatten()
        .collect();

    // only exit with status code 0 if everything ran as expected
    match results {
        // if dispatch of any of the commands failed, panic with that error
        Err(e) => panic!("{:?}", e),
        Ok(statuses) => {
            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => exit(nonzero),
                }
            }
            // everything ran as expected
            exit(0);
        }
    }
}
<|endoftext|>


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

//! Punycode ([RFC 3492](http://tools.ietf.org/html/rfc3492)) implementation.
//!
//! Since Punycode fundamentally works on unicode code points,
//! `encode` and `decode` take and return slices and vectors of `char`.
//! `encode_str` and `decode_to_string` provide convenience wrappers
//! that convert from and to Rust’s UTF-8 based `str` and `String` types.

use std::char;
use std::u32;

// Bootstring parameters for Punycode
static BASE: u32 = 36;
static T_MIN: u32 = 1;
static T_MAX: u32 = 26;
static SKEW: u32 = 38;
static DAMP: u32 = 700;
static INITIAL_BIAS: u32 = 72;
static INITIAL_N: u32 = 0x80;
static DELIMITER: char = '-';

#[inline]
fn adapt(mut delta: u32, num_points: u32, first_time: bool) -> u32 {
    delta /= if first_time { DAMP } else { 2 };
    delta += delta / num_points;
    let mut k = 0;
    while delta > ((BASE - T_MIN) * T_MAX) / 2 {
        delta /= BASE - T_MIN;
        k += BASE;
    }
    k + (((BASE - T_MIN + 1) * delta) / (delta + SKEW))
}

/// Convert Punycode to an Unicode `String`.
///
/// This is a convenience wrapper around `decode`.
#[inline]
pub fn decode_to_string(input: &str) -> Option<String> {
    decode(input).map(|chars| chars.into_iter().collect())
}

/// Convert Punycode to Unicode.
///
/// Return None on malformed input or overflow.
/// Overflow can only happen on inputs that take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn decode(input: &str) -> Option<Vec<char>> {
    // Handle "basic" (ASCII) code points.
    // They are encoded as-is before the last delimiter, if any.
    let (mut output, input) = match input.rfind(DELIMITER) {
        None => (Vec::new(), input),
        Some(position) => (
            input[..position].chars().collect(),
            if position > 0 {
                &input[position + 1..]
            } else {
                input
            },
        ),
    };
    let mut code_point = INITIAL_N;
    let mut bias = INITIAL_BIAS;
    let mut i = 0;
    let mut iter = input.bytes();
    loop {
        let previous_i = i;
        let mut weight = 1;
        let mut k = BASE;
        let mut byte = match iter.next() {
            None => break,
            Some(byte) => byte,
        };
        // Decode a generalized variable-length integer into delta,
        // which gets added to i.
        loop {
            let digit = match byte {
                byte @ b'0'..=b'9' => byte - b'0' + 26,
                byte @ b'A'..=b'Z' => byte - b'A',
                byte @ b'a'..=b'z' => byte - b'a',
                _ => return None,
            } as u32;
            if digit > (u32::MAX - i) / weight {
                return None; // Overflow
            }
            i += digit * weight;
            let t = if k <= bias {
                T_MIN
            } else if k >= bias + T_MAX {
                T_MAX
            } else {
                k - bias
            };
            if digit < t {
                break;
            }
            if weight > u32::MAX / (BASE - t) {
                return None; // Overflow
            }
            weight *= BASE - t;
            k += BASE;
            byte = match iter.next() {
                None => return None, // End of input before the end of this delta
                Some(byte) => byte,
            };
        }
        let length = output.len() as u32;
        bias = adapt(i - previous_i, length + 1, previous_i == 0);
        if i / (length + 1) > u32::MAX - code_point {
            return None; // Overflow
        }
        // i was supposed to wrap around from length+1 to 0,
        // incrementing code_point each time.
        code_point += i / (length + 1);
        i %= length + 1;
        let c = match char::from_u32(code_point) {
            Some(c) => c,
            None => return None,
        };
        output.insert(i as usize, c);
        i += 1;
    }
    Some(output)
}

/// Convert an Unicode `str` to Punycode.
///
/// This is a convenience wrapper around `encode`.
#[inline]
pub fn encode_str(input: &str) -> Option<String> {
    encode(&input.chars().collect::<Vec<char>>())
}

/// Convert Unicode to Punycode.
///
/// Return None on overflow, which can only happen on inputs that would take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn encode(input: &[char]) -> Option<String> {
    // Handle "basic" (ASCII) code points. They are encoded as-is.
    let mut output = input.iter().filter(|&c| c.is_ascii()).collect::<String>();
    let basic_length = output.len() as u32;
    if basic_length > 0 {
        output.push_str("-")
    }
    let mut code_point = INITIAL_N;
    let mut delta = 0;
    let mut bias = INITIAL_BIAS;
    let mut processed = basic_length;
    let input_length = input.len() as u32;
    while processed < input_length {
        // All code points < code_point have been handled already.
        // Find the next larger one.
        let min_code_point = input
            .iter()
            .map(|&c| c as u32)
            .filter(|&c| c >= code_point)
            .min()
            .unwrap();
        if min_code_point - code_point > (u32::MAX - delta) / (processed + 1) {
            return None; // Overflow
        }
        // Increase delta to advance the decoder’s <code_point,i> state to <min_code_point,0>
        delta += (min_code_point - code_point) * (processed + 1);
        code_point = min_code_point;
        for &c in input {
            let c = c as u32;
            if c < code_point {
                delta += 1;
                if delta == 0 {
                    return None; // Overflow
                }
            }
            if c == code_point {
                // Represent delta as a generalized variable-length integer:
                let mut q = delta;
                let mut k = BASE;
                loop {
                    let t = if k <= bias {
                        T_MIN
                    } else if k >= bias + T_MAX {
                        T_MAX
                    } else {
                        k - bias
                    };
                    if q < t {
                        break;
                    }
                    let value = t + ((q - t) % (BASE - t));
                    output.push(value_to_digit(value));
                    q = (q - t) / (BASE - t);
                    k += BASE;
                }
                output.push(value_to_digit(q));
                bias = adapt(delta, processed + 1, processed == basic_length);
                delta = 0;
                processed += 1;
            }
        }
        delta += 1;
        code_point += 1;
    }
    Some(output)
}

#[inline]
fn value_to_digit(value: u32) -> char {
    match value {
        0..=25 => (value as u8 + b'a') as char,       // a..z
        26..=35 => (value as u8 - 26 + b'0') as char, // 0..9
        _ => panic!(),
    }
}
<commit_msg>idna: prevent allocations in punycode encoding (fixes #561)<commit_after>// Copyright 2013 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Punycode ([RFC 3492](http://tools.ietf.org/html/rfc3492)) implementation.
//!
//! Since Punycode fundamentally works on unicode code points,
//! `encode` and `decode` take and return slices and vectors of `char`.
//! `encode_str` and `decode_to_string` provide convenience wrappers
//! that convert from and to Rust’s UTF-8 based `str` and `String` types.

use std::char;
use std::u32;

// Bootstring parameters for Punycode
static BASE: u32 = 36;
static T_MIN: u32 = 1;
static T_MAX: u32 = 26;
static SKEW: u32 = 38;
static DAMP: u32 = 700;
static INITIAL_BIAS: u32 = 72;
static INITIAL_N: u32 = 0x80;
static DELIMITER: char = '-';

#[inline]
fn adapt(mut delta: u32, num_points: u32, first_time: bool) -> u32 {
    delta /= if first_time { DAMP } else { 2 };
    delta += delta / num_points;
    let mut k = 0;
    while delta > ((BASE - T_MIN) * T_MAX) / 2 {
        delta /= BASE - T_MIN;
        k += BASE;
    }
    k + (((BASE - T_MIN + 1) * delta) / (delta + SKEW))
}

/// Convert Punycode to an Unicode `String`.
///
/// This is a convenience wrapper around `decode`.
#[inline]
pub fn decode_to_string(input: &str) -> Option<String> {
    decode(input).map(|chars| chars.into_iter().collect())
}

/// Convert Punycode to Unicode.
///
/// Return None on malformed input or overflow.
/// Overflow can only happen on inputs that take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn decode(input: &str) -> Option<Vec<char>> {
    // Handle "basic" (ASCII) code points.
    // They are encoded as-is before the last delimiter, if any.
    let (mut output, input) = match input.rfind(DELIMITER) {
        None => (Vec::new(), input),
        Some(position) => (
            input[..position].chars().collect(),
            if position > 0 {
                &input[position + 1..]
            } else {
                input
            },
        ),
    };
    let mut code_point = INITIAL_N;
    let mut bias = INITIAL_BIAS;
    let mut i = 0;
    let mut iter = input.bytes();
    loop {
        let previous_i = i;
        let mut weight = 1;
        let mut k = BASE;
        let mut byte = match iter.next() {
            None => break,
            Some(byte) => byte,
        };
        // Decode a generalized variable-length integer into delta,
        // which gets added to i.
        loop {
            let digit = match byte {
                byte @ b'0'..=b'9' => byte - b'0' + 26,
                byte @ b'A'..=b'Z' => byte - b'A',
                byte @ b'a'..=b'z' => byte - b'a',
                _ => return None,
            } as u32;
            if digit > (u32::MAX - i) / weight {
                return None; // Overflow
            }
            i += digit * weight;
            let t = if k <= bias {
                T_MIN
            } else if k >= bias + T_MAX {
                T_MAX
            } else {
                k - bias
            };
            if digit < t {
                break;
            }
            if weight > u32::MAX / (BASE - t) {
                return None; // Overflow
            }
            weight *= BASE - t;
            k += BASE;
            byte = match iter.next() {
                None => return None, // End of input before the end of this delta
                Some(byte) => byte,
            };
        }
        let length = output.len() as u32;
        bias = adapt(i - previous_i, length + 1, previous_i == 0);
        if i / (length + 1) > u32::MAX - code_point {
            return None; // Overflow
        }
        // i was supposed to wrap around from length+1 to 0,
        // incrementing code_point each time.
        code_point += i / (length + 1);
        i %= length + 1;
        let c = match char::from_u32(code_point) {
            Some(c) => c,
            None => return None,
        };
        output.insert(i as usize, c);
        i += 1;
    }
    Some(output)
}

/// Convert an Unicode `str` to Punycode.
///
/// This is a convenience wrapper around `encode`.
#[inline]
pub fn encode_str(input: &str) -> Option<String> {
    let mut buf = String::with_capacity(input.len());
    encode_into(input.chars(), &mut buf).ok().map(|()| buf)
}

/// Convert Unicode to Punycode.
///
/// Return None on overflow, which can only happen on inputs that would take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn encode(input: &[char]) -> Option<String> {
    let mut buf = String::with_capacity(input.len());
    encode_into(input.iter().copied(), &mut buf)
        .ok()
        .map(|()| buf)
}

fn encode_into<I>(input: I, output: &mut String) -> Result<(), ()>
where
    I: Iterator<Item = char> + Clone,
{
    // Handle "basic" (ASCII) code points. They are encoded as-is.
    let (mut input_length, mut basic_length) = (0, 0);
    for c in input.clone() {
        input_length += 1;
        if c.is_ascii() {
            output.push(c);
            basic_length += 1;
        }
    }

    if basic_length > 0 {
        output.push_str("-")
    }
    let mut code_point = INITIAL_N;
    let mut delta = 0;
    let mut bias = INITIAL_BIAS;
    let mut processed = basic_length;
    while processed < input_length {
        // All code points < code_point have been handled already.
        // Find the next larger one.
        let min_code_point = input
            .clone()
            .map(|c| c as u32)
            .filter(|&c| c >= code_point)
            .min()
            .unwrap();
        if min_code_point - code_point > (u32::MAX - delta) / (processed + 1) {
            return Err(()); // Overflow
        }
        // Increase delta to advance the decoder’s <code_point,i> state to <min_code_point,0>
        delta += (min_code_point - code_point) * (processed + 1);
        code_point = min_code_point;
        for c in input.clone() {
            let c = c as u32;
            if c < code_point {
                delta += 1;
                if delta == 0 {
                    return Err(()); // Overflow
                }
            }
            if c == code_point {
                // Represent delta as a generalized variable-length integer:
                let mut q = delta;
                let mut k = BASE;
                loop {
                    let t = if k <= bias {
                        T_MIN
                    } else if k >= bias + T_MAX {
                        T_MAX
                    } else {
                        k - bias
                    };
                    if q < t {
                        break;
                    }
                    let value = t + ((q - t) % (BASE - t));
                    output.push(value_to_digit(value));
                    q = (q - t) / (BASE - t);
                    k += BASE;
                }
                output.push(value_to_digit(q));
                bias = adapt(delta, processed + 1, processed == basic_length);
                delta = 0;
                processed += 1;
            }
        }
        delta += 1;
        code_point += 1;
    }
    Ok(())
}

#[inline]
fn value_to_digit(value: u32) -> char {
    match value {
        0..=25 => (value as u8 + b'a') as char,       // a..z
        26..=35 => (value as u8 - 26 + b'0') as char, // 0..9
        _ => panic!(),
    }
}
<|endoftext|>


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

use std::net::SocketAddr;
use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::io;

use chain::{self, ChainAdapter};
use core::core::{self, Output};
use core::core::hash::{Hash, Hashed};
use core::core::target::Difficulty;
use p2p::{self, NetAdapter, Server, PeerStore, PeerData, Capabilities, State};
use pool;
use secp::pedersen::Commitment;
use util::OneTime;
use store;
use sync;

/// Implementation of the NetAdapter for the blockchain. Gets notified when new
/// blocks and transactions are received and forwards to the chain and pool
/// implementations.
pub struct NetToChainAdapter {
	test_mode: bool,
	chain: Arc<chain::Chain>,
	peer_store: Arc<PeerStore>,
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,

	syncer: OneTime<Arc<sync::Syncer>>,
}

impl NetAdapter for NetToChainAdapter {
	fn total_difficulty(&self) -> Difficulty {
		self.chain.total_difficulty()
	}

	fn transaction_received(&self, tx: core::Transaction) -> Result<(), p2p::Error> {
		let source = pool::TxSource {
			debug_name: "p2p".to_string(),
			identifier: "?.?.?.?".to_string(),
		};
		if let Err(e) = self.tx_pool.write().unwrap().add_to_memory_pool(source, tx) {
			error!("Transaction rejected: {:?}", e);
			return Err(p2p::Error::Invalid);
		}
		Ok(())
	}

	fn block_received(&self, b: core::Block) -> Result<(), p2p::Error> {

    let bhash = b.hash();
		debug!("Received block {} from network, going to process.", bhash);

		// pushing the new block through the chain pipeline
		let res = self.chain.process_block(b, self.chain_opts());

		if let Err(e) = res {
			debug!("Block {} refused by chain: {:?}", b.hash(), e);
			return Err(p2p::Error::Invalid);
		}

		if self.syncer.borrow().syncing() {
			self.syncer.borrow().block_received(bhash);
		}

		Ok(())
	}

	fn headers_received(&self, bhs: Vec<core::BlockHeader>) -> Result<(), p2p::Error> {
		// try to add each header to our header chain
		let mut added_hs = vec![];
		for bh in bhs {
			let res = self.chain.process_block_header(&bh, self.chain_opts());
			match res {
				Ok(_) => {
					added_hs.push(bh.hash());
				}
				Err(chain::Error::Unfit(s)) => {
					info!("Received unfit block header {} at {}: {}.",
					      bh.hash(),
					      bh.height,
					      s);
					return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid Time").into());
				}
				Err(chain::Error::StoreErr(e)) => {
					error!("Store error processing block header {}: {:?}", bh.hash(), e);
					return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid Header Format").into());
				}
				Err(e) => {
					info!("Invalid block header {}: {:?}.", bh.hash(), e);
					return Err(p2p::Error::Invalid);
				}
			}
		}
		info!("Added {} headers to the header chain.", added_hs.len());

		if self.syncer.borrow().syncing() {
			self.syncer.borrow().headers_received(added_hs);
		}
		Ok(())
	}

	fn locate_headers(&self, locator: Vec<Hash>) -> Option<Vec<core::BlockHeader>> {
		if locator.len() == 0 {
			return None;
		}

		// go through the locator vector and check if we know any of these headers
		let known = self.chain.get_block_header(&locator[0]);
		let header = match known {
			Ok(header) => header,
			Err(chain::Error::StoreErr(store::Error::NotFoundErr)) => {
				return self.locate_headers(locator[1..].to_vec());
			}
			Err(e) => {
				error!("Could not build header locator: {:?}", e);
				return None;
			}
		};

		// looks like we know one, getting as many following headers as allowed
		let hh = header.height;
		let mut headers = vec![];
		for h in (hh + 1)..(hh + (p2p::MAX_BLOCK_HEADERS as u64)) {
			let header = self.chain.get_header_by_height(h);
			match header {
				Ok(head) => headers.push(head),
				Err(chain::Error::StoreErr(store::Error::NotFoundErr)) => break,
				Err(e) => {
					error!("Could not build header locator: {:?}", e);
					return None;
				}
			}
		}
		Some(headers)
	}

	/// Gets a full block by its hash.
	fn get_block(&self, h: Hash) -> Option<core::Block> {
		let b = self.chain.get_block(&h);
		match b {
			Ok(b) => Some(b),
			_ => None,
		}
	}

	/// Find good peers we know with the provided capability and return their
	/// addresses.
	fn find_peer_addrs(&self, capab: p2p::Capabilities) -> Option<Vec<SocketAddr>> {
		let peers = self.peer_store.find_peers(State::Healthy, capab, p2p::MAX_PEER_ADDRS as usize);
		debug!("Got {} peer addrs to send.", peers.len());
		if peers.len() == 0 { None } else { Some(map_vec!(peers, |p| p.addr)) }

	}

	/// A list of peers has been received from one of our peers.
	fn peer_addrs_received(&self, peer_addrs: Vec<SocketAddr>) -> Result<(), p2p::Error> {
		debug!("Received {} peer addrs, saving.", peer_addrs.len());
		for pa in peer_addrs {
			if let Ok(e) = self.peer_store.exists_peer(pa) {
				if e {
					continue;
				}
			}
			let peer = PeerData {
				addr: pa,
				capabilities: p2p::UNKNOWN,
				user_agent: "".to_string(),
				flags: State::Healthy,
			};
			if let Err(e) = self.peer_store.save_peer(&peer) {
				error!("Could not save received peer address: {:?}", e);
				return Err(io::Error::new(io::ErrorKind::InvalidData, "Could not save recieved peer address").into())
			}
		}

		Ok(())
	}

	/// Network successfully connected to a peer.
	fn peer_connected(&self, pi: &p2p::PeerInfo) {
		debug!("Saving newly connected peer {}.", pi.addr);
		let peer = PeerData {
			addr: pi.addr,
			capabilities: pi.capabilities,
			user_agent: pi.user_agent.clone(),
			flags: State::Healthy,
		};
		if let Err(e) = self.peer_store.save_peer(&peer) {
			error!("Could not save connected peer: {:?}", e);
		}
	}
}

impl NetToChainAdapter {
	pub fn new(test_mode: bool,
	           chain_ref: Arc<chain::Chain>,
	           tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	           peer_store: Arc<PeerStore>)
	           -> NetToChainAdapter {
		NetToChainAdapter {
			test_mode: test_mode,
			chain: chain_ref,
			peer_store: peer_store,
			tx_pool: tx_pool,
			syncer: OneTime::new(),
		}
	}

	/// Start syncing the chain by instantiating and running the Syncer in the
	/// background (a new thread is created).
	pub fn start_sync(&self, sync: sync::Syncer) {
		let arc_sync = Arc::new(sync);
		self.syncer.init(arc_sync.clone());
		thread::Builder::new().name("syncer".to_string()).spawn(move || {
			arc_sync.run();
		});
	}

	/// Prepare options for the chain pipeline
	fn chain_opts(&self) -> chain::Options {
		let mut opts = if self.syncer.borrow().syncing() {
			chain::SYNC
		} else {
			chain::NONE
		};
		if self.test_mode {
			opts = opts | chain::EASY_POW;
		}
		opts
	}
}

/// Implementation of the ChainAdapter for the network. Gets notified when the
/// blockchain accepted a new block, asking the pool to update its state and
/// the network to broadcast the block
pub struct ChainToPoolAndNetAdapter {
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	p2p: OneTime<Arc<Server>>,
}

impl ChainAdapter for ChainToPoolAndNetAdapter {
	fn block_accepted(&self, b: &core::Block) {
		{
			if let Err(e) = self.tx_pool.write().unwrap().reconcile_block(b) {
				error!("Pool could not update itself at block {}: {:?}",
				       b.hash(),
				       e);
			}
		}
		self.p2p.borrow().broadcast_block(b);
	}
}

impl ChainToPoolAndNetAdapter {
	pub fn new(tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>)
	           -> ChainToPoolAndNetAdapter {
		ChainToPoolAndNetAdapter {
			tx_pool: tx_pool,
			p2p: OneTime::new(),
		}
	}
	pub fn init(&self, p2p: Arc<Server>) {
		self.p2p.init(p2p);
	}
}

/// Implements the view of the blockchain required by the TransactionPool to
/// operate. Mostly needed to break any direct lifecycle or implementation
/// dependency between the pool and the chain.
#[derive(Clone)]
pub struct PoolToChainAdapter {
	chain: OneTime<Arc<chain::Chain>>,
}

impl PoolToChainAdapter {
	/// Create a new pool adapter
	pub fn new() -> PoolToChainAdapter {
		PoolToChainAdapter { chain: OneTime::new() }
	}

	pub fn set_chain(&self, chain_ref: Arc<chain::Chain>) {
		self.chain.init(chain_ref);
	}
}

impl pool::BlockChain for PoolToChainAdapter {
	fn get_unspent(&self, output_ref: &Commitment) -> Option<Output> {
		self.chain.borrow().get_unspent(output_ref)
	}
}
<commit_msg>Try Fix<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::SocketAddr;
use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::io;

use chain::{self, ChainAdapter};
use core::core::{self, Output};
use core::core::hash::{Hash, Hashed};
use core::core::target::Difficulty;
use p2p::{self, NetAdapter, Server, PeerStore, PeerData, Capabilities, State};
use pool;
use secp::pedersen::Commitment;
use util::OneTime;
use store;
use sync;

/// Implementation of the NetAdapter for the blockchain. Gets notified when new
/// blocks and transactions are received and forwards to the chain and pool
/// implementations.
pub struct NetToChainAdapter {
	test_mode: bool,
	chain: Arc<chain::Chain>,
	peer_store: Arc<PeerStore>,
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,

	syncer: OneTime<Arc<sync::Syncer>>,
}

impl NetAdapter for NetToChainAdapter {
	fn total_difficulty(&self) -> Difficulty {
		self.chain.total_difficulty()
	}

	fn transaction_received(&self, tx: core::Transaction) -> Result<(), p2p::Error> {
		let source = pool::TxSource {
			debug_name: "p2p".to_string(),
			identifier: "?.?.?.?".to_string(),
		};
		if let Err(e) = self.tx_pool.write().unwrap().add_to_memory_pool(source, tx) {
			error!("Transaction rejected: {:?}", e);
			return Err(p2p::Error::Invalid);
		}
		Ok(())
	}

	fn block_received(&self, b: core::Block) -> Result<(), p2p::Error> {

    	let bhash = b.hash();

		debug!("Received block {} from network, going to process.", bhash);

		// pushing the new block through the chain pipeline
		let res = self.chain.process_block(b, self.chain_opts());

		if let Err(e) = res {
			debug!("Block {} refused by chain: {:?}", bhash, e);
			return Err(p2p::Error::Invalid);
		}

		if self.syncer.borrow().syncing() {
			self.syncer.borrow().block_received(bhash);
		}

		Ok(())
	}

	fn headers_received(&self, bhs: Vec<core::BlockHeader>) -> Result<(), p2p::Error> {
		// try to add each header to our header chain
		let mut added_hs = vec![];
		for bh in bhs {
			let res = self.chain.process_block_header(&bh, self.chain_opts());
			match res {
				Ok(_) => {
					added_hs.push(bh.hash());
				}
				Err(chain::Error::Unfit(s)) => {
					info!("Received unfit block header {} at {}: {}.",
					      bh.hash(),
					      bh.height,
					      s);
					return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid Time").into());
				}
				Err(chain::Error::StoreErr(e)) => {
					error!("Store error processing block header {}: {:?}", bh.hash(), e);
					return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid Header Format").into());
				}
				Err(e) => {
					info!("Invalid block header {}: {:?}.", bh.hash(), e);
					return Err(p2p::Error::Invalid);
				}
			}
		}
		info!("Added {} headers to the header chain.", added_hs.len());

		if self.syncer.borrow().syncing() {
			self.syncer.borrow().headers_received(added_hs);
		}
		Ok(())
	}

	fn locate_headers(&self, locator: Vec<Hash>) -> Option<Vec<core::BlockHeader>> {
		if locator.len() == 0 {
			return None;
		}

		// go through the locator vector and check if we know any of these headers
		let known = self.chain.get_block_header(&locator[0]);
		let header = match known {
			Ok(header) => header,
			Err(chain::Error::StoreErr(store::Error::NotFoundErr)) => {
				return self.locate_headers(locator[1..].to_vec());
			}
			Err(e) => {
				error!("Could not build header locator: {:?}", e);
				return None;
			}
		};

		// looks like we know one, getting as many following headers as allowed
		let hh = header.height;
		let mut headers = vec![];
		for h in (hh + 1)..(hh + (p2p::MAX_BLOCK_HEADERS as u64)) {
			let header = self.chain.get_header_by_height(h);
			match header {
				Ok(head) => headers.push(head),
				Err(chain::Error::StoreErr(store::Error::NotFoundErr)) => break,
				Err(e) => {
					error!("Could not build header locator: {:?}", e);
					return None;
				}
			}
		}
		Some(headers)
	}

	/// Gets a full block by its hash.
	fn get_block(&self, h: Hash) -> Option<core::Block> {
		let b = self.chain.get_block(&h);
		match b {
			Ok(b) => Some(b),
			_ => None,
		}
	}

	/// Find good peers we know with the provided capability and return their
	/// addresses.
	fn find_peer_addrs(&self, capab: p2p::Capabilities) -> Option<Vec<SocketAddr>> {
		let peers = self.peer_store.find_peers(State::Healthy, capab, p2p::MAX_PEER_ADDRS as usize);
		debug!("Got {} peer addrs to send.", peers.len());
		if peers.len() == 0 { None } else { Some(map_vec!(peers, |p| p.addr)) }

	}

	/// A list of peers has been received from one of our peers.
	fn peer_addrs_received(&self, peer_addrs: Vec<SocketAddr>) -> Result<(), p2p::Error> {
		debug!("Received {} peer addrs, saving.", peer_addrs.len());
		for pa in peer_addrs {
			if let Ok(e) = self.peer_store.exists_peer(pa) {
				if e {
					continue;
				}
			}
			let peer = PeerData {
				addr: pa,
				capabilities: p2p::UNKNOWN,
				user_agent: "".to_string(),
				flags: State::Healthy,
			};
			if let Err(e) = self.peer_store.save_peer(&peer) {
				error!("Could not save received peer address: {:?}", e);
				return Err(io::Error::new(io::ErrorKind::InvalidData, "Could not save recieved peer address").into())
			}
		}

		Ok(())
	}

	/// Network successfully connected to a peer.
	fn peer_connected(&self, pi: &p2p::PeerInfo) {
		debug!("Saving newly connected peer {}.", pi.addr);
		let peer = PeerData {
			addr: pi.addr,
			capabilities: pi.capabilities,
			user_agent: pi.user_agent.clone(),
			flags: State::Healthy,
		};
		if let Err(e) = self.peer_store.save_peer(&peer) {
			error!("Could not save connected peer: {:?}", e);
		}
	}
}

impl NetToChainAdapter {
	pub fn new(test_mode: bool,
	           chain_ref: Arc<chain::Chain>,
	           tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	           peer_store: Arc<PeerStore>)
	           -> NetToChainAdapter {
		NetToChainAdapter {
			test_mode: test_mode,
			chain: chain_ref,
			peer_store: peer_store,
			tx_pool: tx_pool,
			syncer: OneTime::new(),
		}
	}

	/// Start syncing the chain by instantiating and running the Syncer in the
	/// background (a new thread is created).
	pub fn start_sync(&self, sync: sync::Syncer) {
		let arc_sync = Arc::new(sync);
		self.syncer.init(arc_sync.clone());
		thread::Builder::new().name("syncer".to_string()).spawn(move || {
			arc_sync.run();
		});
	}

	/// Prepare options for the chain pipeline
	fn chain_opts(&self) -> chain::Options {
		let mut opts = if self.syncer.borrow().syncing() {
			chain::SYNC
		} else {
			chain::NONE
		};
		if self.test_mode {
			opts = opts | chain::EASY_POW;
		}
		opts
	}
}

/// Implementation of the ChainAdapter for the network. Gets notified when the
/// blockchain accepted a new block, asking the pool to update its state and
/// the network to broadcast the block
pub struct ChainToPoolAndNetAdapter {
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	p2p: OneTime<Arc<Server>>,
}

impl ChainAdapter for ChainToPoolAndNetAdapter {
	fn block_accepted(&self, b: &core::Block) {
		{
			if let Err(e) = self.tx_pool.write().unwrap().reconcile_block(b) {
				error!("Pool could not update itself at block {}: {:?}",
				       b.hash(),
				       e);
			}
		}
		self.p2p.borrow().broadcast_block(b);
	}
}

impl ChainToPoolAndNetAdapter {
	pub fn new(tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>)
	           -> ChainToPoolAndNetAdapter {
		ChainToPoolAndNetAdapter {
			tx_pool: tx_pool,
			p2p: OneTime::new(),
		}
	}
	pub fn init(&self, p2p: Arc<Server>) {
		self.p2p.init(p2p);
	}
}

/// Implements the view of the blockchain required by the TransactionPool to
/// operate. Mostly needed to break any direct lifecycle or implementation
/// dependency between the pool and the chain.
#[derive(Clone)]
pub struct PoolToChainAdapter {
	chain: OneTime<Arc<chain::Chain>>,
}

impl PoolToChainAdapter {
	/// Create a new pool adapter
	pub fn new() -> PoolToChainAdapter {
		PoolToChainAdapter { chain: OneTime::new() }
	}

	pub fn set_chain(&self, chain_ref: Arc<chain::Chain>) {
		self.chain.init(chain_ref);
	}
}

impl pool::BlockChain for PoolToChainAdapter {
	fn get_unspent(&self, output_ref: &Commitment) -> Option<Output> {
		self.chain.borrow().get_unspent(output_ref)
	}
}
<|endoftext|>


<commit_before>use self::Decode::{V, C};

static VS: [char; 5] = ['a', 'e', 'i', 'o', 'u'];
static CS: [char; 14] = ['b', 'd', 'f', 'g', 'j', 'k', 'm', 'n',
    'p', 'r', 's', 't', 'v', 'z'];

#[derive(Copy)]
enum Decode {
    V(u16),
    C(u16),
}

static LUT: [Option<Decode>; 26] = [
    Some(V(0)),  // a (ASCII 97)
    Some(C(0)),  // b
    None,        // c
    Some(C(1)),  // d
    Some(V(1)),  // e
    Some(C(2)),  // f
    Some(C(3)),  // g
    None,        // h
    Some(V(2)),  // i
    Some(C(4)),  // j
    Some(C(5)),  // k
    None,        // l
    Some(C(6)),  // m
    Some(C(7)),  // n
    Some(V(3)),  // o
    Some(C(8)),  // p
    None,        // q
    Some(C(9)),  // r
    Some(C(10)), // s
    Some(C(11)), // t
    Some(V(4)),  // u
    Some(C(12)), // v
    None,        // w
    None,        // x
    None,        // y
    Some(C(13)), // z
];

fn vorud_chunk(data: u16) -> String {
    let (data, c5) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v4) = (data / VS.len() as u16, data % VS.len() as u16);
    let (data, c3) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v2) = (data / VS.len() as u16, data % VS.len() as u16);
    let (_, c1) =    (data / CS.len() as u16, data % CS.len() as u16);
    [CS[c1 as usize],
     VS[v2 as usize],
     CS[c3 as usize],
     VS[v4 as usize],
     CS[c5 as usize],
    ].iter().map(|&x| x).collect()
}

fn decode(c: char) -> Option<Decode> {
    let idx = c as isize - 97;
    if idx < 0 || idx >= LUT.len() as isize { return None; }
    LUT[idx as usize]
}

fn v(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(V(i)) => Ok(i),
        _ => Err(())
    }
}

fn c(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(C(i)) => Ok(i),
        _ => Err(())
    }
}

fn durov_chunk(s: &str) -> Result<u16, ()> {
    if s.len() != 5 { return Err(()); }
    let s: Vec<char> = s.chars().collect();
    let (mut ret, mut n) = (0u16, 1u16);
    ret += try!(c(s[4])) * n; n *= CS.len() as u16;
    ret += try!(v(s[3])) * n; n *= VS.len() as u16;
    ret += try!(c(s[2])) * n; n *= CS.len() as u16;
    ret += try!(v(s[1])) * n; n *= VS.len() as u16;
    ret += try!(c(s[0])) * n;

    Ok(ret)
}

#[derive(PartialEq, Eq, Debug)]
pub struct Vorud(String);

impl Vorud {
    pub fn new(s: String) -> Result<Vorud, ()> {
        if s.len() == 0 { return Ok(Vorud("".to_string())); }
        let ch = &s[].chars().collect::<Vec<char>>();
        let mut i = 0;
        loop {
            if i > ch.len() - 5 { return Err(()); }
            try!(c(ch[i]));
            try!(v(ch[i + 1]));
            try!(c(ch[i + 2]));
            try!(v(ch[i + 3]));
            try!(c(ch[i + 4]));
            if i == ch.len() - 5 { return Ok(Vorud(s)); }
            if ch[i + 5] != '-' { return Err(()); }
            i += 6;
        }
    }
}

pub trait FromVorud<E> {
    fn from_vorud(v: &Vorud) -> Result<Self, E>;
}

pub trait ToVorud {
    fn to_vorud(&self) -> Vorud;
}

impl<'a> ToVorud for &'a [u8] {
    fn to_vorud(&self) -> Vorud {
        let mut ret = String::new();
        for i in 0..(self.len() / 2) {
            if ret.len() > 0 { ret.push_str("-"); }
            let b0 = self[i * 2] as u16;
            let b1 = if self.len() == i * 2 + 1 { 0 } else { self[i * 2 + 1] as u16 };
            ret.push_str(&vorud_chunk(b1 + (b0 << 8))[]);
        }
        Vorud(ret)
    }
}

impl FromVorud<()> for Vec<u8> {
    fn from_vorud(&Vorud(ref s): &Vorud) -> Result<Vec<u8>, ()> {
        let mut ret = Vec::new();
        for chunk in (&s[]).split('-') {
            let x = try!(durov_chunk(chunk));
            ret.push((x / 0xff) as u8);
            ret.push((x % 0xff) as u8);
        }
        Ok(ret)
    }
}

impl ToVorud for u32 {
    fn to_vorud(&self) -> Vorud {
        let mut vec = Vec::new();
        vec.push(((*self >> 24) % 0xff) as u8);
        vec.push(((*self >> 16) % 0xff) as u8);
        vec.push(((*self >> 8) % 0xff) as u8);
        vec.push((*self % 0xff) as u8);
        (&vec[]).to_vorud()
    }
}

impl FromVorud<()> for u32 {
    fn from_vorud(v: &Vorud) -> Result<u32, ()> {
        let v: Vec<u8> = try!(FromVorud::from_vorud(v));
        if v.len() != 4 { return Err(()); }
        Ok(v[3] as u32 +
            ((v[2] as u32) << 8) +
            ((v[1] as u32) << 16) +
            ((v[0] as u32) << 24))
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_vorud() {
        use super::ToVorud;

        assert_eq!("babab", &super::vorud_chunk(0)[]);
        assert_eq!("babad", &super::vorud_chunk(1)[]);
        assert_eq!(Ok(0u16), super::durov_chunk("babab"));
        assert_eq!(Ok(1234u16), &super::durov_chunk(super::vorud_chunk(1234)[]));
        assert_eq!("togas", &super::vorud_chunk(super::durov_chunk("togas").unwrap())[]);
        assert_eq!(super::Vorud("babab-babab".to_string()), 0u32.to_vorud());
        assert_eq!(super::Vorud("babab-babad".to_string()), 1u32.to_vorud());
        assert_eq!(Ok(1u32), super::FromVorud::from_vorud(&super::Vorud("babab-babad".to_string())));
    }
}
<commit_msg>Fix unit test<commit_after>use self::Decode::{V, C};

static VS: [char; 5] = ['a', 'e', 'i', 'o', 'u'];
static CS: [char; 14] = ['b', 'd', 'f', 'g', 'j', 'k', 'm', 'n',
    'p', 'r', 's', 't', 'v', 'z'];

#[derive(Copy)]
enum Decode {
    V(u16),
    C(u16),
}

static LUT: [Option<Decode>; 26] = [
    Some(V(0)),  // a (ASCII 97)
    Some(C(0)),  // b
    None,        // c
    Some(C(1)),  // d
    Some(V(1)),  // e
    Some(C(2)),  // f
    Some(C(3)),  // g
    None,        // h
    Some(V(2)),  // i
    Some(C(4)),  // j
    Some(C(5)),  // k
    None,        // l
    Some(C(6)),  // m
    Some(C(7)),  // n
    Some(V(3)),  // o
    Some(C(8)),  // p
    None,        // q
    Some(C(9)),  // r
    Some(C(10)), // s
    Some(C(11)), // t
    Some(V(4)),  // u
    Some(C(12)), // v
    None,        // w
    None,        // x
    None,        // y
    Some(C(13)), // z
];

fn vorud_chunk(data: u16) -> String {
    let (data, c5) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v4) = (data / VS.len() as u16, data % VS.len() as u16);
    let (data, c3) = (data / CS.len() as u16, data % CS.len() as u16);
    let (data, v2) = (data / VS.len() as u16, data % VS.len() as u16);
    let (_, c1) =    (data / CS.len() as u16, data % CS.len() as u16);
    [CS[c1 as usize],
     VS[v2 as usize],
     CS[c3 as usize],
     VS[v4 as usize],
     CS[c5 as usize],
    ].iter().map(|&x| x).collect()
}

fn decode(c: char) -> Option<Decode> {
    let idx = c as isize - 97;
    if idx < 0 || idx >= LUT.len() as isize { return None; }
    LUT[idx as usize]
}

fn v(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(V(i)) => Ok(i),
        _ => Err(())
    }
}

fn c(c: char) -> Result<u16, ()> {
    match decode(c) {
        Some(C(i)) => Ok(i),
        _ => Err(())
    }
}

fn durov_chunk(s: &str) -> Result<u16, ()> {
    if s.len() != 5 { return Err(()); }
    let s: Vec<char> = s.chars().collect();
    let (mut ret, mut n) = (0u16, 1u16);
    ret += try!(c(s[4])) * n; n *= CS.len() as u16;
    ret += try!(v(s[3])) * n; n *= VS.len() as u16;
    ret += try!(c(s[2])) * n; n *= CS.len() as u16;
    ret += try!(v(s[1])) * n; n *= VS.len() as u16;
    ret += try!(c(s[0])) * n;

    Ok(ret)
}

#[derive(PartialEq, Eq, Debug)]
pub struct Vorud(String);

impl Vorud {
    pub fn new(s: String) -> Result<Vorud, ()> {
        if s.len() == 0 { return Ok(Vorud("".to_string())); }
        let ch = &s[].chars().collect::<Vec<char>>();
        let mut i = 0;
        loop {
            if i > ch.len() - 5 { return Err(()); }
            try!(c(ch[i]));
            try!(v(ch[i + 1]));
            try!(c(ch[i + 2]));
            try!(v(ch[i + 3]));
            try!(c(ch[i + 4]));
            if i == ch.len() - 5 { return Ok(Vorud(s)); }
            if ch[i + 5] != '-' { return Err(()); }
            i += 6;
        }
    }
}

pub trait FromVorud<E> {
    fn from_vorud(v: &Vorud) -> Result<Self, E>;
}

pub trait ToVorud {
    fn to_vorud(&self) -> Vorud;
}

impl<'a> ToVorud for &'a [u8] {
    fn to_vorud(&self) -> Vorud {
        let mut ret = String::new();
        for i in 0..(self.len() / 2) {
            if ret.len() > 0 { ret.push_str("-"); }
            let b0 = self[i * 2] as u16;
            let b1 = if self.len() == i * 2 + 1 { 0 } else { self[i * 2 + 1] as u16 };
            ret.push_str(&vorud_chunk(b1 + (b0 << 8))[]);
        }
        Vorud(ret)
    }
}

impl FromVorud<()> for Vec<u8> {
    fn from_vorud(&Vorud(ref s): &Vorud) -> Result<Vec<u8>, ()> {
        let mut ret = Vec::new();
        for chunk in (&s[]).split('-') {
            let x = try!(durov_chunk(chunk));
            ret.push((x / 0xff) as u8);
            ret.push((x % 0xff) as u8);
        }
        Ok(ret)
    }
}

impl ToVorud for u32 {
    fn to_vorud(&self) -> Vorud {
        let mut vec = Vec::new();
        vec.push(((*self >> 24) % 0xff) as u8);
        vec.push(((*self >> 16) % 0xff) as u8);
        vec.push(((*self >> 8) % 0xff) as u8);
        vec.push((*self % 0xff) as u8);
        (&vec[]).to_vorud()
    }
}

impl FromVorud<()> for u32 {
    fn from_vorud(v: &Vorud) -> Result<u32, ()> {
        let v: Vec<u8> = try!(FromVorud::from_vorud(v));
        if v.len() != 4 { return Err(()); }
        Ok(v[3] as u32 +
            ((v[2] as u32) << 8) +
            ((v[1] as u32) << 16) +
            ((v[0] as u32) << 24))
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_vorud() {
        use super::ToVorud;

        assert_eq!("babab", &super::vorud_chunk(0)[]);
        assert_eq!("babad", &super::vorud_chunk(1)[]);
        assert_eq!(Ok(0u16), super::durov_chunk("babab"));
        assert_eq!(Ok(1234u16), super::durov_chunk(&super::vorud_chunk(1234)[]));
        assert_eq!("togas", &super::vorud_chunk(super::durov_chunk("togas").unwrap())[]);
        assert_eq!(super::Vorud("babab-babab".to_string()), 0u32.to_vorud());
        assert_eq!(super::Vorud("babab-babad".to_string()), 1u32.to_vorud());
        assert_eq!(Ok(1u32), super::FromVorud::from_vorud(&super::Vorud("babab-babad".to_string())));
    }
}
<|endoftext|>