<commit_before>//! Convenience functions and types for working with [`std::path::Path`].
//!
//! This module deliberately ignores Window's prefixes for now, but I would welcome a change that
//! adds it.
//!
//! [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html

use std::ffi::OsString;
use std::path::{Component, Path, PathBuf};

/// An iterator with `peek()` and `peek2()` calls that return optional references to the next
/// element or the one after.
///
/// This struct is created by the [`peek2able()`] extension method on [`Iterator`] provided by this
/// module's [`IteratorExt`].
///
/// [`peek2able()`]: trait.IteratorExt.html#method.peek2able
/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
/// [`IteratorExt`]: trait.IteratorExt.html
#[derive(Debug)]
pub struct Peek2able<I: Iterator> {
    // iter is the original iterator that we now have a Peek2able of.
    iter: I,
    // peek1 is the stashed value corresponding to the first lookahead from a peek or peek2 call,
    // or the second value from a peek2 call after next has been called once.
    peek1: Option<Option<I::Item>>,
    // peek2 is the stashed value corresponding to the second lookahead from a `.peek2()` call.
    peek2: Option<Option<I::Item>>,
}

/// An extension to add two-element lookahead to an iterator.
pub trait IteratorExt<I: Iterator> {
    /// Creates an iterator that can look at he next two elments from the iterator without
    /// consuming it.
    ///
    /// Adds [`peek()`] and [`peek2()`] methods to an iterator.
    ///
    /// Note that the underlying iterator is still advanced when either [`peek()`] or [`peek2()`]
    /// is called for the first time. In order to peek, [`next()`] is called, hence any side
    /// effects of the [`next()`] method will occur.
    ///
    /// [`next()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
    /// [`peek()`]: struct.Peek2able.html#method.peek
    /// [`peek2()`]: struct.Peek2able.html#method.peek2
    fn peek2able(self) -> Peek2able<I>;
}

impl<I: Iterator> IteratorExt<I> for I {
    fn peek2able(self) -> Peek2able<I> {
        Peek2able {
            iter: self,
            peek1: None,
            peek2: None,
        }
    }
}

impl<I: Iterator> Iterator for Peek2able<I> {
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.peek1.take() {
            Some(v) => {
                self.peek1 = self.peek2.take();
                v
            }
            None => self.iter.next(),
        }
    }
}

impl<I: Iterator> Peek2able<I> {
    /// Returns a reference to the next `.next()` value without advancing the iterator.
    #[allow(dead_code)]
    pub fn peek(&mut self) -> Option<&I::Item> {
        if self.peek1.is_none() {
            self.peek1 = Some(self.iter.next());
        }
        match self.peek1 {
            Some(Some(ref value)) => Some(value),
            Some(None) => None,
            _ => unreachable!(),
        }
    }
    pub fn peek2(&mut self) -> Option<&I::Item> {
        if self.peek1.is_none() {
            self.peek1 = Some(self.iter.next());
        }
        if self.peek2.is_none() {
            self.peek2 = Some(self.iter.next());
        }
        match self.peek2 {
            Some(Some(ref value)) => Some(value),
            Some(None) => None,
            _ => unreachable!(),
        }
    }
}

/// A simplified version of [`std::path::Component`].
///
/// [`std::path::Component`]: https://doc.rust-lang.org/std/path/enum.Component.html
#[derive(Clone, Debug, PartialEq)]
pub enum Part {
    /// A `..` in a path that could not be normalized away.
    ParentDir,
    /// A file or directory name.
    Normal(OsString),
}

impl Part {
    /// Borrows a `Normal` path part's `OsString` path.
    pub fn as_normal(&self) -> Option<&OsString> {
        match *self {
            Part::Normal(ref s) => Some(s),
            Part::ParentDir => None,
        }
    }
    /// Consumes a `Normal` path part into its `OsString` path.
    pub fn into_normal(self) -> Option<OsString> {
        match self {
            Part::Normal(s) => Some(s),
            Part::ParentDir => None,
        }
    }
}

/// Wraps information about a path and provides iterators over the components in that path.
///
/// This struct is created by the [`normalize`] function.
///
/// [`normalize`]: fn.normalize.html
#[derive(Debug)]
pub struct Parts {
    // at_root signifies whether the original path, normalized, began at root.
    pub at_root: bool,
    // inner contains all normal inner of a path and, if not at root, may begin with a few
    // parent directories.
    pub inner: Vec<Part>,
}

impl From<Part> for Parts {
    fn from(p: Part) -> Parts {
        Parts { at_root: false, inner: vec![p] }
    }
}

/// Returns the shortest [`Parts`] equivalent to path purely by lexical parsing.
///
/// - replaces multiple path separators with one
/// - eliminates each `.`
/// - replaces `..` with the non `..` that preceeds it
///
/// Effectively, this is [`std::fs::canonicalize`] except for this operates on a potential path.
///
/// [`Parts`]: struct.Parts.html
/// [`std::fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html
pub fn normalize<P: AsRef<Path>>(path: &P) -> Parts {
    let mut ps = Parts {
        at_root: false,
        inner: Vec::new(),
    };
    for comp in path.as_ref().components() {
        match comp {
            Component::RootDir => ps.at_root = true,
            Component::ParentDir => {
                if ps.at_root || ps.inner.last().map_or(false, |last| *last != Part::ParentDir) {
                    ps.inner.pop();
                } else {
                    ps.inner.push(Part::ParentDir);
                }
            }
            Component::Normal(p) => {
                ps.inner.push(Part::Normal(p.to_os_string()));
            }
            _ => (),
        }
    }
    ps
}
<commit_msg>path_parts: remove now unused `use`<commit_after>//! Convenience functions and types for working with [`std::path::Path`].
//!
//! This module deliberately ignores Window's prefixes for now, but I would welcome a change that
//! adds it.
//!
//! [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html

use std::ffi::OsString;
use std::path::{Component, Path};

/// An iterator with `peek()` and `peek2()` calls that return optional references to the next
/// element or the one after.
///
/// This struct is created by the [`peek2able()`] extension method on [`Iterator`] provided by this
/// module's [`IteratorExt`].
///
/// [`peek2able()`]: trait.IteratorExt.html#method.peek2able
/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
/// [`IteratorExt`]: trait.IteratorExt.html
#[derive(Debug)]
pub struct Peek2able<I: Iterator> {
    // iter is the original iterator that we now have a Peek2able of.
    iter: I,
    // peek1 is the stashed value corresponding to the first lookahead from a peek or peek2 call,
    // or the second value from a peek2 call after next has been called once.
    peek1: Option<Option<I::Item>>,
    // peek2 is the stashed value corresponding to the second lookahead from a `.peek2()` call.
    peek2: Option<Option<I::Item>>,
}

/// An extension to add two-element lookahead to an iterator.
pub trait IteratorExt<I: Iterator> {
    /// Creates an iterator that can look at he next two elments from the iterator without
    /// consuming it.
    ///
    /// Adds [`peek()`] and [`peek2()`] methods to an iterator.
    ///
    /// Note that the underlying iterator is still advanced when either [`peek()`] or [`peek2()`]
    /// is called for the first time. In order to peek, [`next()`] is called, hence any side
    /// effects of the [`next()`] method will occur.
    ///
    /// [`next()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
    /// [`peek()`]: struct.Peek2able.html#method.peek
    /// [`peek2()`]: struct.Peek2able.html#method.peek2
    fn peek2able(self) -> Peek2able<I>;
}

impl<I: Iterator> IteratorExt<I> for I {
    fn peek2able(self) -> Peek2able<I> {
        Peek2able {
            iter: self,
            peek1: None,
            peek2: None,
        }
    }
}

impl<I: Iterator> Iterator for Peek2able<I> {
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.peek1.take() {
            Some(v) => {
                self.peek1 = self.peek2.take();
                v
            }
            None => self.iter.next(),
        }
    }
}

impl<I: Iterator> Peek2able<I> {
    /// Returns a reference to the next `.next()` value without advancing the iterator.
    #[allow(dead_code)]
    pub fn peek(&mut self) -> Option<&I::Item> {
        if self.peek1.is_none() {
            self.peek1 = Some(self.iter.next());
        }
        match self.peek1 {
            Some(Some(ref value)) => Some(value),
            Some(None) => None,
            _ => unreachable!(),
        }
    }
    pub fn peek2(&mut self) -> Option<&I::Item> {
        if self.peek1.is_none() {
            self.peek1 = Some(self.iter.next());
        }
        if self.peek2.is_none() {
            self.peek2 = Some(self.iter.next());
        }
        match self.peek2 {
            Some(Some(ref value)) => Some(value),
            Some(None) => None,
            _ => unreachable!(),
        }
    }
}

