<commit_before>use image::RgbImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbCodec;

impl Codec for RgbCodec
{
    type Input = RgbImage;
    type Mode = RgbMode;

    fn encode<R: Rng>(
        source: &mut RgbImage,
        payload: &[u8],
        mode: RgbMode,
        mut rng: R)
    {
        let px_chunk = 24;
        let by_chunk = 3;

        // iterate over pixels mutably
        for (mut pixels, bytes) in source.pixels_mut()
            // ~2.7 pixels per byte, so instead by use 24-pixel
            // and 3-byte chunks
            .chunks(8).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk 3 bytes
            .zip(payload.iter().map(|x| *x)
                 .chunks(3).into_iter()
                 // make them also vectors
                 .map(|ch| ch.collect::<Vec<_>>()))
        {
            // if any of the chunks are short, abort
            if pixels.len() != 8 || bytes.len() != 3
            {
                return;
            }

            match mode
            {
                RgbMode::All =>
                {
                    let rng = &mut rng;
                    // i looked for a better way...
                    fix_u8(&mut pixels[0].data[0], get_bit(bytes[0], 0), rng);
                    fix_u8(&mut pixels[0].data[1], get_bit(bytes[0], 1), rng);
                    fix_u8(&mut pixels[0].data[2], get_bit(bytes[0], 2), rng);
                    fix_u8(&mut pixels[1].data[0], get_bit(bytes[0], 3), rng);
                    fix_u8(&mut pixels[1].data[1], get_bit(bytes[0], 4), rng);
                    fix_u8(&mut pixels[1].data[2], get_bit(bytes[0], 5), rng);
                    fix_u8(&mut pixels[2].data[0], get_bit(bytes[0], 6), rng);
                    fix_u8(&mut pixels[2].data[1], get_bit(bytes[0], 7), rng);

                    fix_u8(&mut pixels[2].data[2], get_bit(bytes[1], 0), rng);
                    fix_u8(&mut pixels[3].data[0], get_bit(bytes[1], 1), rng);
                    fix_u8(&mut pixels[3].data[1], get_bit(bytes[1], 2), rng);
                    fix_u8(&mut pixels[3].data[2], get_bit(bytes[1], 3), rng);
                    fix_u8(&mut pixels[4].data[0], get_bit(bytes[1], 4), rng);
                    fix_u8(&mut pixels[4].data[1], get_bit(bytes[1], 5), rng);
                    fix_u8(&mut pixels[4].data[2], get_bit(bytes[1], 6), rng);
                    fix_u8(&mut pixels[5].data[0], get_bit(bytes[1], 7), rng);

                    fix_u8(&mut pixels[5].data[1], get_bit(bytes[2], 0), rng);
                    fix_u8(&mut pixels[5].data[2], get_bit(bytes[2], 1), rng);
                    fix_u8(&mut pixels[6].data[0], get_bit(bytes[2], 2), rng);
                    fix_u8(&mut pixels[6].data[1], get_bit(bytes[2], 3), rng);
                    fix_u8(&mut pixels[6].data[2], get_bit(bytes[2], 4), rng);
                    fix_u8(&mut pixels[7].data[0], get_bit(bytes[2], 5), rng);
                    fix_u8(&mut pixels[7].data[1], get_bit(bytes[2], 6), rng);
                    fix_u8(&mut pixels[7].data[2], get_bit(bytes[2], 7), rng);
                }
            }
        }
    }

    fn decode(
        source: &RgbImage,
        payload: &mut [u8],
        len: usize,
        mode: RgbMode)
    {
        unimplemented!()
    }

    fn estimate(
        source: &RgbImage,
        mode: RgbMode) -> Option<usize>
    {
        Some(match mode
        {
            RgbMode::All =>
                source.width() as usize * source.height() as usize / 3
        })
    }

}

#[derive(Copy, Clone)]
pub enum RgbMode
{
    All,
}

use std::default::Default;

impl Default for RgbMode
{
    fn default() -> RgbMode
    {
        RgbMode::All
    }
}

use std::str::FromStr;

impl FromStr for RgbMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbMode, ()>
    {
        if s == "all"
        {
            Ok(RgbMode::All)
        }
        else
        {
            Err(())
        }
    }
}
<commit_msg>Implemented Rgb decoding<commit_after>use image::RgbImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbCodec;

impl Codec for RgbCodec
{
    type Input = RgbImage;
    type Mode = RgbMode;

    fn encode<R: Rng>(
        source: &mut RgbImage,
        payload: &[u8],
        _mode: RgbMode,
        mut rng: R)
    {
        // iterate over pixels mutably
        for (mut pixels, bytes) in source.pixels_mut()
            // ~2.7 pixels per byte, so instead by use 24-pixel
            // and 3-byte chunks
            .chunks(8).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk 3 bytes
            .zip(payload.iter().map(|x| *x)
                 .chunks(3).into_iter()
                 // make them also vectors
                 .map(|ch| ch.collect::<Vec<_>>()))
        {
            // if any of the chunks are short, abort
            if pixels.len() != 8 || bytes.len() != 3
            {
                return;
            }

            let rng = &mut rng;
            // i looked for a better way...
            fix_u8(&mut pixels[0].data[0], get_bit(bytes[0], 0), rng);
            fix_u8(&mut pixels[0].data[1], get_bit(bytes[0], 1), rng);
            fix_u8(&mut pixels[0].data[2], get_bit(bytes[0], 2), rng);
            fix_u8(&mut pixels[1].data[0], get_bit(bytes[0], 3), rng);
            fix_u8(&mut pixels[1].data[1], get_bit(bytes[0], 4), rng);
            fix_u8(&mut pixels[1].data[2], get_bit(bytes[0], 5), rng);
            fix_u8(&mut pixels[2].data[0], get_bit(bytes[0], 6), rng);
            fix_u8(&mut pixels[2].data[1], get_bit(bytes[0], 7), rng);

            fix_u8(&mut pixels[2].data[2], get_bit(bytes[1], 0), rng);
            fix_u8(&mut pixels[3].data[0], get_bit(bytes[1], 1), rng);
            fix_u8(&mut pixels[3].data[1], get_bit(bytes[1], 2), rng);
            fix_u8(&mut pixels[3].data[2], get_bit(bytes[1], 3), rng);
            fix_u8(&mut pixels[4].data[0], get_bit(bytes[1], 4), rng);
            fix_u8(&mut pixels[4].data[1], get_bit(bytes[1], 5), rng);
            fix_u8(&mut pixels[4].data[2], get_bit(bytes[1], 6), rng);
            fix_u8(&mut pixels[5].data[0], get_bit(bytes[1], 7), rng);

            fix_u8(&mut pixels[5].data[1], get_bit(bytes[2], 0), rng);
            fix_u8(&mut pixels[5].data[2], get_bit(bytes[2], 1), rng);
            fix_u8(&mut pixels[6].data[0], get_bit(bytes[2], 2), rng);
            fix_u8(&mut pixels[6].data[1], get_bit(bytes[2], 3), rng);
            fix_u8(&mut pixels[6].data[2], get_bit(bytes[2], 4), rng);
            fix_u8(&mut pixels[7].data[0], get_bit(bytes[2], 5), rng);
            fix_u8(&mut pixels[7].data[1], get_bit(bytes[2], 6), rng);
            fix_u8(&mut pixels[7].data[2], get_bit(bytes[2], 7), rng);
        }
    }

    fn decode(
        source: &RgbImage,
        payload: &mut [u8],
        len: usize,
        _mode: RgbMode)
    {
        assert!(len <= payload.len());

        let exlen = len + (len % 3);

        // iterate over the pixels
        for (index, pixels) in source.pixels()
            // grab them in chunks of 8
            .chunks(8).into_iter()
            // make them vectors
            .map(|ch| ch.collect::<Vec<_>>())
            .take(exlen / 3) // exlen is always exactly divisible by 3
            .enumerate()
        {
            if pixels.len() != 8
            {
                return;
            }

            let mut byte = 0u8;
            byte = set_bit(byte, 0, pixels[0].data[0] % 2 == 1);
            byte = set_bit(byte, 1, pixels[0].data[1] % 2 == 1);
            byte = set_bit(byte, 2, pixels[0].data[2] % 2 == 1);
            byte = set_bit(byte, 3, pixels[1].data[0] % 2 == 1);
            byte = set_bit(byte, 4, pixels[1].data[1] % 2 == 1);
            byte = set_bit(byte, 5, pixels[1].data[2] % 2 == 1);
            byte = set_bit(byte, 6, pixels[2].data[0] % 2 == 1);
            byte = set_bit(byte, 7, pixels[2].data[1] % 2 == 1);

            if index * 3 < len
            {
                payload[index * 3] = byte;
            }

            byte = set_bit(byte, 0, pixels[2].data[2] % 2 == 1);
            byte = set_bit(byte, 1, pixels[3].data[0] % 2 == 1);
            byte = set_bit(byte, 2, pixels[3].data[1] % 2 == 1);
            byte = set_bit(byte, 3, pixels[3].data[2] % 2 == 1);
            byte = set_bit(byte, 4, pixels[4].data[0] % 2 == 1);
            byte = set_bit(byte, 5, pixels[4].data[1] % 2 == 1);
            byte = set_bit(byte, 6, pixels[4].data[2] % 2 == 1);
            byte = set_bit(byte, 7, pixels[5].data[0] % 2 == 1);

            if index * 3 + 1 < len
            {
                payload[index * 3 + 1] = byte;
            }

            byte = set_bit(byte, 0, pixels[5].data[1] % 2 == 1);
            byte = set_bit(byte, 1, pixels[5].data[2] % 2 == 1);
            byte = set_bit(byte, 2, pixels[6].data[0] % 2 == 1);
            byte = set_bit(byte, 3, pixels[6].data[1] % 2 == 1);
            byte = set_bit(byte, 4, pixels[6].data[2] % 2 == 1);
            byte = set_bit(byte, 5, pixels[7].data[0] % 2 == 1);
            byte = set_bit(byte, 6, pixels[7].data[1] % 2 == 1);
            byte = set_bit(byte, 7, pixels[7].data[2] % 2 == 1);

            if index * 3 + 2 < len
            {
                payload[index * 3 + 2] = byte;
            }
        }
    }