/// A simplified version of [`std::path::Component`].
///
/// [`std::path::Component`]: https://doc.rust-lang.org/std/path/enum.Component.html
#[derive(Clone, Debug, PartialEq)]
pub enum Part {
    /// A `..` in a path that could not be normalized away.
    ParentDir,
    /// A file or directory name.
    Normal(OsString),
}

impl Part {
    /// Borrows a `Normal` path part's `OsString` path.
    pub fn as_normal(&self) -> Option<&OsString> {
        match *self {
            Part::Normal(ref s) => Some(s),
            Part::ParentDir => None,
        }
    }
    /// Consumes a `Normal` path part into its `OsString` path.
    pub fn into_normal(self) -> Option<OsString> {
        match self {
            Part::Normal(s) => Some(s),
            Part::ParentDir => None,
        }
    }
}

/// Wraps information about a path and provides iterators over the components in that path.
///
/// This struct is created by the [`normalize`] function.
///
/// [`normalize`]: fn.normalize.html
#[derive(Debug)]
pub struct Parts {
    // at_root signifies whether the original path, normalized, began at root.
    pub at_root: bool,
    // inner contains all normal inner of a path and, if not at root, may begin with a few
    // parent directories.
    pub inner: Vec<Part>,
}

impl From<Part> for Parts {
    fn from(p: Part) -> Parts {
        Parts { at_root: false, inner: vec![p] }
    }
}

/// Returns the shortest [`Parts`] equivalent to path purely by lexical parsing.
///
/// - replaces multiple path separators with one
/// - eliminates each `.`
/// - replaces `..` with the non `..` that preceeds it
///
/// Effectively, this is [`std::fs::canonicalize`] except for this operates on a potential path.
///
/// [`Parts`]: struct.Parts.html
/// [`std::fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html
pub fn normalize<P: AsRef<Path>>(path: &P) -> Parts {
    let mut ps = Parts {
        at_root: false,
        inner: Vec::new(),
    };
    for comp in path.as_ref().components() {
        match comp {
            Component::RootDir => ps.at_root = true,
            Component::ParentDir => {
                if ps.at_root || ps.inner.last().map_or(false, |last| *last != Part::ParentDir) {
                    ps.inner.pop();
                } else {
                    ps.inner.push(Part::ParentDir);
                }
            }
            Component::Normal(p) => {
                ps.inner.push(Part::Normal(p.to_os_string()));
            }
            _ => (),
        }
    }
    ps
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{Nil, Append, Space, Group, Nest, Newline, Text};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

/// The concrete document type. This type is not meant to be used directly. Instead use the static
/// functions on `Doc` or the methods on an `DocAllocator`.
///
/// The `B` parameter is used to abstract over pointers to `Doc`. See `RefDoc` and `BoxDoc` for how
/// it is used
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Space,
    Newline,
    Text(Cow<'a, str>),
}

impl<'a, B, S> From<S> for Doc<'a, B>
    where S: Into<Cow<'a, str>>
{
    fn from(s: S) -> Doc<'a, B> {
        Doc::Text(s.into())
    }
}

impl<'a, B> Doc<'a, B> {
    /// Writes a rendered document.
    #[inline]
    pub fn render<'b, W: ?Sized + io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
        where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out)
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

fn write_newline<W: ?Sized + io::Write>(ind: usize, out: &mut W) -> io::Result<()> {
    try!(out.write_all(b"\n"));
    write_spaces(ind, out)
}

fn write_spaces<W: ?Sized + io::Write>(spaces: usize, out: &mut W) -> io::Result<()> {
    const SPACES: [u8; 100] = [b' '; 100];
    let mut inserted = 0;
    while inserted < spaces {
        let insert = cmp::min(100, spaces - inserted);
        inserted += try!(out.write(&SPACES[..insert]));
    }
    Ok(())
}

#[inline]
fn fitting<'a, B>(next: Cmd<'a, B>,
                  bcmds: &Vec<Cmd<'a, B>>,
                  fcmds: &mut Vec<Cmd<'a, B>>,
                  mut rem: isize)
                  -> bool
    where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    while rem >= 0 {
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    // All commands have been processed
                    return true;
                } else {
                    fcmds.push(bcmds[bidx - 1]);
                    bidx -= 1;
                }
            }
            Some((ind, mode, doc)) => {
                match doc {
                    &Nil => {}
                    &Append(ref ldoc, ref rdoc) => {
                        fcmds.push((ind, mode, rdoc));
                        fcmds.push((ind, mode, ldoc));
                    }
                    &Group(ref doc) => {
                        fcmds.push((ind, mode, doc));
                    }
                    &Nest(off, ref doc) => {
                        fcmds.push((ind + off, mode, doc));
                    }
                    &Space => {
                        match mode {
                            Mode::Flat => {
                                rem -= 1;
                            }
                            Mode::Break => {
                                return true;
                            }
                        }
                    }
                    &Newline => return true,
                    &Text(ref str) => {
                        rem -= str.len() as isize;
                    }
                }
            }
        }
    }
    false
}

#[inline]
pub fn best<'a, W: ?Sized + io::Write, B>(doc: &'a Doc<'a, B>,
                                          width: usize,
                                          out: &mut W)
                                          -> io::Result<()>
    where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {}
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            }
            &Group(ref doc) => {
                match mode {
                    Mode::Flat => {
                        bcmds.push((ind, Mode::Flat, doc));
                    }
                    Mode::Break => {
                        let next = (ind, Mode::Flat, &**doc);
                        let rem = width as isize - pos as isize;
                        if fitting(next, &bcmds, &mut fcmds, rem) {
                            bcmds.push(next);
                        } else {
                            bcmds.push((ind, Mode::Break, doc));
                        }
                    }
                }
            }
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            }
            &Space => {
                match mode {
                    Mode::Flat => {
                        try!(write_spaces(1, out));
                    }
                    Mode::Break => {
                        try!(write_newline(ind, out));
                    }
                }
                pos = ind;
            }
            &Newline => {
                try!(write_newline(ind, out));
                pos = ind;
            }
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            }
        }
    }
    Ok(())
}
<commit_msg>perf: Push appended documents in batches<commit_after>use std::borrow::Cow;
use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{Nil, Append, Space, Group, Nest, Newline, Text};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

/// The concrete document type. This type is not meant to be used directly. Instead use the static
/// functions on `Doc` or the methods on an `DocAllocator`.
///
/// The `B` parameter is used to abstract over pointers to `Doc`. See `RefDoc` and `BoxDoc` for how
/// it is used
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Space,
    Newline,
    Text(Cow<'a, str>),
}

impl<'a, B, S> From<S> for Doc<'a, B>
    where S: Into<Cow<'a, str>>
{
    fn from(s: S) -> Doc<'a, B> {
        Doc::Text(s.into())
    }
}

impl<'a, B> Doc<'a, B> {
    /// Writes a rendered document.
    #[inline]
    pub fn render<'b, W: ?Sized + io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
        where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out)
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

fn write_newline<W: ?Sized + io::Write>(ind: usize, out: &mut W) -> io::Result<()> {
    try!(out.write_all(b"\n"));
    write_spaces(ind, out)
}

fn write_spaces<W: ?Sized + io::Write>(spaces: usize, out: &mut W) -> io::Result<()> {
    const SPACES: [u8; 100] = [b' '; 100];
    let mut inserted = 0;
    while inserted < spaces {
        let insert = cmp::min(100, spaces - inserted);
        inserted += try!(out.write(&SPACES[..insert]));
    }
    Ok(())
}

#[inline]
fn fitting<'a, B>(next: Cmd<'a, B>,
                  bcmds: &Vec<Cmd<'a, B>>,
                  fcmds: &mut Vec<Cmd<'a, B>>,
                  mut rem: isize)
                  -> bool
    where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    while rem >= 0 {
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    // All commands have been processed
                    return true;
                } else {
                    fcmds.push(bcmds[bidx - 1]);
                    bidx -= 1;
                }
            }
            Some((ind, mode, doc)) => {
                match doc {
                    &Nil => {}
                    &Append(ref ldoc, ref rdoc) => {
                        fcmds.push((ind, mode, rdoc));
                        // Since appended documents often appear in sequence on the left side we
                        // gain a slight performance increase by batching these pushes (avoiding
                        // to push and directly pop `Append` documents)
                        let mut doc = ldoc;
                        while let Append(ref l, ref r) = **doc {
                            fcmds.push((ind, mode, r));
                            doc = l;
                        }
                        fcmds.push((ind, mode, doc));
                    }
                    &Group(ref doc) => {
                        fcmds.push((ind, mode, doc));
                    }
                    &Nest(off, ref doc) => {
                        fcmds.push((ind + off, mode, doc));
                    }
                    &Space => {
                        match mode {
                            Mode::Flat => {
                                rem -= 1;
                            }
                            Mode::Break => {
                                return true;
                            }
                        }
                    }
                    &Newline => return true,
                    &Text(ref str) => {
                        rem -= str.len() as isize;
                    }
                }
            }
        }
    }
    false
}

#[inline]
pub fn best<'a, W: ?Sized + io::Write, B>(doc: &'a Doc<'a, B>,
                                          width: usize,
                                          out: &mut W)
                                          -> io::Result<()>
    where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {}
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                let mut doc = ldoc;
                while let Append(ref l, ref r) = **doc {
                    bcmds.push((ind, mode, r));
                    doc = l;
                }
                bcmds.push((ind, mode, doc));
            }
            &Group(ref doc) => {
                match mode {
                    Mode::Flat => {
                        bcmds.push((ind, Mode::Flat, doc));
                    }
                    Mode::Break => {
                        let next = (ind, Mode::Flat, &**doc);
                        let rem = width as isize - pos as isize;
                        if fitting(next, &bcmds, &mut fcmds, rem) {
                            bcmds.push(next);
                        } else {
                            bcmds.push((ind, Mode::Break, doc));
                        }
                    }
                }
            }
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            }
            &Space => {
                match mode {
                    Mode::Flat => {
                        try!(write_spaces(1, out));
                    }
                    Mode::Break => {
                        try!(write_newline(ind, out));
                    }
                }
                pos = ind;
            }
            &Newline => {
                try!(write_newline(ind, out));
                pos = ind;
            }
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock};
use subject::{
    Subject, Source, Mapper, Receiver, WrapArc, Snapper, Merger, Filter,
    WeakSnapperWrapper, SamplingSubject, Holder, CellSwitcher, Lift2,
    WeakLift2Wrapper
};

pub struct Sink<A> {
    source: Arc<RwLock<Source<A>>>,
}