    fn estimate(
        source: &RgbImage,
        mode: RgbMode) -> Option<usize>
    {
        Some(match mode
        {
            RgbMode::All =>
                source.width() as usize * source.height() as usize / 3
        })
    }

}

#[derive(Copy, Clone)]
pub enum RgbMode
{
    All,
}

use std::default::Default;

impl Default for RgbMode
{
    fn default() -> RgbMode
    {
        RgbMode::All
    }
}

use std::str::FromStr;

impl FromStr for RgbMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbMode, ()>
    {
        if s == "all"
        {
            Ok(RgbMode::All)
        }
        else
        {
            Err(())
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

fn count_word(line: String) -> isize {
	let mut nb_word_found = 0;
	let mut last_char_was_word = false;
	for c in line.chars() {
		let char_is_word = c.is_alphanumeric();
		if char_is_word && !last_char_was_word {
			nb_word_found += 1;
//			write!( std::io::stdout(), "{}", '\n' ).unwrap();
		}
		last_char_was_word = char_is_word;
//		if char_is_word {
//			write!( std::io::stdout(), "{}", c ).unwrap();
//		}
	}
	nb_word_found
}

fn run_app() -> Result<(), std::io::Error> {
	let path = "Cargo.toml";
	let file = File::open(path);
	let file = match file {
		Ok(file) => file,
		Err(err) => return Err(err), // Put nicer error message with path that was not found
	};
	let reader = BufReader::new(file);
	let mut total_word_count = 0;
	for line in reader.lines() {
		match line {
			Ok(line) => total_word_count += count_word( line ),
			Err(err) => return Err(err),
		};

	}
	println!("{}", total_word_count);
    Ok(())
}

fn main() {
    ::std::process::exit(match run_app() {
       Ok(_) => 0,
       Err(err) => {
           writeln!(std::io::stderr(), "error: {:?}", err).unwrap();
           1
       }
    });
}
<commit_msg>Use iterator.map instead of foreach.<commit_after>use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

fn count_word(line: String) -> isize {
	let mut nb_word_found = 0;
	let mut last_char_was_word = false;
	for c in line.chars() {
		let char_is_word = c.is_alphanumeric();
		if char_is_word && !last_char_was_word {
			nb_word_found += 1;
//			write!( std::io::stdout(), "{}", '\n' ).unwrap();
		}
		last_char_was_word = char_is_word;
//		if char_is_word {
//			write!( std::io::stdout(), "{}", c ).unwrap();
//		}
	}
	nb_word_found
}

fn run_app() -> Result<(), std::io::Error> {
	let path = "Cargo.toml";
	let file = File::open(path);
	let file = match file {
		Ok(file) => file,
		Err(err) => return Err(err), // Put nicer error message with path that was not found
	};
	let reader = BufReader::new(file);
	let total_word_count: Result<isize, std::io::Error> = reader.lines().map(
		|line| match line {
			Ok(line) => Ok(count_word( line )),
			Err(err) => Err(err),
		}
		).sum();
	match total_word_count {
		Ok(count) => println!("{}", count),
		Err(err) => return Err(err),
	};

    Ok(())
}

fn main() {
    ::std::process::exit(match run_app() {
       Ok(_) => 0,
       Err(err) => {
           writeln!(std::io::stderr(), "error: {:?}", err).unwrap();
           1
       }
    });
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla
//
// 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::fmt::{Display, Formatter};

/// A simplification of Clojure's Symbol.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct PlainSymbol(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedSymbol {
    // We derive PartialOrd, which implements a lexicographic based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
/// This concept is imported from Clojure, as it features in EDN and the query
/// syntax that we use.
///
/// Clojure's constraints are looser than ours, allowing empty namespaces or
/// names:
///
/// ```clojure
/// user=> (keyword "" "")
/// :/
/// user=> (keyword "foo" "")
/// :foo/
/// user=> (keyword "" "bar")
/// :/bar
/// ```
///
/// We think that's nonsense, so we only allow keywords like `:bar` and `:foo/bar`,
/// with both namespace and main parts containing no whitespace and no colon or slash:
///
/// ```rust
/// # use edn::symbols::Keyword;
/// # use edn::symbols::NamespacedKeyword;
/// let bar     = Keyword::new("bar");                         // :bar
/// let foo_bar = NamespacedKeyword::new("foo", "bar");        // :foo/bar
/// assert_eq!("bar", bar.0);
/// assert_eq!("bar", foo_bar.name);
/// assert_eq!("foo", foo_bar.namespace);
/// ```
///
/// If you're not sure whether your input is well-formed, you should use a
/// parser or a reader function first to validate. TODO: implement `read`.
///
/// Callers are expected to follow these rules:
/// http://www.clojure.org/reference/reader#_symbols
///
/// Future: fast equality (interning?) for keywords.
///
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct Keyword(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedKeyword {
    // We derive PartialOrd, which implements a lexicographic order based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

impl PlainSymbol {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Symbols cannot be unnamed.");

        PlainSymbol(n)
    }
}

impl NamespacedSymbol {
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();

        assert!(!n.is_empty(), "Symbols cannot be unnamed.");
        assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace.");

        NamespacedSymbol { name: n, namespace: ns }
    }
}

impl Keyword {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");

        Keyword(n)
    }
}

impl NamespacedKeyword {
    /// Creates a new `NamespacedKeyword`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let keyword = NamespacedKeyword::new("foo", "bar");
    /// assert_eq!(keyword.to_string(), ":foo/bar");
    /// ```
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");
        assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace.");

        // TODO: debug asserts to ensure that neither field matches [ :/].
        NamespacedKeyword {
            name: n,
            namespace: ns,
        }
    }

    /// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example,
    /// the two following snippets are identical:
    ///
    /// ```edn
    /// [?y :person/friend ?x]
    /// [?x :person/hired ?y]
    ///
    /// [?y :person/friend ?x]
    /// [?y :person/_hired ?x]
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(!NamespacedKeyword::new("foo", "bar").is_backward());
    /// assert!(NamespacedKeyword::new("foo", "_bar").is_backward());
    /// ```
    #[inline]
    pub fn is_backward(&self) -> bool {
        self.name.starts_with("_")
    }

    /// Whether this `NamespacedKeyword` should be interpreted in forward order.
    /// See `symbols::NamespacedKeyword::is_backwards`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(NamespacedKeyword::new("foo", "bar").is_forward());
    /// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward());
    /// ```
    #[inline]
    pub fn is_forward(&self) -> bool {
        !self.is_backward()
    }

    /// Returns a `NamespacedKeyword` with the same namespace and a
    /// 'backward' name. See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let nsk = NamespacedKeyword::new("foo", "bar");
    /// assert!(!nsk.is_backward());
    /// assert_eq!(":foo/bar", nsk.to_string());
    ///
    /// let reversed = nsk.to_reverse();
    /// assert!(reversed.is_backward());
    /// assert_eq!(":foo/_bar", reversed.to_string());
    /// ```
    pub fn to_reverse(&self) -> NamespacedKeyword {
        let name = if self.is_backward() {
            self.name[1..].to_string()
        } else {
            format!("{}{}", "_", self.name)
        };

        NamespacedKeyword {
            name: name,
            namespace: self.namespace.clone(),
        }
    }
}

//
// Note that we don't currently do any escaping.
//

impl Display for PlainSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("baz", PlainSymbol::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Display for NamespacedSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedSymbol;
    /// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}/{}", self.namespace, self.name)
    }
}

impl Display for Keyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::Keyword;
    /// assert_eq!(":baz", Keyword::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}", self.0)
    }
}