impl<A> Clone for Sink<A> {
    fn clone(&self) -> Sink<A> {
        Sink { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Sink<A> {
    pub fn new() -> Sink<A> {
        Sink { source: Arc::new(RwLock::new(Source::new())) }
    }

    pub fn send(&self, a: A) {
        self.source.write().unwrap().send(a)
    }

    pub fn event(&self) -> Stream<A> {
        Stream { source: self.source.wrap_as_subject() }
    }
}

pub struct Stream<A> {
    source: Arc<RwLock<Box<Subject<A> + 'static>>>,
}

impl<A> Clone for Stream<A> {
    fn clone(&self) -> Stream<A> {
        Stream { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Stream<A> {
    pub fn map<B, F>(&self, f: F) -> Stream<B>
        where B: Send + Sync + Clone,
              F: Fn(A) -> B + Send + Sync,
    {
        let source = Arc::new(RwLock::new(Mapper::new(f, self.source.clone())));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn filter<F: Fn(&A) -> bool + Send + Sync>(&self, f: F) -> Stream<A> {
        let source = Arc::new(RwLock::new(Filter::new(f, self.source.clone())));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn merge(&self, other: &Stream<A>) -> Stream<A> {
        let source = Arc::new(RwLock::new(Merger::new([
            self.source.clone(),
            other.source.clone(),
        ])));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        other.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn hold(&self, initial: A) -> Cell<A> {
        let source = Arc::new(RwLock::new(
            Holder::new(initial, self.source.clone())
        ));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Cell { source: source.wrap_into_sampling_subject() }
    }

    fn iter(&self) -> Iter<A> { Iter::new(self) }
}

pub struct Cell<A> {
    source: Arc<RwLock<Box<SamplingSubject<A> + 'static>>>
}

impl<A> Clone for Cell<A> {
    fn clone(&self) -> Cell<A> {
        Cell { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Cell<A> {
    pub fn sample(&self) -> A {
        self.source.write().unwrap().sample()
    }

    pub fn snapshot<B: Send + Sync + Clone>(&self, event: &Stream<B>) -> Stream<(A, B)> {
        let source = Arc::new(RwLock::new(Snapper::new(
            self.sample(), (self.source.clone(), event.source.clone())
        )));
        self.source.write().unwrap()
            .listen(WeakSnapperWrapper::boxed(&source));
        event.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }
}

impl<A: Send + Sync + Clone> Cell<Cell<A>> {
    pub fn switch(&self) -> Cell<A> {
        let source = Arc::new(RwLock::new(
            CellSwitcher::new(
                self.sample().sample(),
                self.source.clone(),
            )
        ));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Cell { source: source.wrap_into_sampling_subject() }
    }
}

pub fn lift2<A, B, C, F>(f: F, ba: &Cell<A>, bb: &Cell<B>) -> Cell<C>
    where A: Send + Sync + Clone,
          B: Send + Sync + Clone,
          C: Send + Sync + Clone,
          F: Fn(A, B) -> C + Send + Sync,
{
    let source = Arc::new(RwLock::new(Lift2::new(
        (ba.sample(), bb.sample()), f, (ba.source.clone(), bb.source.clone())
    )));
    ba.source.write().unwrap().listen(source.wrap_as_listener());
    bb.source.write().unwrap().listen(WeakLift2Wrapper::boxed(&source));
    Cell { source: source.wrap_into_sampling_subject() }
}

struct Iter<A> {
    recv: Arc<RwLock<Receiver<A>>>,
}

impl<A> Clone for Iter<A> {
    fn clone(&self) -> Iter<A> {
        Iter { recv: self.recv.clone() }
    }
}

impl<A: Send + Sync + Clone> Iter<A> {
    fn new(event: &Stream<A>) -> Iter<A> {
        let iter = Iter {
            recv: Arc::new(RwLock::new(Receiver::new(
                event.source.clone()
            ))),
        };
        event.source.write().unwrap().listen(iter.recv.wrap_as_listener());
        iter
    }
}

impl<A: Send + Sync> Iterator for Iter<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.recv.write().unwrap().next()
    }
}

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

    #[test]
    fn sink() {
        let sink = Sink::new();
        let mut iter = sink.event().iter();
        sink.send(1);
        sink.send(2);
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn map() {
        let sink = Sink::new();
        let triple = sink.event().map(|x| 3 * x);
        let mut iter = triple.iter();
        sink.send(1);
        assert_eq!(iter.next(), Some(3));
    }

    #[test]
    fn filter() {
        let sink = Sink::new();
        let small = sink.event().filter(|&x: &i32| x < 11);
        let mut iter = small.iter();
        sink.send(12);
        sink.send(9);
        assert_eq!(iter.next(), Some(9));
    }

    #[test]
    fn merge() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let mut iter = sink1.event().merge(&sink2.event()).iter();
        sink1.send(12);
        sink2.send(9);
        assert_eq!(iter.next(), Some(12));
        assert_eq!(iter.next(), Some(9));
    }

    #[test]
    fn hold() {
        let ea = Sink::new();
        let ba = ea.event().hold(3);
        assert_eq!(ba.sample(), 3);
        ea.send(4);
        assert_eq!(ba.sample(), 4);
    }

    #[test]
    fn chain_1() {
        let sink = Sink::new();
        let chain = sink.event().filter(|&x: &i32| x < 20).map(|x| x / 2);
        let mut iter = chain.iter();
        sink.send(4);
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn chain_2() {
        let sink: Sink<i32> = Sink::new();
        let chain = sink.event().map(|x| x / 2).filter(|&x| x < 3);
        let mut iter = chain.iter();
        sink.send(4);
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn chain_3() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<i32> = Sink::new();
        let mut iter = sink1.event().map(|x| x + 4)
            .merge(&sink2.event().filter(|&x| x < 4).map(|x| x * 5))
            .iter();
        sink1.send(12);
        sink2.send(3);
        assert_eq!(iter.next(), Some(16));
        assert_eq!(iter.next(), Some(15));
    }

    #[test]
    fn snapshot() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<f64> = Sink::new();
        let mut snap_iter = sink1.event().hold(1).snapshot(&sink2.event().map(|x| x + 3.0)).iter();
        sink2.send(4.0);
        assert_eq!(snap_iter.next(), Some((1, 7.0)));
    }

    #[test]
    fn snapshot_2() {
        let ev1 = Sink::new();
        let beh1 = ev1.event().hold(5);
        let ev2 = Sink::new();
        let snap = beh1.snapshot(&ev2.event());
        let mut iter = snap.iter();
        assert_eq!(iter.next(), None);
        ev2.send(4);
        assert_eq!(iter.next(), Some((5, 4)));
        ev1.send(-2);
        assert_eq!(iter.next(), None);
        ev2.send(6);
        assert_eq!(iter.next(), Some((-2, 6)));
    }

    #[test]
    fn lift2_test() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let lifted = lift2(|a, b| a + b, &sink1.event().hold(0), &sink2.event().hold(3));
        assert_eq!(lifted.sample(), 3);
        sink1.send(1);
        assert_eq!(lifted.sample(), 4);
        sink2.send(11);
        assert_eq!(lifted.sample(), 12);
    }

    #[test]
    fn switch() {
        let stream1 = Sink::<Option<i32>>::new();
        let stream2 = Sink::<Option<i32>>::new();
        let button1 = Sink::<()>::new();
        let button2 = Sink::<()>::new();
        let tv = {
            let stream1 = stream1.event().hold(Some(-1));
            let stream2 = stream2.event().hold(Some(-2));
            button1.event()
                .map(move |_| { println!("switch to 1"); stream1.clone() })
                .merge(&button2.event()
                    .map(move |_| stream2.clone())
                )
                .hold(Sink::new().event().hold(Some(-3)))
                .switch()
        };
        assert_eq!(tv.sample(), Some(-3));
        button1.send(());
        assert_eq!(tv.sample(), Some(-1));
        button2.send(());
        assert_eq!(tv.sample(), Some(-2));
        stream1.send(Some(6));
        button1.send(());
        assert_eq!(tv.sample(), Some(6));
    }

    #[test]
    fn clone() {
        let sink = Sink::new();
        let b = sink.event().hold(1);
        sink.clone().send(3);
        assert_eq!(b.sample(), 3);
    }
}
<commit_msg>Test moving a value into a closure<commit_after>use std::sync::{Arc, RwLock};
use subject::{
    Subject, Source, Mapper, Receiver, WrapArc, Snapper, Merger, Filter,
    WeakSnapperWrapper, SamplingSubject, Holder, CellSwitcher, Lift2,
    WeakLift2Wrapper
};

pub struct Sink<A> {
    source: Arc<RwLock<Source<A>>>,
}

impl<A> Clone for Sink<A> {
    fn clone(&self) -> Sink<A> {
        Sink { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Sink<A> {
    pub fn new() -> Sink<A> {
        Sink { source: Arc::new(RwLock::new(Source::new())) }
    }

    pub fn send(&self, a: A) {
        self.source.write().unwrap().send(a)
    }

    pub fn event(&self) -> Stream<A> {
        Stream { source: self.source.wrap_as_subject() }
    }
}

pub struct Stream<A> {
    source: Arc<RwLock<Box<Subject<A> + 'static>>>,
}

impl<A> Clone for Stream<A> {
    fn clone(&self) -> Stream<A> {
        Stream { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Stream<A> {
    pub fn map<B, F>(&self, f: F) -> Stream<B>
        where B: Send + Sync + Clone,
              F: Fn(A) -> B + Send + Sync,
    {
        let source = Arc::new(RwLock::new(Mapper::new(f, self.source.clone())));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn filter<F: Fn(&A) -> bool + Send + Sync>(&self, f: F) -> Stream<A> {
        let source = Arc::new(RwLock::new(Filter::new(f, self.source.clone())));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn merge(&self, other: &Stream<A>) -> Stream<A> {
        let source = Arc::new(RwLock::new(Merger::new([
            self.source.clone(),
            other.source.clone(),
        ])));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        other.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }

    pub fn hold(&self, initial: A) -> Cell<A> {
        let source = Arc::new(RwLock::new(
            Holder::new(initial, self.source.clone())
        ));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Cell { source: source.wrap_into_sampling_subject() }
    }

    fn iter(&self) -> Iter<A> { Iter::new(self) }
}

pub struct Cell<A> {
    source: Arc<RwLock<Box<SamplingSubject<A> + 'static>>>
}

impl<A> Clone for Cell<A> {
    fn clone(&self) -> Cell<A> {
        Cell { source: self.source.clone() }
    }
}

impl<A: Send + Sync + Clone> Cell<A> {
    pub fn sample(&self) -> A {
        self.source.write().unwrap().sample()
    }

    pub fn snapshot<B: Send + Sync + Clone>(&self, event: &Stream<B>) -> Stream<(A, B)> {
        let source = Arc::new(RwLock::new(Snapper::new(
            self.sample(), (self.source.clone(), event.source.clone())
        )));
        self.source.write().unwrap()
            .listen(WeakSnapperWrapper::boxed(&source));
        event.source.write().unwrap().listen(source.wrap_as_listener());
        Stream { source: source.wrap_into_subject() }
    }
}

impl<A: Send + Sync + Clone> Cell<Cell<A>> {
    pub fn switch(&self) -> Cell<A> {
        let source = Arc::new(RwLock::new(
            CellSwitcher::new(
                self.sample().sample(),
                self.source.clone(),
            )
        ));
        self.source.write().unwrap().listen(source.wrap_as_listener());
        Cell { source: source.wrap_into_sampling_subject() }
    }
}

pub fn lift2<A, B, C, F>(f: F, ba: &Cell<A>, bb: &Cell<B>) -> Cell<C>
    where A: Send + Sync + Clone,
          B: Send + Sync + Clone,
          C: Send + Sync + Clone,
          F: Fn(A, B) -> C + Send + Sync,
{
    let source = Arc::new(RwLock::new(Lift2::new(
        (ba.sample(), bb.sample()), f, (ba.source.clone(), bb.source.clone())
    )));
    ba.source.write().unwrap().listen(source.wrap_as_listener());
    bb.source.write().unwrap().listen(WeakLift2Wrapper::boxed(&source));
    Cell { source: source.wrap_into_sampling_subject() }
}

struct Iter<A> {
    recv: Arc<RwLock<Receiver<A>>>,
}

impl<A> Clone for Iter<A> {
    fn clone(&self) -> Iter<A> {
        Iter { recv: self.recv.clone() }
    }
}

impl<A: Send + Sync + Clone> Iter<A> {
    fn new(event: &Stream<A>) -> Iter<A> {
        let iter = Iter {
            recv: Arc::new(RwLock::new(Receiver::new(
                event.source.clone()
            ))),
        };
        event.source.write().unwrap().listen(iter.recv.wrap_as_listener());
        iter
    }
}

impl<A: Send + Sync> Iterator for Iter<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.recv.write().unwrap().next()
    }
}

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

    #[test]
    fn sink() {
        let sink = Sink::new();
        let mut iter = sink.event().iter();
        sink.send(1);
        sink.send(2);
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn map() {
        let sink = Sink::new();
        let triple = sink.event().map(|x| 3 * x);
        let mut iter = triple.iter();
        sink.send(1);
        assert_eq!(iter.next(), Some(3));
    }

    #[test]
    fn filter() {
        let sink = Sink::new();
        let small = sink.event().filter(|&x: &i32| x < 11);
        let mut iter = small.iter();
        sink.send(12);
        sink.send(9);
        assert_eq!(iter.next(), Some(9));
    }

    #[test]
    fn merge() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let mut iter = sink1.event().merge(&sink2.event()).iter();
        sink1.send(12);
        sink2.send(9);
        assert_eq!(iter.next(), Some(12));
        assert_eq!(iter.next(), Some(9));
    }

    #[test]
    fn hold() {
        let ea = Sink::new();
        let ba = ea.event().hold(3);
        assert_eq!(ba.sample(), 3);
        ea.send(4);
        assert_eq!(ba.sample(), 4);
    }

    #[test]
    fn chain_1() {
        let sink = Sink::new();
        let chain = sink.event().filter(|&x: &i32| x < 20).map(|x| x / 2);
        let mut iter = chain.iter();
        sink.send(4);
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn chain_2() {
        let sink: Sink<i32> = Sink::new();
        let chain = sink.event().map(|x| x / 2).filter(|&x| x < 3);
        let mut iter = chain.iter();
        sink.send(4);
        assert_eq!(iter.next(), Some(2));
    }

    #[test]
    fn chain_3() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<i32> = Sink::new();
        let mut iter = sink1.event().map(|x| x + 4)
            .merge(&sink2.event().filter(|&x| x < 4).map(|x| x * 5))
            .iter();
        sink1.send(12);
        sink2.send(3);
        assert_eq!(iter.next(), Some(16));
        assert_eq!(iter.next(), Some(15));
    }

    #[test]
    fn snapshot() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<f64> = Sink::new();
        let mut snap_iter = sink1.event().hold(1).snapshot(&sink2.event().map(|x| x + 3.0)).iter();
        sink2.send(4.0);
        assert_eq!(snap_iter.next(), Some((1, 7.0)));
    }

    #[test]
    fn snapshot_2() {
        let ev1 = Sink::new();
        let beh1 = ev1.event().hold(5);
        let ev2 = Sink::new();
        let snap = beh1.snapshot(&ev2.event());
        let mut iter = snap.iter();
        assert_eq!(iter.next(), None);
        ev2.send(4);
        assert_eq!(iter.next(), Some((5, 4)));
        ev1.send(-2);
        assert_eq!(iter.next(), None);
        ev2.send(6);
        assert_eq!(iter.next(), Some((-2, 6)));
    }

    #[test]
    fn lift2_test() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let lifted = lift2(|a, b| a + b, &sink1.event().hold(0), &sink2.event().hold(3));
        assert_eq!(lifted.sample(), 3);
        sink1.send(1);
        assert_eq!(lifted.sample(), 4);
        sink2.send(11);
        assert_eq!(lifted.sample(), 12);
    }

    #[test]
    fn switch() {
        let stream1 = Sink::<Option<i32>>::new();
        let stream2 = Sink::<Option<i32>>::new();
        let button1 = Sink::<()>::new();
        let button2 = Sink::<()>::new();
        let tv = {
            let stream1 = stream1.event().hold(Some(-1));
            let stream2 = stream2.event().hold(Some(-2));
            button1.event()
                .map(move |_| { println!("switch to 1"); stream1.clone() })
                .merge(&button2.event()
                    .map(move |_| stream2.clone())
                )
                .hold(Sink::new().event().hold(Some(-3)))
                .switch()
        };
        assert_eq!(tv.sample(), Some(-3));
        button1.send(());
        assert_eq!(tv.sample(), Some(-1));
        button2.send(());
        assert_eq!(tv.sample(), Some(-2));
        stream1.send(Some(6));
        button1.send(());
        assert_eq!(tv.sample(), Some(6));
    }

    #[test]
    fn clone() {
        let sink = Sink::new();
        let b = sink.event().hold(1);
        sink.clone().send(3);
        assert_eq!(b.sample(), 3);
    }

    #[test]
    fn move_closure() {
        let sink = Sink::<i32>::new();
        let x = 3;
        sink.event().map(move |y| y + x);
    }
}
<|endoftext|>


<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::error::Error;

use thiserror::Error as ThisError;

use base::MappedRegion;
use base::MemoryMappingArena;
use base::MmapError;
use ffmpeg::avcodec::AvBuffer;
use ffmpeg::avcodec::AvBufferSource;
use ffmpeg::avcodec::AvError;
use ffmpeg::avcodec::AvFrame;
use ffmpeg::avcodec::AvFrameError;
use ffmpeg::avcodec::AvPixelFormat;
use ffmpeg::avcodec::Dimensions;
use ffmpeg::avcodec::PlaneDescriptor;

use crate::virtio::video::format::Format;
use crate::virtio::video::resource::BufferHandle;
use crate::virtio::video::resource::GuestResource;

/// A simple wrapper that turns a [`MemoryMappingArena`] into an [`AvBufferSource`].
///
/// **Note:** Only use this if you can reasonably assume the mapped memory won't be written to from
/// another thread or the VM! The reason [`AvBufferSource`] is not directly implemented on
/// [`MemoryMappingArena`] is exactly due to this unsafety: If the guest or someone else writes to
/// the buffer FFmpeg is currently reading from or writing to, undefined behavior might occur. This
/// struct acts as an opt-in mechanism for this potential unsafety.
pub struct MemoryMappingAvBufferSource(MemoryMappingArena);

impl From<MemoryMappingArena> for MemoryMappingAvBufferSource {
    fn from(inner: MemoryMappingArena) -> Self {
        Self(inner)
    }
}
impl AvBufferSource for MemoryMappingAvBufferSource {
    fn as_ptr(&self) -> *const u8 {
        self.0.as_ptr() as _
    }

    fn len(&self) -> usize {
        self.0.size()
    }
}

pub trait TryAsAvFrameExt {
    type BufferSource;
    type Error: Error;

    /// Try to create an [`AvFrame`] from `self`.
    ///
    /// `wrapper` is a constructor for `T` that wraps `Self::BufferSource` and implement the
    /// `AvBufferSource` functionality. This can be used to provide a custom destructor
    /// implementation: for example, sending a virtio message signaling the buffer source is no
    /// longer used and it can be recycled by the guest.
    ///
    /// Note that `Self::BufferSource` might not always implement `AvBufferSource`. For instance,
    /// it's not guaranteed that a `MemoryMappingArena` created from `GuestResource` will be always
    /// immutable, and the backend need to explicit acknowledge the potential unsoundness by
    /// wrapping it in [`MemoryMappingAvBufferSource`].
    fn try_as_av_frame<T: AvBufferSource + 'static>(
        &self,
        wrapper: impl FnOnce(Self::BufferSource) -> T,
    ) -> Result<AvFrame, Self::Error>;
}

#[derive(Debug, ThisError)]
pub enum GuestResourceToAvFrameError {
    #[error("error while creating the AvFrame: {0}")]
    AvFrameError(#[from] AvFrameError),
    #[error("cannot mmap guest resource: {0}")]
    MappingResource(#[from] MmapError),
    #[error("virtio resource format is not convertible to AvPixelFormat")]
    InvalidFormat,
    #[error("out of memory while allocating AVBuffer")]
    CannotAllocateAvBuffer,
}

impl From<AvError> for GuestResourceToAvFrameError {
    fn from(e: AvError) -> Self {
        GuestResourceToAvFrameError::AvFrameError(AvFrameError::AvError(e))
    }
}

impl TryAsAvFrameExt for GuestResource {
    type BufferSource = MemoryMappingArena;
    type Error = GuestResourceToAvFrameError;

    fn try_as_av_frame<T: AvBufferSource + 'static>(
        &self,
        wrapper: impl FnOnce(MemoryMappingArena) -> T,
    ) -> Result<AvFrame, Self::Error> {
        let mut builder = AvFrame::builder()?;
        builder.set_dimensions(Dimensions {
            width: self.width,
            height: self.height,
        })?;
        let format = self
            .format
            .try_into()
            .map_err(|_| GuestResourceToAvFrameError::InvalidFormat)?;
        builder.set_format(format)?;
        let planes = &self.planes;
        // We have at least one plane, so we can unwrap below.
        let len = format.plane_sizes(planes.iter().map(|p| p.stride as _), self.height)?;
        let start = planes.iter().map(|p| p.offset).min().unwrap();
        let end = planes
            .iter()
            .enumerate()
            .map(|(i, p)| p.offset + len[i])
            .max()
            .unwrap();
        let mapping = self.handle.get_mapping(start, end - start)?;
        Ok(builder.build_owned(
            [AvBuffer::new(wrapper(mapping))
                .ok_or(GuestResourceToAvFrameError::CannotAllocateAvBuffer)?],
            planes.iter().map(|p| PlaneDescriptor {
                buffer_index: 0,
                offset: p.offset - start,
                stride: p.stride,
            }),
        )?)
    }
}

/// The error returned by `AvPixelFormat::try_from` when there's no applicable format.
// The empty field prevents constructing this and allows extending it in the future.
#[derive(Debug)]
pub struct TryFromFormatError(());

impl TryFrom<Format> for AvPixelFormat {
    type Error = TryFromFormatError;

    fn try_from(value: Format) -> Result<Self, Self::Error> {
        use ffmpeg::*;
        AvPixelFormat::try_from(match value {
            Format::NV12 => AVPixelFormat_AV_PIX_FMT_NV12,
            Format::YUV420 => AVPixelFormat_AV_PIX_FMT_YUV420P,
            _ => return Err(TryFromFormatError(())),
        })
        .map_err(|_|
            // The error case should never happen as long as we use valid constant values, but
            // don't panic in case something goes wrong.
            TryFromFormatError(()))
    }
}
<commit_msg>virtio: video: Add an Error implementation for TryFromFormatError.<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::error::Error;
use std::fmt::{Display, Formatter};

use thiserror::Error as ThisError;

use base::MappedRegion;
use base::MemoryMappingArena;
use base::MmapError;
use ffmpeg::avcodec::AvBuffer;
use ffmpeg::avcodec::AvBufferSource;
use ffmpeg::avcodec::AvError;
use ffmpeg::avcodec::AvFrame;
use ffmpeg::avcodec::AvFrameError;
use ffmpeg::avcodec::AvPixelFormat;
use ffmpeg::avcodec::Dimensions;
use ffmpeg::avcodec::PlaneDescriptor;

use crate::virtio::video::format::Format;
use crate::virtio::video::resource::BufferHandle;
use crate::virtio::video::resource::GuestResource;

/// A simple wrapper that turns a [`MemoryMappingArena`] into an [`AvBufferSource`].
///
/// **Note:** Only use this if you can reasonably assume the mapped memory won't be written to from
/// another thread or the VM! The reason [`AvBufferSource`] is not directly implemented on
/// [`MemoryMappingArena`] is exactly due to this unsafety: If the guest or someone else writes to
/// the buffer FFmpeg is currently reading from or writing to, undefined behavior might occur. This
/// struct acts as an opt-in mechanism for this potential unsafety.
pub struct MemoryMappingAvBufferSource(MemoryMappingArena);

impl From<MemoryMappingArena> for MemoryMappingAvBufferSource {
    fn from(inner: MemoryMappingArena) -> Self {
        Self(inner)
    }
}
impl AvBufferSource for MemoryMappingAvBufferSource {
    fn as_ptr(&self) -> *const u8 {
        self.0.as_ptr() as _
    }

    fn len(&self) -> usize {
        self.0.size()
    }
}

pub trait TryAsAvFrameExt {
    type BufferSource;
    type Error: Error;

    /// Try to create an [`AvFrame`] from `self`.
    ///
    /// `wrapper` is a constructor for `T` that wraps `Self::BufferSource` and implement the
    /// `AvBufferSource` functionality. This can be used to provide a custom destructor
    /// implementation: for example, sending a virtio message signaling the buffer source is no
    /// longer used and it can be recycled by the guest.
    ///
    /// Note that `Self::BufferSource` might not always implement `AvBufferSource`. For instance,
    /// it's not guaranteed that a `MemoryMappingArena` created from `GuestResource` will be always
    /// immutable, and the backend need to explicit acknowledge the potential unsoundness by
    /// wrapping it in [`MemoryMappingAvBufferSource`].
    fn try_as_av_frame<T: AvBufferSource + 'static>(
        &self,
        wrapper: impl FnOnce(Self::BufferSource) -> T,
    ) -> Result<AvFrame, Self::Error>;
}

#[derive(Debug, ThisError)]
pub enum GuestResourceToAvFrameError {
    #[error("error while creating the AvFrame: {0}")]
    AvFrameError(#[from] AvFrameError),
    #[error("cannot mmap guest resource: {0}")]
    MappingResource(#[from] MmapError),
    #[error("virtio resource format is not convertible to AvPixelFormat")]
    InvalidFormat,
    #[error("out of memory while allocating AVBuffer")]
    CannotAllocateAvBuffer,
}

impl From<AvError> for GuestResourceToAvFrameError {
    fn from(e: AvError) -> Self {
        GuestResourceToAvFrameError::AvFrameError(AvFrameError::AvError(e))
    }
}

impl TryAsAvFrameExt for GuestResource {
    type BufferSource = MemoryMappingArena;
    type Error = GuestResourceToAvFrameError;

    fn try_as_av_frame<T: AvBufferSource + 'static>(
        &self,
        wrapper: impl FnOnce(MemoryMappingArena) -> T,
    ) -> Result<AvFrame, Self::Error> {
        let mut builder = AvFrame::builder()?;
        builder.set_dimensions(Dimensions {
            width: self.width,
            height: self.height,
        })?;
        let format = self
            .format
            .try_into()
            .map_err(|_| GuestResourceToAvFrameError::InvalidFormat)?;
        builder.set_format(format)?;
        let planes = &self.planes;
        // We have at least one plane, so we can unwrap below.
        let len = format.plane_sizes(planes.iter().map(|p| p.stride as _), self.height)?;
        let start = planes.iter().map(|p| p.offset).min().unwrap();
        let end = planes
            .iter()
            .enumerate()
            .map(|(i, p)| p.offset + len[i])
            .max()
            .unwrap();
        let mapping = self.handle.get_mapping(start, end - start)?;
        Ok(builder.build_owned(
            [AvBuffer::new(wrapper(mapping))
                .ok_or(GuestResourceToAvFrameError::CannotAllocateAvBuffer)?],
            planes.iter().map(|p| PlaneDescriptor {
                buffer_index: 0,
                offset: p.offset - start,
                stride: p.stride,
            }),
        )?)
    }
}

/// The error returned by `AvPixelFormat::try_from` when there's no applicable format.
// The empty field prevents constructing this and allows extending it in the future.
#[derive(Debug)]
pub struct TryFromFormatError(());

impl Display for TryFromFormatError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "No matching format to convert between AvPixelFormat and Format"
        )
    }
}

impl Error for TryFromFormatError {}

impl TryFrom<Format> for AvPixelFormat {
    type Error = TryFromFormatError;

    fn try_from(value: Format) -> Result<Self, Self::Error> {
        use ffmpeg::*;
        AvPixelFormat::try_from(match value {
            Format::NV12 => AVPixelFormat_AV_PIX_FMT_NV12,
            Format::YUV420 => AVPixelFormat_AV_PIX_FMT_YUV420P,
            _ => return Err(TryFromFormatError(())),
        })
        .map_err(|_|
            // The error case should never happen as long as we use valid constant values, but
            // don't panic in case something goes wrong.
            TryFromFormatError(()))
    }
}
<|endoftext|>


<commit_before>use ::geometry::*;
use arrayvec;
trait SliceUp: Sized {
    type PerSlice: Iterator<Item=Self>;
    type Out: Iterator<Item=Self::PerSlice>;
    fn slice_up_x(&self, planes: PlaneSet) -> Self::Out;
    fn slice_up_y(&self, planes: PlaneSet) -> Self::Out;
}

type LineIter = ::std::option::IntoIter<Line>;

#[derive(Debug)]
struct LineSliceIter {
    l: Line,
    m: f32,
    c: f32,
    planes: PlaneSet,
    i: usize
}

impl Iterator for LineSliceIter {
    type Item = LineIter;
    fn next(&mut self) -> Option<LineIter> {
        if self.i >= self.planes.count {
            return None
        }
        if self.m == 0.0 {
            self.i += 1;
            return Some(Some(self.l).into_iter())
        }
        let lower = self.i as f32;
        let upper = lower + 1.0;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let mut lower_t = (lower_d - self.c) / self.m;
        let mut upper_t = (upper_d - self.c) / self.m;
        lower_t = lower_t.max(0.0).min(1.0);
        upper_t = upper_t.max(0.0).min(1.0);
        if self.m < 0.0 {
            ::std::mem::swap(&mut lower_t, &mut upper_t);
        }
        self.i += 1;
        if lower_t != upper_t {
            let p = &self.l.p;
            let v = p[1] - p[0];
            Some(Some(Line {
                p: [p[0] + v * lower_t,
                    p[0] + v * upper_t]
            }).into_iter())
        } else {
            Some(None.into_iter())
        }
    }
}

impl SliceUp for Line {
    type PerSlice = LineIter;
    type Out = LineSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].x - p[0].x,
            c: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].y - p[0].y,
            c: p[0].y
        }
    }
}

type CurveIter = arrayvec::IntoIter<[Curve; 2]>;

struct CurveSliceIter {
    curve: Curve,
    planes: PlaneSet,
    i: usize,
    a: f32,
    b: f32,
    c_shift: f32
}

impl Iterator for CurveSliceIter {
    type Item = CurveIter;
    fn next(&mut self) -> Option<Self::Item> {
        use arrayvec::ArrayVec;
        use geometry::RealQuadraticSolution as RQS;
        use geometry::solve_quadratic_real as solve;
        use geometry::Cut;
        if self.i >= self.planes.count {
            return None
        }
        let lower = self.i as f32;
        self.i += 1;
        let upper = lower + self.planes.step;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let l_sol = solve(self.a, self.b, self.c_shift - lower_d);
        let u_sol = solve(self.a, self.b, self.c_shift - upper_d);
        let mut result = ArrayVec::<[Curve; 2]>::new();
        match (l_sol.in_order(), u_sol.in_order()) {
            (RQS::Two(a, b), RQS::Two(c, d)) => {
                // Two pieces
                let (a, b, c, d) = if self.a > 0.0 {
                    (c, a, b, d)
                } else {
                    (a, c, d, b)
                };
                let (a, b, c, d) = (a.min(1.0).max(0.0),
                                    b.min(1.0).max(0.0),
                                    c.min(1.0).max(0.0),
                                    d.min(1.0).max(0.0));
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
                if c != d {
                    result.push(self.curve.cut_from_to(c, d));
                }
            }
            (RQS::Two(a, b), RQS::None) |
            (RQS::Two(a, b), RQS::Touch(_)) |
            (RQS::None, RQS::Two(a, b)) |
            (RQS::Touch(_), RQS::Two(a, b)) |
            (RQS::One(a), RQS::One(b)) => {
                // One piece
                let (a, b) = if a > b { (b, a) } else { (a, b) };
                let a = a.min(1.0).max(0.0);
                let b = b.min(1.0).max(0.0);
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
            }
            (RQS::All, RQS::None) |
            (RQS::None, RQS::All) => {
                // coincident with one plane
                result.push(self.curve);
            }
            (RQS::None, RQS::None) => if self.a == 0.0 && self.b == 0.0
                && self.c_shift >= lower_d && self.c_shift <= upper_d
            {
                // parallel to planes, inbetween
                result.push(self.curve);
            },
            _ => unreachable!() // impossible
        }
        //println!("{:?}", result);
        Some(result.into_iter())
    }
}

#[derive(Debug)]
struct PlaneSet {
    start: f32,
    step: f32,
    count: usize
}

impl SliceUp for Curve {
    type PerSlice = CurveIter;
    type Out = CurveSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].x - 2.0 * p[1].x + p[2].x,
            b: 2.0 * (p[1].x - p[0].x),
            c_shift: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].y - 2.0 * p[1].y + p[2].y,
            b: 2.0 * (p[1].y - p[0].y),
            c_shift: p[0].y
        }
    }
}