impl Display for NamespacedKeyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string());
    /// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reverse().to_string());
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reverse().to_reverse().to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}/{}", self.namespace, self.name)
    }
}
<commit_msg>Minor EDN cleanup. (#217) r=jsantell<commit_after>// Copyright 2016 Mozilla
//
// 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::fmt::{Display, Formatter};

/// A simplification of Clojure's Symbol.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct PlainSymbol(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedSymbol {
    // We derive PartialOrd, which implements a lexicographic based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
/// This concept is imported from Clojure, as it features in EDN and the query
/// syntax that we use.
///
/// Clojure's constraints are looser than ours, allowing empty namespaces or
/// names:
///
/// ```clojure
/// user=> (keyword "" "")
/// :/
/// user=> (keyword "foo" "")
/// :foo/
/// user=> (keyword "" "bar")
/// :/bar
/// ```
///
/// We think that's nonsense, so we only allow keywords like `:bar` and `:foo/bar`,
/// with both namespace and main parts containing no whitespace and no colon or slash:
///
/// ```rust
/// # use edn::symbols::Keyword;
/// # use edn::symbols::NamespacedKeyword;
/// let bar     = Keyword::new("bar");                         // :bar
/// let foo_bar = NamespacedKeyword::new("foo", "bar");        // :foo/bar
/// assert_eq!("bar", bar.0);
/// assert_eq!("bar", foo_bar.name);
/// assert_eq!("foo", foo_bar.namespace);
/// ```
///
/// If you're not sure whether your input is well-formed, you should use a
/// parser or a reader function first to validate. TODO: implement `read`.
///
/// Callers are expected to follow these rules:
/// http://www.clojure.org/reference/reader#_symbols
///
/// Future: fast equality (interning?) for keywords.
///
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct Keyword(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedKeyword {
    // We derive PartialOrd, which implements a lexicographic order based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

impl PlainSymbol {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Symbols cannot be unnamed.");

        PlainSymbol(n)
    }

    /// Return the name of the symbol without any leading '?' or '$'.
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("foo", PlainSymbol::new("?foo").plain_name());
    /// assert_eq!("foo", PlainSymbol::new("$foo").plain_name());
    /// assert_eq!("!foo", PlainSymbol::new("!foo").plain_name());
    /// ```
    pub fn plain_name(&self) -> &str {
        if self.is_src_symbol() || self.is_var_symbol() {
            &self.0[1..]
        } else {
            &self.0
        }
    }

    #[inline]
    pub fn is_var_symbol(&self) -> bool {
        self.0.starts_with('?')
    }

    #[inline]
    pub fn is_src_symbol(&self) -> bool {
        self.0.starts_with('$')
    }
}

impl NamespacedSymbol {
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();

        assert!(!n.is_empty(), "Symbols cannot be unnamed.");
        assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace.");

        NamespacedSymbol { name: n, namespace: ns }
    }
}

impl Keyword {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");

        Keyword(n)
    }
}

impl NamespacedKeyword {
    /// Creates a new `NamespacedKeyword`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let keyword = NamespacedKeyword::new("foo", "bar");
    /// assert_eq!(keyword.to_string(), ":foo/bar");
    /// ```
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");
        assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace.");

        // TODO: debug asserts to ensure that neither field matches [ :/].
        NamespacedKeyword {
            name: n,
            namespace: ns,
        }
    }

    /// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example,
    /// the two following snippets are identical:
    ///
    /// ```edn
    /// [?y :person/friend ?x]
    /// [?x :person/hired ?y]
    ///
    /// [?y :person/friend ?x]
    /// [?y :person/_hired ?x]
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(!NamespacedKeyword::new("foo", "bar").is_backward());
    /// assert!(NamespacedKeyword::new("foo", "_bar").is_backward());
    /// ```
    #[inline]
    pub fn is_backward(&self) -> bool {
        self.name.starts_with("_")
    }

    /// Whether this `NamespacedKeyword` should be interpreted in forward order.
    /// See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(NamespacedKeyword::new("foo", "bar").is_forward());
    /// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward());
    /// ```
    #[inline]
    pub fn is_forward(&self) -> bool {
        !self.is_backward()
    }

    /// Returns a `NamespacedKeyword` with the same namespace and a
    /// 'backward' name. See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let nsk = NamespacedKeyword::new("foo", "bar");
    /// assert!(!nsk.is_backward());
    /// assert_eq!(":foo/bar", nsk.to_string());
    ///
    /// let reversed = nsk.to_reversed();
    /// assert!(reversed.is_backward());
    /// assert_eq!(":foo/_bar", reversed.to_string());
    /// ```
    pub fn to_reversed(&self) -> NamespacedKeyword {
        let name = if self.is_backward() {
            self.name[1..].to_string()
        } else {
            format!("{}{}", "_", self.name)
        };

        NamespacedKeyword {
            name: name,
            namespace: self.namespace.clone(),
        }
    }
}

//
// Note that we don't currently do any escaping.
//

impl Display for PlainSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("baz", PlainSymbol::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Display for NamespacedSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedSymbol;
    /// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}/{}", self.namespace, self.name)
    }
}

impl Display for Keyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::Keyword;
    /// assert_eq!(":baz", Keyword::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}", self.0)
    }
}

impl Display for NamespacedKeyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string());
    /// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_string());
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_reversed().to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}/{}", self.namespace, self.name)
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use crate::decoder::{Decoder, MAX_COMPONENTS};
use crate::error::{Error, Result};
use crate::huffman::HuffmanDecoder;
use crate::marker::Marker;
use crate::parser::Predictor;
use crate::parser::{Component, FrameInfo, ScanInfo};

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Vec<Vec<u16>>)> {
        let ncomp = scan.component_indices.len();
        let npixel = frame.image_size.height as usize * frame.image_size.width as usize;
        assert!(ncomp <= MAX_COMPONENTS);
        let mut results = vec![vec![0u16; npixel]; ncomp];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut mcus_left_until_restart = self.restart_interval;
        let mut expected_rst_num = 0;
        let mut ra = [0u16; MAX_COMPONENTS];
        let mut rb = [0u16; MAX_COMPONENTS];
        let mut rc = [0u16; MAX_COMPONENTS];

        let width = frame.image_size.width as usize;
        let height = frame.image_size.height as usize;

        let mut differences = vec![Vec::with_capacity(npixel); ncomp];
        for _mcu_y in 0..height {
            for _mcu_x in 0..width {
                if self.restart_interval > 0 {
                    if mcus_left_until_restart == 0 {
                        match huffman.take_marker(reader)? {
                            Some(Marker::RST(n)) => {
                                if n != expected_rst_num {
                                    return Err(Error::Format(format!(
                                        "found RST{} where RST{} was expected",
                                        n, expected_rst_num
                                    )));
                                }

                                huffman.reset();

                                expected_rst_num = (expected_rst_num + 1) % 8;
                                mcus_left_until_restart = self.restart_interval;
                            }
                            Some(marker) => {
                                return Err(Error::Format(format!(
                                    "found marker {:?} inside scan where RST{} was expected",
                                    marker, expected_rst_num
                                )))
                            }
                            None => {
                                return Err(Error::Format(format!(
                                    "no marker found where RST{} was expected",
                                    expected_rst_num
                                )))
                            }
                        }
                    }

                    mcus_left_until_restart -= 1;
                }

                for (i, _component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)? as i32,
                        16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    differences[i].push(diff);
                }
            }
        }

        if scan.predictor_selection == Predictor::Ra {
            for (i, _component) in components.iter().enumerate() {
                // calculate the top left pixel
                let diff = differences[i][0];
                let prediction = 1 << (frame.precision - scan.point_transform - 1) as i32;
                let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                let result = result << scan.point_transform;
                results[i][0] = result;

                // calculate leftmost column, using top pixel as predictor
                let mut previous = result;
                for mcu_y in 1..height {
                    let diff = differences[i][mcu_y * width];
                    let prediction = previous as i32;
                    let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                    let result = result << scan.point_transform;
                    results[i][mcu_y * width] = result;
                    previous = result;
                }

                // calculate rows, using left pixel as predictor
                for mcu_y in 0..height {
                    for mcu_x in 1..width {
                        let diff = differences[i][mcu_y * width + mcu_x];
                        let prediction = results[i][mcu_y * width + mcu_x - 1] as i32;
                        let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                        let result = result << scan.point_transform;
                        results[i][mcu_y * width + mcu_x] = result;
                    }
                }
            }
        } else {
            for mcu_y in 0..height {
                for mcu_x in 0..width {
                    for (i, _component) in components.iter().enumerate() {
                        let diff = differences[i][mcu_y * width + mcu_x];

                        // The following lines could be further optimized, e.g. moving the checks
                        // and updates of the previous values into the prediction function or
                        // iterating such that diagonals with mcu_x + mcu_y = const are computed at
                        // the same time to exploit independent predictions in this case
                        if mcu_x > 0 {
                            ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1];
                        }
                        if mcu_y > 0 {
                            rb[i] =
                                results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                            if mcu_x > 0 {
                                rc[i] = results[i]
                                    [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                            }
                        }
                        let prediction = predict(
                            ra[i] as i32,
                            rb[i] as i32,
                            rc[i] as i32,
                            scan.predictor_selection,
                            scan.point_transform,
                            frame.precision,
                            mcu_x,
                            mcu_y,
                            self.restart_interval > 0
                                && mcus_left_until_restart == self.restart_interval - 1,
                        );
                        let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                        results[i][mcu_y * width + mcu_x] = result << scan.point_transform;
                    }
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }
        Ok((marker, results))
    }
}

/// H.1.2.1
fn predict(
    ra: i32,
    rb: i32,
    rc: i32,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> i32 {
    if (ix == 0 && iy == 0) || restart {
        // start of first line or restart
        1 << (input_precision - point_transform - 1)
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + ((rb - rc) >> 1),
            Predictor::RaRbRc3 => rb + ((ra - rc) >> 1),
            Predictor::RaRb => (ra + rb) / 2,
        }
    }
}

pub fn compute_image_lossless(frame: &FrameInfo, mut data: Vec<Vec<u16>>) -> Result<Vec<u8>> {
    if data.is_empty() || data.iter().any(Vec::is_empty) {
        return Err(Error::Format("not all components have data".to_owned()));
    }
    let output_size = frame.output_size;
    let components = &frame.components;
    let ncomp = components.len();

    if ncomp == 1 {
        let decoded = convert_to_u8(frame, data.remove(0));
        Ok(decoded)
    } else {
        let mut decoded: Vec<u16> =
            vec![0u16; ncomp * output_size.width as usize * output_size.height as usize];
        for (x, chunk) in decoded.chunks_mut(ncomp).enumerate() {
            for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() {
                chunk[i] = component_data[x];
            }
        }
        let decoded = convert_to_u8(frame, decoded);
        Ok(decoded)
    }
}

fn convert_to_u8(frame: &FrameInfo, data: Vec<u16>) -> Vec<u8> {
    if frame.precision == 8 {
        data.iter().map(|x| *x as u8).collect()
    } else {
        // we output native endian, which is the standard for image-rs
        let ne_bytes: Vec<_> = data.iter().map(|x| x.to_ne_bytes()).collect();
        ne_bytes.concat()
    }
}
<commit_msg>Mitigate panic due to arithmetic overflow in lossless module<commit_after>use std::io::Read;
use crate::decoder::{Decoder, MAX_COMPONENTS};
use crate::error::{Error, Result};
use crate::huffman::HuffmanDecoder;
use crate::marker::Marker;
use crate::parser::Predictor;
use crate::parser::{Component, FrameInfo, ScanInfo};

impl<R: Read> Decoder<R> {
    /// decode_scan_lossless
    pub fn decode_scan_lossless(
        &mut self,
        frame: &FrameInfo,
        scan: &ScanInfo,
    ) -> Result<(Option<Marker>, Vec<Vec<u16>>)> {
        let ncomp = scan.component_indices.len();
        let npixel = frame.image_size.height as usize * frame.image_size.width as usize;
        assert!(ncomp <= MAX_COMPONENTS);
        let mut results = vec![vec![0u16; npixel]; ncomp];

        let components: Vec<Component> = scan
            .component_indices
            .iter()
            .map(|&i| frame.components[i].clone())
            .collect();

        // Verify that all required huffman tables has been set.
        if scan
            .dc_table_indices
            .iter()
            .any(|&i| self.dc_huffman_tables[i].is_none())
        {
            return Err(Error::Format(
                "scan makes use of unset dc huffman table".to_owned(),
            ));
        }

        let mut huffman = HuffmanDecoder::new();
        let reader = &mut self.reader;
        let mut mcus_left_until_restart = self.restart_interval;
        let mut expected_rst_num = 0;
        let mut ra = [0u16; MAX_COMPONENTS];
        let mut rb = [0u16; MAX_COMPONENTS];
        let mut rc = [0u16; MAX_COMPONENTS];

        let width = frame.image_size.width as usize;
        let height = frame.image_size.height as usize;

        let mut differences = vec![Vec::with_capacity(npixel); ncomp];
        for _mcu_y in 0..height {
            for _mcu_x in 0..width {
                if self.restart_interval > 0 {
                    if mcus_left_until_restart == 0 {
                        match huffman.take_marker(reader)? {
                            Some(Marker::RST(n)) => {
                                if n != expected_rst_num {
                                    return Err(Error::Format(format!(
                                        "found RST{} where RST{} was expected",
                                        n, expected_rst_num
                                    )));
                                }

                                huffman.reset();

                                expected_rst_num = (expected_rst_num + 1) % 8;
                                mcus_left_until_restart = self.restart_interval;
                            }
                            Some(marker) => {
                                return Err(Error::Format(format!(
                                    "found marker {:?} inside scan where RST{} was expected",
                                    marker, expected_rst_num
                                )))
                            }
                            None => {
                                return Err(Error::Format(format!(
                                    "no marker found where RST{} was expected",
                                    expected_rst_num
                                )))
                            }
                        }
                    }

                    mcus_left_until_restart -= 1;
                }

                for (i, _component) in components.iter().enumerate() {
                    let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]]
                        .as_ref()
                        .unwrap();
                    let value = huffman.decode(reader, dc_table)?;
                    let diff = match value {
                        0 => 0,
                        1..=15 => huffman.receive_extend(reader, value)? as i32,
                        16 => 32768,
                        _ => {
                            // Section F.1.2.1.1
                            // Table F.1
                            return Err(Error::Format(
                                "invalid DC difference magnitude category".to_owned(),
                            ));
                        }
                    };
                    differences[i].push(diff);
                }
            }
        }

        if scan.predictor_selection == Predictor::Ra {
            for (i, _component) in components.iter().enumerate() {
                // calculate the top left pixel
                let diff = differences[i][0];
                let prediction = 1 << (frame.precision - scan.point_transform - 1) as i32;
                let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                let result = result << scan.point_transform;
                results[i][0] = result;

                // calculate leftmost column, using top pixel as predictor
                let mut previous = result;
                for mcu_y in 1..height {
                    let diff = differences[i][mcu_y * width];
                    let prediction = previous as i32;
                    let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                    let result = result << scan.point_transform;
                    results[i][mcu_y * width] = result;
                    previous = result;
                }

                // calculate rows, using left pixel as predictor
                for mcu_y in 0..height {
                    for mcu_x in 1..width {
                        let diff = differences[i][mcu_y * width + mcu_x];
                        let prediction = results[i][mcu_y * width + mcu_x - 1] as i32;
                        let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                        let result = result << scan.point_transform;
                        results[i][mcu_y * width + mcu_x] = result;
                    }
                }
            }
        } else {
            for mcu_y in 0..height {
                for mcu_x in 0..width {
                    for (i, _component) in components.iter().enumerate() {
                        let diff = differences[i][mcu_y * width + mcu_x];

                        // The following lines could be further optimized, e.g. moving the checks
                        // and updates of the previous values into the prediction function or
                        // iterating such that diagonals with mcu_x + mcu_y = const are computed at
                        // the same time to exploit independent predictions in this case
                        if mcu_x > 0 {
                            ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1];
                        }
                        if mcu_y > 0 {
                            rb[i] =
                                results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x];
                            if mcu_x > 0 {
                                rc[i] = results[i]
                                    [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)];
                            }
                        }
                        let prediction = predict(
                            ra[i] as i32,
                            rb[i] as i32,
                            rc[i] as i32,
                            scan.predictor_selection,
                            scan.point_transform,
                            frame.precision,
                            mcu_x,
                            mcu_y,
                            self.restart_interval > 0
                                && mcus_left_until_restart == self.restart_interval - 1,
                        );
                        let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16
                        results[i][mcu_y * width + mcu_x] = result << scan.point_transform;
                    }
                }
            }
        }

        let mut marker = huffman.take_marker(&mut self.reader)?;
        while let Some(Marker::RST(_)) = marker {
            marker = self.read_marker().ok();
        }
        Ok((marker, results))
    }
}

/// H.1.2.1
fn predict(
    ra: i32,
    rb: i32,
    rc: i32,
    predictor: Predictor,
    point_transform: u8,
    input_precision: u8,
    ix: usize,
    iy: usize,
    restart: bool,
) -> i32 {
    if (ix == 0 && iy == 0) || restart {
        // start of first line or restart
        if input_precision > 1 + point_transform {
            1 << (input_precision - point_transform - 1)
        } else {
            0
        }
    } else if iy == 0 {
        // rest of first line
        ra
    } else if ix == 0 {
        // start of other line
        rb
    } else {
        // use predictor Table H.1
        match predictor {
            Predictor::NoPrediction => 0,
            Predictor::Ra => ra,
            Predictor::Rb => rb,
            Predictor::Rc => rc,
            Predictor::RaRbRc1 => ra + rb - rc,
            Predictor::RaRbRc2 => ra + ((rb - rc) >> 1),
            Predictor::RaRbRc3 => rb + ((ra - rc) >> 1),
            Predictor::RaRb => (ra + rb) / 2,
        }
    }
}

pub fn compute_image_lossless(frame: &FrameInfo, mut data: Vec<Vec<u16>>) -> Result<Vec<u8>> {
    if data.is_empty() || data.iter().any(Vec::is_empty) {
        return Err(Error::Format("not all components have data".to_owned()));
    }
    let output_size = frame.output_size;
    let components = &frame.components;
    let ncomp = components.len();

    if ncomp == 1 {
        let decoded = convert_to_u8(frame, data.remove(0));
        Ok(decoded)
    } else {
        let mut decoded: Vec<u16> =
            vec![0u16; ncomp * output_size.width as usize * output_size.height as usize];
        for (x, chunk) in decoded.chunks_mut(ncomp).enumerate() {
            for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() {
                chunk[i] = component_data[x];
            }
        }
        let decoded = convert_to_u8(frame, decoded);
        Ok(decoded)
    }
}