pub fn rasterize<O: FnMut(u32, u32, f32)>(lines: &[Line], curves: &[Curve],
                                          width: u32, height: u32,
                                          mut output: O) {
    use ::std::collections::HashMap;
    let mut lines: Vec<_> = lines.iter().map(|&l| (l, l.bounding_box())).collect();
    lines[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut curves: Vec<_> = curves.iter().map(|&c| (c, c.bounding_box())).collect();
    curves[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut y = 0;
    let mut next_line = 0; let mut next_curve = 0;
    let mut active_lines_y  = HashMap::new(); let mut active_curves_y = HashMap::new();
    let mut active_lines_x  = HashMap::new(); let mut active_curves_x = HashMap::new();
    let mut scanline_lines = Vec::new();
    let mut lines_to_remove = Vec::new();
    let mut scanline_curves = Vec::new();
    let mut curves_to_remove = Vec::new();
    while y < height && (next_line != lines.len() || next_curve != curves.len()
        || active_lines_y.len() > 0 || active_curves_y.len() > 0)
    {
        let lower = y as f32;
        let upper = (y + 1) as f32;
        // Add newly active segments
        for &(ref line, ref bb) in lines[next_line..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_lines_y.insert(next_line, line.slice_up_y(planes));
            next_line += 1;
        }
        for &(ref curve, ref bb) in curves[next_curve..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_curves_y.insert(next_curve, curve.slice_up_y(planes));
            next_curve += 1;
        }
        // get y sliced segments for this scanline
        scanline_lines.clear();
        scanline_curves.clear();
        for (k, itr) in active_lines_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for line in itr {
                    scanline_lines.push((line, line.x_bounds()))
                }
            } else {
                lines_to_remove.push(*k);
            }
        }
        for (k, itr) in active_curves_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for curve in itr {
                    scanline_curves.push((curve, curve.x_bounds()))
                }
            } else {
                curves_to_remove.push(*k);
            }
        }
        // remove deactivated segments
        for k in lines_to_remove.drain(..) {
            active_lines_y.remove(&k);
        }
        for k in curves_to_remove.drain(..) {
            active_curves_y.remove(&k);
        }
        // sort scanline for traversal
        scanline_lines.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        scanline_curves.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        // Iterate through x, slice scanline segments into each cell. Evaluate, accumulate and output.
        {
            let mut next_line = 0; let mut next_curve = 0;
            let mut x = 0;
            let mut acc = 0.0;
            active_lines_x.clear();
            active_curves_x.clear();
            while x < width && (next_line != scanline_lines.len() || next_curve != scanline_curves.len()
                || active_lines_x.len() > 0 || active_curves_x.len() > 0)
            {
                let offset = vector(x as f32, y as f32);
                let lower = x as f32;
                let upper = (x+1) as f32;
                //add newly active segments
                for &(ref line, (_, ref max)) in scanline_lines[next_line..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_lines_x.insert(next_line, line.slice_up_x(planes));
                    next_line += 1;
                }
                for &(ref curve, (_, ref max)) in scanline_curves[next_curve..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_curves_x.insert(next_curve, curve.slice_up_x(planes));
                    next_curve += 1;
                }
                //process x sliced segments for this pixel
                let mut pixel_value = acc;
                let mut pixel_acc = 0.0;
                for (k, itr) in active_lines_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut line in itr {
                            let p = &mut line.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;

                            let a = p[0].y - p[1].y;
                            let v = (1.0 - (p[0].x + p[1].x) * 0.5) * a;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        lines_to_remove.push(*k);
                    }
                }
                for (k, itr) in active_curves_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut curve in itr {
                            let p = &mut curve.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;
                            p[2] = p[2] - offset;
                            let a = p[0].y - p[2].y;
                            let b = p[0].y - p[1].y;
                            let c = p[1].y - p[2].y;
                            let v = (b*(6.0 - 3.0*p[0].x - 2.0*p[1].x -     p[2].x) +
                                     c*(6.0 -     p[0].x - 2.0*p[1].x - 3.0*p[2].x)) / 6.0;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        curves_to_remove.push(*k);
                    }
                }
                //output
                output(x, y, pixel_value);
                acc += pixel_acc;
                // remove deactivated segments
                for k in lines_to_remove.drain(..) {
                    active_lines_x.remove(&k);
                }
                for k in curves_to_remove.drain(..) {
                    active_curves_x.remove(&k);
                }
                x += 1;
            }
            // fill remaining pixels
            for x in x..width {
                output(x, y, acc);
            }
        }
        y += 1;
    }
    // fill remaining scanlines with 0.0
    for y in y..height {
        for x in 0..width {
            output(x, y, 0.0);
        }
    }
}
<commit_msg>Absolute value results before sending to output from rasterize.<commit_after>use ::geometry::*;
use arrayvec;
trait SliceUp: Sized {
    type PerSlice: Iterator<Item=Self>;
    type Out: Iterator<Item=Self::PerSlice>;
    fn slice_up_x(&self, planes: PlaneSet) -> Self::Out;
    fn slice_up_y(&self, planes: PlaneSet) -> Self::Out;
}