fn convert_to_u8(frame: &FrameInfo, data: Vec<u16>) -> Vec<u8> {
    if frame.precision == 8 {
        data.iter().map(|x| *x as u8).collect()
    } else {
        // we output native endian, which is the standard for image-rs
        let ne_bytes: Vec<_> = data.iter().map(|x| x.to_ne_bytes()).collect();
        ne_bytes.concat()
    }
}
<|endoftext|>


<commit_before>use std::mem::size_of;
use std::ptr;
use std::sync::Mutex;

use gc::arena;
use gc::Address;
use gc::swiper::Region;
use gc::swiper::LARGE_OBJECT_SIZE;
use mem;

pub struct LargeSpace {
    total: Region,
    ranges: Mutex<Ranges>,
}

impl LargeSpace {
    pub fn new(start: Address, end: Address) -> LargeSpace {
        LargeSpace {
            total: Region::new(start, end),
            ranges: Mutex::new(Ranges::new(start, end)),
        }
    }

    pub fn alloc(&self, size: usize) -> *const u8 {
        debug_assert!(size >= LARGE_OBJECT_SIZE);
        let size = mem::page_align(size_of::<LargeAlloc>() + size);

        let mut ranges = self.ranges.lock().unwrap();

        if let Some(range) = ranges.alloc(size) {
            arena::commit(range.start, range.size(), false).expect("couldn't commit large object.");
            ranges.append_large_alloc(range.start, range.size());
            range.start.to_ptr()

        } else {
            ptr::null()
        }
    }

    pub fn free(&self, ptr: Address, size: usize) {
        debug_assert!(size >= LARGE_OBJECT_SIZE);
        debug_assert!(mem::is_page_aligned(ptr.to_usize()));
        let size = mem::page_align(size_of::<LargeAlloc>() + size);

        let mut ranges = self.ranges.lock().unwrap();
        debug_assert!(!ranges.contains(ptr));
        ranges.free(ptr, size);
        ranges.merge();
    }

    pub fn contains(&self, addr: Address) -> bool {
        self.total.contains(addr)
    }
}

struct LargeAlloc {
    prev: Address,
    next: Address,
    size: usize,
}

struct Ranges {
    elements: Vec<Range>,
    head: Address,
    tail: Address,
}

impl Ranges {
    fn new(start: Address, end: Address) -> Ranges {
        Ranges {
            elements: vec![Range::new(start, end)],
            head: Address::null(),
            tail: Address::null(),
        }
    }

    fn alloc(&mut self, size: usize) -> Option<Range> {
        debug_assert!(mem::is_page_aligned(size));
        let len = self.elements.len();

        for i in 0..len {
            if self.elements[i].size() >= size {
                let range = self.elements[i];
                let alloc = Range::new(range.start, range.start.offset(size));

                if range.size() == size {
                    self.elements.remove(i);
                } else {
                    self.elements[i] = Range::new(range.start.offset(size), range.end);
                }

                return Some(alloc);
            }
        }

        None
    }

    fn free(&mut self, ptr: Address, size: usize) {
        debug_assert!(mem::is_page_aligned(size));
        self.elements.push(Range::new(ptr, ptr.offset(size)));
    }

    fn merge(&mut self) {
        self.elements.sort_unstable_by(|lhs, rhs| lhs.start.to_usize().cmp(&rhs.start.to_usize()));

        let len = self.elements.len();
        let mut last_element = 0;

        for i in 1..len {
            if self.elements[last_element].end == self.elements[i].start {
                self.elements[last_element].end = self.elements[i].end;
            } else {
                last_element += 1;
                self.elements[last_element] = self.elements[i];
            }
        }

        self.elements.truncate(last_element+1);
    }

    fn contains(&self, ptr: Address) -> bool {
        for element in &self.elements {
            if element.contains(ptr) {
                return true;
            }
        }

        false
    }

    fn append_large_alloc(&mut self, addr: Address, size: usize) {
        if !self.tail.is_null() {
            let old_tail = unsafe { &mut *self.tail.to_mut_ptr::<LargeAlloc>() };
            old_tail.next = addr;
        }

        let new_tail = unsafe { &mut *addr.to_mut_ptr::<LargeAlloc>() };
        new_tail.prev = self.tail;
        new_tail.next = Address::null();
        new_tail.size = size;

        self.tail = addr;
    }
}

#[derive(Copy, Clone)]
struct Range {
    start: Address,
    end: Address,
}

impl Range {
    fn new(start: Address, end: Address) -> Range {
        assert!(end > start);

        Range {
            start: start,
            end: end,
        }
    }

    fn contains(&self, ptr: Address) -> bool {
        self.start <= ptr && ptr < self.end
    }

    fn size(&self) -> usize {
        self.end.offset_from(self.start)
    }
}<commit_msg>swiper: rename Ranges to LargeSpaceProtected<commit_after>use std::mem::size_of;
use std::ptr;
use std::sync::Mutex;

use gc::arena;
use gc::Address;
use gc::swiper::Region;
use gc::swiper::LARGE_OBJECT_SIZE;
use mem;

pub struct LargeSpace {
    total: Region,
    space: Mutex<LargeSpaceProtected>,
}

impl LargeSpace {
    pub fn new(start: Address, end: Address) -> LargeSpace {
        LargeSpace {
            total: Region::new(start, end),
            space: Mutex::new(LargeSpaceProtected::new(start, end)),
        }
    }

    pub fn alloc(&self, size: usize) -> *const u8 {
        debug_assert!(size >= LARGE_OBJECT_SIZE);
        let size = mem::page_align(size_of::<LargeAlloc>() + size);

        let mut space = self.space.lock().unwrap();

        if let Some(range) = space.alloc(size) {
            arena::commit(range.start, range.size(), false).expect("couldn't commit large object.");
            space.append_large_alloc(range.start, range.size());
            range.start.to_ptr()

        } else {
            ptr::null()
        }
    }

    pub fn free(&self, ptr: Address, size: usize) {
        debug_assert!(size >= LARGE_OBJECT_SIZE);
        debug_assert!(mem::is_page_aligned(ptr.to_usize()));
        let size = mem::page_align(size_of::<LargeAlloc>() + size);

        let mut space = self.space.lock().unwrap();
        debug_assert!(!space.contains(ptr));
        space.free(ptr, size);
        space.merge();
    }

    pub fn contains(&self, addr: Address) -> bool {
        self.total.contains(addr)
    }
}

struct LargeAlloc {
    prev: Address,
    next: Address,
    size: usize,
}

struct LargeSpaceProtected {
    elements: Vec<Range>,
    head: Address,
    tail: Address,
}

impl LargeSpaceProtected {
    fn new(start: Address, end: Address) -> LargeSpaceProtected {
        LargeSpaceProtected {
            elements: vec![Range::new(start, end)],
            head: Address::null(),
            tail: Address::null(),
        }
    }

    fn alloc(&mut self, size: usize) -> Option<Range> {
        debug_assert!(mem::is_page_aligned(size));
        let len = self.elements.len();

        for i in 0..len {
            if self.elements[i].size() >= size {
                let range = self.elements[i];
                let alloc = Range::new(range.start, range.start.offset(size));

                if range.size() == size {
                    self.elements.remove(i);
                } else {
                    self.elements[i] = Range::new(range.start.offset(size), range.end);
                }

                return Some(alloc);
            }
        }

        None
    }

    fn free(&mut self, ptr: Address, size: usize) {
        debug_assert!(mem::is_page_aligned(size));
        self.elements.push(Range::new(ptr, ptr.offset(size)));
    }

    fn merge(&mut self) {
        self.elements.sort_unstable_by(|lhs, rhs| lhs.start.to_usize().cmp(&rhs.start.to_usize()));

        let len = self.elements.len();
        let mut last_element = 0;

        for i in 1..len {
            if self.elements[last_element].end == self.elements[i].start {
                self.elements[last_element].end = self.elements[i].end;
            } else {
                last_element += 1;
                self.elements[last_element] = self.elements[i];
            }
        }

        self.elements.truncate(last_element+1);
    }

    fn contains(&self, ptr: Address) -> bool {
        for element in &self.elements {
            if element.contains(ptr) {
                return true;
            }
        }

        false
    }

    fn append_large_alloc(&mut self, addr: Address, size: usize) {
        if !self.tail.is_null() {
            let old_tail = unsafe { &mut *self.tail.to_mut_ptr::<LargeAlloc>() };
            old_tail.next = addr;
        }

        let new_tail = unsafe { &mut *addr.to_mut_ptr::<LargeAlloc>() };
        new_tail.prev = self.tail;
        new_tail.next = Address::null();
        new_tail.size = size;

        self.tail = addr;
    }
}