type LineIter = ::std::option::IntoIter<Line>;

#[derive(Debug)]
struct LineSliceIter {
    l: Line,
    m: f32,
    c: f32,
    planes: PlaneSet,
    i: usize
}

impl Iterator for LineSliceIter {
    type Item = LineIter;
    fn next(&mut self) -> Option<LineIter> {
        if self.i >= self.planes.count {
            return None
        }
        if self.m == 0.0 {
            self.i += 1;
            return Some(Some(self.l).into_iter())
        }
        let lower = self.i as f32;
        let upper = lower + 1.0;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let mut lower_t = (lower_d - self.c) / self.m;
        let mut upper_t = (upper_d - self.c) / self.m;
        lower_t = lower_t.max(0.0).min(1.0);
        upper_t = upper_t.max(0.0).min(1.0);
        if self.m < 0.0 {
            ::std::mem::swap(&mut lower_t, &mut upper_t);
        }
        self.i += 1;
        if lower_t != upper_t {
            let p = &self.l.p;
            let v = p[1] - p[0];
            Some(Some(Line {
                p: [p[0] + v * lower_t,
                    p[0] + v * upper_t]
            }).into_iter())
        } else {
            Some(None.into_iter())
        }
    }
}

impl SliceUp for Line {
    type PerSlice = LineIter;
    type Out = LineSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].x - p[0].x,
            c: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> LineSliceIter {
        let p = &self.p;
        LineSliceIter {
            l: *self,
            planes: planes,
            i: 0,
            m: p[1].y - p[0].y,
            c: p[0].y
        }
    }
}