#[derive(Copy, Clone)]
struct Range {
    start: Address,
    end: Address,
}

impl Range {
    fn new(start: Address, end: Address) -> Range {
        assert!(end > start);

        Range {
            start: start,
            end: end,
        }
    }

    fn contains(&self, ptr: Address) -> bool {
        self.start <= ptr && ptr < self.end
    }

    fn size(&self) -> usize {
        self.end.offset_from(self.start)
    }
}<|endoftext|>


<commit_before>//! Items related to the nodes of a geometry graph.

use daggy::{self, Walker};
use daggy::petgraph::visit::{self, Visitable};
use geom;
use geom::{DefaultScalar, Graph};
use geom::graph::Edge;
use math::{self, BaseFloat, Basis3, Euler, Point3, Rad, Rotation, Vector3};
use std::collections::HashMap;
use std::marker::PhantomData;
use std::ops;

/// Unique index for a **Node** within a **Graph**.
pub type Index = daggy::NodeIndex<usize>;

/// The **Node** type used within the **Graph**.
#[derive(Clone, Debug)]
pub enum Node<S = DefaultScalar>
where
    S: BaseFloat,
{
    /// A point has no vertices other than that yielded at the node's position.
    ///
    /// Useful for acting as an invisible "reference" node for controlling other children nodes.
    ///
    /// Also used to represent the graph's "origin" node.
    Point,
    /// A nested Graph.
    Graph { graph: super::Graph<S>, dfs: Dfs<S> },
}

/// An iterator yielding all vertices for a node transformed by some given transform.
#[derive(Clone, Debug)]
pub struct TransformedVertices<I, S = DefaultScalar>
where
    S: BaseFloat,
{
    transform: PreparedTransform<S>,
    vertices: I,
}

/// An iterator yielding all vertices for a node transformed by some given transform.
#[derive(Clone, Debug)]
pub struct TransformedTriangles<I, V, S = DefaultScalar>
where
    S: BaseFloat,
{
    transform: PreparedTransform<S>,
    triangles: I,
    _vertex: PhantomData<V>,
}

/// A node's resulting rotation, displacement and scale relative to the graph's origin.
///
/// A transform is calculated and applied to a node's vertices in the following order:
///
/// 1. **scale**: `1.0 * parent_scale * edge_scale`
/// 2. **rotation**: `0.0 + parent_position + edge_displacement`
/// 3. **displacement**: 0.0 + parent_orientation + edge_orientation`
#[derive(Clone, Debug, PartialEq)]
pub struct Transform<S = DefaultScalar>
where
    S: BaseFloat,
{
    /// A scaling amount along each axis.
    ///
    /// The scaling amount is multiplied onto each vertex of the node.
    pub scale: Vector3<S>,
    /// A rotation amount along each axis, describing a relative orientation.
    ///
    /// Rotates all vertices around the node origin when applied.
    pub rot: Euler<Rad<S>>,
    /// A displacement amount along each axis.
    ///
    /// This vector is added onto the position of each vertex of the node.
    pub disp: Vector3<S>,
}

/// A node's resulting rotation, displacement and scale relative to the graph's origin.
///
/// The same as **Transfrom** but the euler has been converted to a matrix for more efficient
/// application.
#[derive(Clone, Debug, PartialEq)]
pub struct PreparedTransform<S = DefaultScalar> {
    /// A scaling amount along each axis.
    ///
    /// The scaling amount is multiplied onto each vertex of the node.
    pub scale: Vector3<S>,
    /// A rotation amount along each axis, describing a relative orientation.
    ///
    /// Rotates all vertices around the node origin when applied.
    pub rot: Basis3<S>,
    /// A displacement amount along each axis.
    ///
    /// This vector is added onto the position of each vertex of the node.
    pub disp: Vector3<S>,
}

/// Mappings from node indices to their respective transform within the graph.
///
/// This is calculated via the `Graph::update_transform_map` method.
#[derive(Clone, Debug, PartialEq)]
pub struct TransformMap<S = DefaultScalar>
where
    S: BaseFloat,
{
    map: HashMap<Index, Transform<S>>,
}

/// A depth-first-search over nodes in the graph, yielding each node's unique index alongside its
/// absolute transform.
///
/// The traversal may start at any given node.
///
/// **Note:** The algorithm may not behave correctly if nodes are removed during iteration. It may
/// not necessarily visit added nodes or edges.
#[derive(Clone, Debug)]
pub struct Dfs<S = DefaultScalar>
where
    S: BaseFloat,
{
    dfs: visit::Dfs<Index, <Graph<S> as Visitable>::Map>,
    visited: TransformMap<S>,
}

impl<S> Dfs<S>
where
    S: BaseFloat,
{
    /// Create a new **Dfs** starting from the graph's origin.
    pub fn new(graph: &Graph<S>) -> Self {
        Self::start_from(graph, graph.origin())
    }

    /// Create a new **Dfs** starting from the node at the given node.
    pub fn start_from(graph: &Graph<S>, start: Index) -> Self {
        let dfs = visit::Dfs::new(graph, start);
        let visited = TransformMap::default();
        Dfs { dfs, visited }
    }

    /// Clears the visit state.
    pub fn reset(&mut self, graph: &Graph<S>) {
        self.dfs.reset(graph);
        self.dfs.move_to(graph.origin());
    }

    /// Keep the discovered map but clear the visit stack and restart the dfs from the given node.
    pub fn move_to(&mut self, start: Index) {
        self.dfs.move_to(start);
    }

    /// Return the tranform for the next node in the DFS.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_transform(&mut self, graph: &Graph<S>) -> Option<(Index, Transform<S>)> {
        let n = match self.dfs.next(graph) {
            None => return None,
            Some(n) => n,
        };
        let mut transform = Transform::default();
        for (e, parent) in graph.parents(n).iter(graph) {
            let parent_transform = &self.visited[&parent];
            let edge = &graph[e];
            transform.apply_edge(parent_transform, edge);
        }
        self.visited.map.insert(n, transform.clone());
        Some((n, transform))
    }

    /// Return the vertices for the next node in the DFS.
    ///
    /// Uses `Dfs::next_transform` internally.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_vertices<F, I>(
        &mut self,
        graph: &Graph<S>,
        vertices_fn: F,
    ) -> Option<(Index, TransformedVertices<I::IntoIter, S>)>
    where
        F: FnOnce(&Index) -> I,
        I: IntoIterator,
        I::Item: ApplyTransform<S>,
    {
        self.next_transform(graph).map(|(n, transform)| {
            let vertices = vertices_fn(&n);
            let vertices = vertices.into_iter();
            (n, transform.vertices(vertices))
        })
    }

    /// Return the triangles for the next node in the DFS.
    ///
    /// Uses `Dfs::next_transform` and `Node::triangles` internally.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_triangles<F, I, V>(
        &mut self,
        graph: &Graph<S>,
        triangles_fn: F,
    ) -> Option<(Index, TransformedTriangles<I::IntoIter, V, S>)>
    where
        F: FnOnce(&Index) -> I,
        I: IntoIterator<Item = geom::Tri<V>>,
        V: geom::Vertex + ApplyTransform<S>,
    {
        self.next_transform(graph).map(|(n, transform)| {
            let triangles = triangles_fn(&n);
            let triangles = triangles.into_iter();
            (n, transform.triangles(triangles))
        })
    }
}

impl<'a, S> Walker<&'a Graph<S>> for Dfs<S>
where
    S: BaseFloat,
{
    type Item = (Index, Transform<S>);
    fn walk_next(&mut self, graph: &'a Graph<S>) -> Option<Self::Item> {
        self.next_transform(graph)
    }
}

impl<S> Default for TransformMap<S>
where
    S: BaseFloat,
{
    fn default() -> Self {
        TransformMap {
            map: Default::default(),
        }
    }
}

impl<S> ops::Deref for TransformMap<S>
where
    S: BaseFloat,
{
    type Target = HashMap<Index, Transform<S>>;
    fn deref(&self) -> &Self::Target {
        &self.map
    }
}

impl<S> Into<HashMap<Index, Transform<S>>> for TransformMap<S>
where
    S: BaseFloat,
{
    fn into(self) -> HashMap<Index, Transform<S>> {
        self.map
    }
}