type CurveIter = arrayvec::IntoIter<[Curve; 2]>;

struct CurveSliceIter {
    curve: Curve,
    planes: PlaneSet,
    i: usize,
    a: f32,
    b: f32,
    c_shift: f32
}

impl Iterator for CurveSliceIter {
    type Item = CurveIter;
    fn next(&mut self) -> Option<Self::Item> {
        use arrayvec::ArrayVec;
        use geometry::RealQuadraticSolution as RQS;
        use geometry::solve_quadratic_real as solve;
        use geometry::Cut;
        if self.i >= self.planes.count {
            return None
        }
        let lower = self.i as f32;
        self.i += 1;
        let upper = lower + self.planes.step;
        let lower_d = self.planes.start + self.planes.step * lower;
        let upper_d = self.planes.start + self.planes.step * upper;
        let l_sol = solve(self.a, self.b, self.c_shift - lower_d);
        let u_sol = solve(self.a, self.b, self.c_shift - upper_d);
        let mut result = ArrayVec::<[Curve; 2]>::new();
        match (l_sol.in_order(), u_sol.in_order()) {
            (RQS::Two(a, b), RQS::Two(c, d)) => {
                // Two pieces
                let (a, b, c, d) = if self.a > 0.0 {
                    (c, a, b, d)
                } else {
                    (a, c, d, b)
                };
                let (a, b, c, d) = (a.min(1.0).max(0.0),
                                    b.min(1.0).max(0.0),
                                    c.min(1.0).max(0.0),
                                    d.min(1.0).max(0.0));
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
                if c != d {
                    result.push(self.curve.cut_from_to(c, d));
                }
            }
            (RQS::Two(a, b), RQS::None) |
            (RQS::Two(a, b), RQS::Touch(_)) |
            (RQS::None, RQS::Two(a, b)) |
            (RQS::Touch(_), RQS::Two(a, b)) |
            (RQS::One(a), RQS::One(b)) => {
                // One piece
                let (a, b) = if a > b { (b, a) } else { (a, b) };
                let a = a.min(1.0).max(0.0);
                let b = b.min(1.0).max(0.0);
                if a != b {
                    result.push(self.curve.cut_from_to(a, b));
                }
            }
            (RQS::All, RQS::None) |
            (RQS::None, RQS::All) => {
                // coincident with one plane
                result.push(self.curve);
            }
            (RQS::None, RQS::None) => if self.a == 0.0 && self.b == 0.0
                && self.c_shift >= lower_d && self.c_shift <= upper_d
            {
                // parallel to planes, inbetween
                result.push(self.curve);
            },
            _ => unreachable!() // impossible
        }
        //println!("{:?}", result);
        Some(result.into_iter())
    }
}