impl<S> Transform<S>
where
    S: BaseFloat,
{
    /// Apply the given parent `Edge` to this transform.
    pub fn apply_edge(&mut self, parent: &Self, edge: &Edge<S>) {
        use geom::graph::edge::{Axis, Relative};
        match (edge.kind.relative, edge.kind.axis) {
            (Relative::Position, Axis::X) => self.disp.x += parent.disp.x + edge.weight,
            (Relative::Position, Axis::Y) => self.disp.y += parent.disp.y + edge.weight,
            (Relative::Position, Axis::Z) => self.disp.z += parent.disp.z + edge.weight,
            (Relative::Orientation, Axis::X) => self.rot.x += parent.rot.x + Rad(edge.weight),
            (Relative::Orientation, Axis::Y) => self.rot.y += parent.rot.y + Rad(edge.weight),
            (Relative::Orientation, Axis::Z) => self.rot.z += parent.rot.z + Rad(edge.weight),
            (Relative::Scale, Axis::X) => self.scale.x *= parent.scale.x * edge.weight,
            (Relative::Scale, Axis::Y) => self.scale.y *= parent.scale.y * edge.weight,
            (Relative::Scale, Axis::Z) => self.scale.z *= parent.scale.z * edge.weight,
        }
    }

    /// Prepare this transform for application.
    pub fn prepare(self) -> PreparedTransform<S> {
        let Transform { disp, rot, scale } = self;
        let rot = Basis3::from(rot);
        PreparedTransform { disp, rot, scale }
    }

    /// Transform the given vertices.
    pub fn vertices<I>(self, vertices: I) -> TransformedVertices<I::IntoIter, S>
    where
        I: IntoIterator,
        I::Item: ApplyTransform<S>,
    {
        let transform = self.prepare();
        let vertices = vertices.into_iter();
        TransformedVertices {
            transform,
            vertices,
        }
    }

    /// Transform the given vertices.
    pub fn triangles<I, V>(self, triangles: I) -> TransformedTriangles<I::IntoIter, V, S>
    where
        I: IntoIterator<Item = geom::Tri<V>>,
        V: geom::Vertex + ApplyTransform<S>,
    {
        let transform = self.prepare();
        let triangles = triangles.into_iter();
        let _vertex = PhantomData;
        TransformedTriangles {
            transform,
            triangles,
            _vertex,
        }
    }
}

impl<S> Default for Transform<S>
where
    S: BaseFloat,
{
    fn default() -> Self {
        let zero = S::zero();
        let one = S::one();
        let scale = Vector3 {
            x: one,
            y: one,
            z: one,
        };
        let rot = Euler {
            x: Rad(zero),
            y: Rad(zero),
            z: Rad(zero),
        };
        let disp = Vector3 {
            x: zero,
            y: zero,
            z: zero,
        };
        Transform { scale, rot, disp }
    }
}

impl<S> math::Transform<Point3<S>> for Transform<S>
where
    S: BaseFloat,
{
    fn one() -> Self {
        let one = S::one();
        let (x, y, z) = (one, one, one);
        Transform {
            scale: Vector3 { x, y, z },
            rot: Euler {
                x: Rad(x),
                y: Rad(y),
                z: Rad(z),
            },
            disp: Vector3 { x, y, z },
        }
    }

    fn look_at(_eye: Point3<S>, _center: Point3<S>, _up: Vector3<S>) -> Self {
        unimplemented!();
    }

    fn transform_vector(&self, _vec: Vector3<S>) -> Vector3<S> {
        unimplemented!();
    }

    fn inverse_transform_vector(&self, _vec: Vector3<S>) -> Option<Vector3<S>> {
        unimplemented!();
    }

    fn transform_point(&self, _point: Point3<S>) -> Point3<S> {
        unimplemented!();
    }

    fn concat(&self, _other: &Self) -> Self {
        unimplemented!();
    }

    fn inverse_transform(&self) -> Option<Self> {
        unimplemented!();
    }
}

/// Apply the given transform to the given 3D point.
pub fn transform_point<S>(transform: &PreparedTransform<S>, mut point: Point3<S>) -> Point3<S>
where
    S: BaseFloat,
{
    // Scale the point relative to the node origin.
    point.x *= transform.scale.x;
    point.y *= transform.scale.y;
    point.z *= transform.scale.z;
    // Rotate the point around the node origin.
    point = transform.rot.rotate_point(point);
    // Displace the point from the node origin.
    point += transform.disp;
    point
}

/// Vertex types which may apply a transform and produce a resulting transform.
pub trait ApplyTransform<S>
where
    S: BaseFloat,
{
    /// Apply the given transform and return the result.
    fn apply_transform(self, transform: &PreparedTransform<S>) -> Self;
}

impl<S> ApplyTransform<S> for Point3<S>
where
    S: BaseFloat,
{
    fn apply_transform(self, transform: &PreparedTransform<S>) -> Self {
        transform_point(transform, self)
    }
}

impl<I, S> Iterator for TransformedVertices<I, S>
where
    I: Iterator,
    I::Item: ApplyTransform<S>,
    S: BaseFloat,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        self.vertices
            .next()
            .map(|vertex| vertex.apply_transform(&self.transform))
    }
}

impl<I, V, S> Iterator for TransformedTriangles<I, V, S>
where
    I: Iterator<Item = geom::Tri<V>>,
    V: geom::Vertex + ApplyTransform<S>,
    S: BaseFloat,
{
    type Item = geom::Tri<V>;
    fn next(&mut self) -> Option<Self::Item> {
        self.triangles
            .next()
            .map(|tri| tri.map_vertices(|vertex| vertex.apply_transform(&self.transform)))
    }
}
<commit_msg>Fix graph edge orientation application so that positive values result in clockwise rotations around axes<commit_after>//! Items related to the nodes of a geometry graph.

use daggy::{self, Walker};
use daggy::petgraph::visit::{self, Visitable};
use geom;
use geom::{DefaultScalar, Graph};
use geom::graph::Edge;
use math::{self, BaseFloat, Basis3, Euler, Point3, Rad, Rotation, Vector3};
use std::collections::HashMap;
use std::marker::PhantomData;
use std::ops;

/// Unique index for a **Node** within a **Graph**.
pub type Index = daggy::NodeIndex<usize>;

/// The **Node** type used within the **Graph**.
#[derive(Clone, Debug)]
pub enum Node<S = DefaultScalar>
where
    S: BaseFloat,
{
    /// A point has no vertices other than that yielded at the node's position.
    ///
    /// Useful for acting as an invisible "reference" node for controlling other children nodes.
    ///
    /// Also used to represent the graph's "origin" node.
    Point,
    /// A nested Graph.
    Graph { graph: super::Graph<S>, dfs: Dfs<S> },
}

/// An iterator yielding all vertices for a node transformed by some given transform.
#[derive(Clone, Debug)]
pub struct TransformedVertices<I, S = DefaultScalar>
where
    S: BaseFloat,
{
    transform: PreparedTransform<S>,
    vertices: I,
}

/// An iterator yielding all vertices for a node transformed by some given transform.
#[derive(Clone, Debug)]
pub struct TransformedTriangles<I, V, S = DefaultScalar>
where
    S: BaseFloat,
{
    transform: PreparedTransform<S>,
    triangles: I,
    _vertex: PhantomData<V>,
}

/// A node's resulting rotation, displacement and scale relative to the graph's origin.
///
/// A transform is calculated and applied to a node's vertices in the following order:
///
/// 1. **scale**: `1.0 * parent_scale * edge_scale`
/// 2. **rotation**: `0.0 + parent_position + edge_displacement`
/// 3. **displacement**: 0.0 + parent_orientation + edge_orientation`
#[derive(Clone, Debug, PartialEq)]
pub struct Transform<S = DefaultScalar>
where
    S: BaseFloat,
{
    /// A scaling amount along each axis.
    ///
    /// The scaling amount is multiplied onto each vertex of the node.
    pub scale: Vector3<S>,
    /// A rotation amount along each axis, describing a relative orientation.
    ///
    /// Rotates all vertices around the node origin when applied.
    pub rot: Euler<Rad<S>>,
    /// A displacement amount along each axis.
    ///
    /// This vector is added onto the position of each vertex of the node.
    pub disp: Vector3<S>,
}

/// A node's resulting rotation, displacement and scale relative to the graph's origin.
///
/// The same as **Transfrom** but the euler has been converted to a matrix for more efficient
/// application.
#[derive(Clone, Debug, PartialEq)]
pub struct PreparedTransform<S = DefaultScalar> {
    /// A scaling amount along each axis.
    ///
    /// The scaling amount is multiplied onto each vertex of the node.
    pub scale: Vector3<S>,
    /// A rotation amount along each axis, describing a relative orientation.
    ///
    /// Rotates all vertices around the node origin when applied.
    pub rot: Basis3<S>,
    /// A displacement amount along each axis.
    ///
    /// This vector is added onto the position of each vertex of the node.
    pub disp: Vector3<S>,
}

/// Mappings from node indices to their respective transform within the graph.
///
/// This is calculated via the `Graph::update_transform_map` method.
#[derive(Clone, Debug, PartialEq)]
pub struct TransformMap<S = DefaultScalar>
where
    S: BaseFloat,
{
    map: HashMap<Index, Transform<S>>,
}

/// A depth-first-search over nodes in the graph, yielding each node's unique index alongside its
/// absolute transform.
///
/// The traversal may start at any given node.
///
/// **Note:** The algorithm may not behave correctly if nodes are removed during iteration. It may
/// not necessarily visit added nodes or edges.
#[derive(Clone, Debug)]
pub struct Dfs<S = DefaultScalar>
where
    S: BaseFloat,
{
    dfs: visit::Dfs<Index, <Graph<S> as Visitable>::Map>,
    visited: TransformMap<S>,
}

impl<S> Dfs<S>
where
    S: BaseFloat,
{
    /// Create a new **Dfs** starting from the graph's origin.
    pub fn new(graph: &Graph<S>) -> Self {
        Self::start_from(graph, graph.origin())
    }

    /// Create a new **Dfs** starting from the node at the given node.
    pub fn start_from(graph: &Graph<S>, start: Index) -> Self {
        let dfs = visit::Dfs::new(graph, start);
        let visited = TransformMap::default();
        Dfs { dfs, visited }
    }

    /// Clears the visit state.
    pub fn reset(&mut self, graph: &Graph<S>) {
        self.dfs.reset(graph);
        self.dfs.move_to(graph.origin());
    }

    /// Keep the discovered map but clear the visit stack and restart the dfs from the given node.
    pub fn move_to(&mut self, start: Index) {
        self.dfs.move_to(start);
    }

    /// Return the tranform for the next node in the DFS.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_transform(&mut self, graph: &Graph<S>) -> Option<(Index, Transform<S>)> {
        let n = match self.dfs.next(graph) {
            None => return None,
            Some(n) => n,
        };
        let mut transform = Transform::default();
        for (e, parent) in graph.parents(n).iter(graph) {
            let parent_transform = &self.visited[&parent];
            let edge = &graph[e];
            transform.apply_edge(parent_transform, edge);
        }
        self.visited.map.insert(n, transform.clone());
        Some((n, transform))
    }

    /// Return the vertices for the next node in the DFS.
    ///
    /// Uses `Dfs::next_transform` internally.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_vertices<F, I>(
        &mut self,
        graph: &Graph<S>,
        vertices_fn: F,
    ) -> Option<(Index, TransformedVertices<I::IntoIter, S>)>
    where
        F: FnOnce(&Index) -> I,
        I: IntoIterator,
        I::Item: ApplyTransform<S>,
    {
        self.next_transform(graph).map(|(n, transform)| {
            let vertices = vertices_fn(&n);
            let vertices = vertices.into_iter();
            (n, transform.vertices(vertices))
        })
    }

    /// Return the triangles for the next node in the DFS.
    ///
    /// Uses `Dfs::next_transform` and `Node::triangles` internally.
    ///
    /// Returns `None` if the traversal is finished.
    pub fn next_triangles<F, I, V>(
        &mut self,
        graph: &Graph<S>,
        triangles_fn: F,
    ) -> Option<(Index, TransformedTriangles<I::IntoIter, V, S>)>
    where
        F: FnOnce(&Index) -> I,
        I: IntoIterator<Item = geom::Tri<V>>,
        V: geom::Vertex + ApplyTransform<S>,
    {
        self.next_transform(graph).map(|(n, transform)| {
            let triangles = triangles_fn(&n);
            let triangles = triangles.into_iter();
            (n, transform.triangles(triangles))
        })
    }
}

impl<'a, S> Walker<&'a Graph<S>> for Dfs<S>
where
    S: BaseFloat,
{
    type Item = (Index, Transform<S>);
    fn walk_next(&mut self, graph: &'a Graph<S>) -> Option<Self::Item> {
        self.next_transform(graph)
    }
}

impl<S> Default for TransformMap<S>
where
    S: BaseFloat,
{
    fn default() -> Self {
        TransformMap {
            map: Default::default(),
        }
    }
}

impl<S> ops::Deref for TransformMap<S>
where
    S: BaseFloat,
{
    type Target = HashMap<Index, Transform<S>>;
    fn deref(&self) -> &Self::Target {
        &self.map
    }
}

impl<S> Into<HashMap<Index, Transform<S>>> for TransformMap<S>
where
    S: BaseFloat,
{
    fn into(self) -> HashMap<Index, Transform<S>> {
        self.map
    }
}

impl<S> Transform<S>
where
    S: BaseFloat,
{
    /// Apply the given parent `Edge` to this transform.
    pub fn apply_edge(&mut self, parent: &Self, edge: &Edge<S>) {
        use geom::graph::edge::{Axis, Relative};
        match (edge.kind.relative, edge.kind.axis) {
            (Relative::Position, Axis::X) => self.disp.x += parent.disp.x + edge.weight,
            (Relative::Position, Axis::Y) => self.disp.y += parent.disp.y + edge.weight,
            (Relative::Position, Axis::Z) => self.disp.z += parent.disp.z + edge.weight,
            (Relative::Orientation, Axis::X) => self.rot.x += parent.rot.x - Rad(edge.weight),
            (Relative::Orientation, Axis::Y) => self.rot.y += parent.rot.y - Rad(edge.weight),
            (Relative::Orientation, Axis::Z) => self.rot.z += parent.rot.z - Rad(edge.weight),
            (Relative::Scale, Axis::X) => self.scale.x *= parent.scale.x * edge.weight,
            (Relative::Scale, Axis::Y) => self.scale.y *= parent.scale.y * edge.weight,
            (Relative::Scale, Axis::Z) => self.scale.z *= parent.scale.z * edge.weight,
        }
    }

    /// Prepare this transform for application.
    pub fn prepare(self) -> PreparedTransform<S> {
        let Transform { disp, rot, scale } = self;
        let rot = Basis3::from(rot);
        PreparedTransform { disp, rot, scale }
    }

    /// Transform the given vertices.
    pub fn vertices<I>(self, vertices: I) -> TransformedVertices<I::IntoIter, S>
    where
        I: IntoIterator,
        I::Item: ApplyTransform<S>,
    {
        let transform = self.prepare();
        let vertices = vertices.into_iter();
        TransformedVertices {
            transform,
            vertices,
        }
    }

    /// Transform the given vertices.
    pub fn triangles<I, V>(self, triangles: I) -> TransformedTriangles<I::IntoIter, V, S>
    where
        I: IntoIterator<Item = geom::Tri<V>>,
        V: geom::Vertex + ApplyTransform<S>,
    {
        let transform = self.prepare();
        let triangles = triangles.into_iter();
        let _vertex = PhantomData;
        TransformedTriangles {
            transform,
            triangles,
            _vertex,
        }
    }
}

impl<S> Default for Transform<S>
where
    S: BaseFloat,
{
    fn default() -> Self {
        let zero = S::zero();
        let one = S::one();
        let scale = Vector3 {
            x: one,
            y: one,
            z: one,
        };
        let rot = Euler {
            x: Rad(zero),
            y: Rad(zero),
            z: Rad(zero),
        };
        let disp = Vector3 {
            x: zero,
            y: zero,
            z: zero,
        };
        Transform { scale, rot, disp }
    }
}

impl<S> math::Transform<Point3<S>> for Transform<S>
where
    S: BaseFloat,
{
    fn one() -> Self {
        let one = S::one();
        let (x, y, z) = (one, one, one);
        Transform {
            scale: Vector3 { x, y, z },
            rot: Euler {
                x: Rad(x),
                y: Rad(y),
                z: Rad(z),
            },
            disp: Vector3 { x, y, z },
        }
    }

    fn look_at(_eye: Point3<S>, _center: Point3<S>, _up: Vector3<S>) -> Self {
        unimplemented!();
    }

    fn transform_vector(&self, _vec: Vector3<S>) -> Vector3<S> {
        unimplemented!();
    }

    fn inverse_transform_vector(&self, _vec: Vector3<S>) -> Option<Vector3<S>> {
        unimplemented!();
    }

    fn transform_point(&self, _point: Point3<S>) -> Point3<S> {
        unimplemented!();
    }

    fn concat(&self, _other: &Self) -> Self {
        unimplemented!();
    }

    fn inverse_transform(&self) -> Option<Self> {
        unimplemented!();
    }
}

/// Apply the given transform to the given 3D point.
pub fn transform_point<S>(transform: &PreparedTransform<S>, mut point: Point3<S>) -> Point3<S>
where
    S: BaseFloat,
{
    // Scale the point relative to the node origin.
    point.x *= transform.scale.x;
    point.y *= transform.scale.y;
    point.z *= transform.scale.z;
    // Rotate the point around the node origin.
    point = transform.rot.rotate_point(point);
    // Displace the point from the node origin.
    point += transform.disp;
    point
}

/// Vertex types which may apply a transform and produce a resulting transform.
pub trait ApplyTransform<S>
where
    S: BaseFloat,
{
    /// Apply the given transform and return the result.
    fn apply_transform(self, transform: &PreparedTransform<S>) -> Self;
}

impl<S> ApplyTransform<S> for Point3<S>
where
    S: BaseFloat,
{
    fn apply_transform(self, transform: &PreparedTransform<S>) -> Self {
        transform_point(transform, self)
    }
}

impl<I, S> Iterator for TransformedVertices<I, S>
where
    I: Iterator,
    I::Item: ApplyTransform<S>,
    S: BaseFloat,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        self.vertices
            .next()
            .map(|vertex| vertex.apply_transform(&self.transform))
    }
}

impl<I, V, S> Iterator for TransformedTriangles<I, V, S>
where
    I: Iterator<Item = geom::Tri<V>>,
    V: geom::Vertex + ApplyTransform<S>,
    S: BaseFloat,
{
    type Item = geom::Tri<V>;
    fn next(&mut self) -> Option<Self::Item> {
        self.triangles
            .next()
            .map(|tri| tri.map_vertices(|vertex| vertex.apply_transform(&self.transform)))
    }
}
<|endoftext|>