#[derive(Debug)]
struct PlaneSet {
    start: f32,
    step: f32,
    count: usize
}

impl SliceUp for Curve {
    type PerSlice = CurveIter;
    type Out = CurveSliceIter;
    fn slice_up_x(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].x - 2.0 * p[1].x + p[2].x,
            b: 2.0 * (p[1].x - p[0].x),
            c_shift: p[0].x
        }
    }
    fn slice_up_y(&self, planes: PlaneSet) -> CurveSliceIter {
        let p = &self.p;
        CurveSliceIter {
            curve: *self,
            planes: planes,
            i: 0,
            a: p[0].y - 2.0 * p[1].y + p[2].y,
            b: 2.0 * (p[1].y - p[0].y),
            c_shift: p[0].y
        }
    }
}

pub fn rasterize<O: FnMut(u32, u32, f32)>(lines: &[Line], curves: &[Curve],
                                          width: u32, height: u32,
                                          mut output: O) {
    use ::std::collections::HashMap;
    let mut lines: Vec<_> = lines.iter().map(|&l| (l, l.bounding_box())).collect();
    lines[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut curves: Vec<_> = curves.iter().map(|&c| (c, c.bounding_box())).collect();
    curves[..].sort_by(|&(_, ref a), &(_, ref b)| a.min.y.partial_cmp(&b.min.y).unwrap());
    let mut y = 0;
    let mut next_line = 0; let mut next_curve = 0;
    let mut active_lines_y  = HashMap::new(); let mut active_curves_y = HashMap::new();
    let mut active_lines_x  = HashMap::new(); let mut active_curves_x = HashMap::new();
    let mut scanline_lines = Vec::new();
    let mut lines_to_remove = Vec::new();
    let mut scanline_curves = Vec::new();
    let mut curves_to_remove = Vec::new();
    while y < height && (next_line != lines.len() || next_curve != curves.len()
        || active_lines_y.len() > 0 || active_curves_y.len() > 0)
    {
        let lower = y as f32;
        let upper = (y + 1) as f32;
        // Add newly active segments
        for &(ref line, ref bb) in lines[next_line..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_lines_y.insert(next_line, line.slice_up_y(planes));
            next_line += 1;
        }
        for &(ref curve, ref bb) in curves[next_curve..].iter().take_while(|p| p.1.min.y < upper) {
            let planes = PlaneSet {
                start: lower,
                step: 1.0,
                count: (bb.max.y.ceil() - lower).max(1.0) as usize
            };
            active_curves_y.insert(next_curve, curve.slice_up_y(planes));
            next_curve += 1;
        }
        // get y sliced segments for this scanline
        scanline_lines.clear();
        scanline_curves.clear();
        for (k, itr) in active_lines_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for line in itr {
                    scanline_lines.push((line, line.x_bounds()))
                }
            } else {
                lines_to_remove.push(*k);
            }
        }
        for (k, itr) in active_curves_y.iter_mut() {
            if let Some(itr) = itr.next() {
                for curve in itr {
                    scanline_curves.push((curve, curve.x_bounds()))
                }
            } else {
                curves_to_remove.push(*k);
            }
        }
        // remove deactivated segments
        for k in lines_to_remove.drain(..) {
            active_lines_y.remove(&k);
        }
        for k in curves_to_remove.drain(..) {
            active_curves_y.remove(&k);
        }
        // sort scanline for traversal
        scanline_lines.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        scanline_curves.sort_by(|a, b| (a.1).0.partial_cmp(&(b.1).0).unwrap());
        // Iterate through x, slice scanline segments into each cell. Evaluate, accumulate and output.
        {
            let mut next_line = 0; let mut next_curve = 0;
            let mut x = 0;
            let mut acc = 0.0;
            active_lines_x.clear();
            active_curves_x.clear();
            while x < width && (next_line != scanline_lines.len() || next_curve != scanline_curves.len()
                || active_lines_x.len() > 0 || active_curves_x.len() > 0)
            {
                let offset = vector(x as f32, y as f32);
                let lower = x as f32;
                let upper = (x+1) as f32;
                //add newly active segments
                for &(ref line, (_, ref max)) in scanline_lines[next_line..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_lines_x.insert(next_line, line.slice_up_x(planes));
                    next_line += 1;
                }
                for &(ref curve, (_, ref max)) in scanline_curves[next_curve..].iter()
                    .take_while(|p| (p.1).0 < upper)
                {
                    let planes = PlaneSet {
                        start: lower,
                        step: 1.0,
                        count: (max.ceil() - lower).max(1.0) as usize
                    };
                    active_curves_x.insert(next_curve, curve.slice_up_x(planes));
                    next_curve += 1;
                }
                //process x sliced segments for this pixel
                let mut pixel_value = acc;
                let mut pixel_acc = 0.0;
                for (k, itr) in active_lines_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut line in itr {
                            let p = &mut line.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;

                            let a = p[0].y - p[1].y;
                            let v = (1.0 - (p[0].x + p[1].x) * 0.5) * a;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        lines_to_remove.push(*k);
                    }
                }
                for (k, itr) in active_curves_x.iter_mut() {
                    if let Some(itr) = itr.next() {
                        for mut curve in itr {
                            let p = &mut curve.p;
                            p[0] = p[0] - offset;
                            p[1] = p[1] - offset;
                            p[2] = p[2] - offset;
                            let a = p[0].y - p[2].y;
                            let b = p[0].y - p[1].y;
                            let c = p[1].y - p[2].y;
                            let v = (b*(6.0 - 3.0*p[0].x - 2.0*p[1].x -     p[2].x) +
                                     c*(6.0 -     p[0].x - 2.0*p[1].x - 3.0*p[2].x)) / 6.0;
                            pixel_value += v;
                            pixel_acc += a;
                        }
                    } else {
                        curves_to_remove.push(*k);
                    }
                }
                //output
                output(x, y, pixel_value.abs());
                acc += pixel_acc;
                // remove deactivated segments
                for k in lines_to_remove.drain(..) {
                    active_lines_x.remove(&k);
                }
                for k in curves_to_remove.drain(..) {
                    active_curves_x.remove(&k);
                }
                x += 1;
            }
            // fill remaining pixels
            for x in x..width {
                output(x, y, acc.abs());
            }
        }
        y += 1;
    }
    // fill remaining scanlines with 0.0
    for y in y..height {
        for x in 0..width {
            output(x, y, 0.0);
        }
    }
}
<|endoftext|>