<commit_before>use std::ops::Mul;

struct Matrix {
	dim1: i32,
	dim2: i32
}

impl Mul<f32> for Matrix {
	type Output = Matrix;

	fn mul(self, f: f32) -> Matrix {

	}
}

impl Mul<Matrix> for Matrix {
	type Output = Matrix;

	fn mul(self, f: f32) -> Matrix {

	}
}<commit_msg>Adding more to stub<commit_after>use std::ops::Mul;
use std::ops::Add;
use std::ops::Div;

struct Matrix {
	dim1: i32,
	dim2: i32
}

impl Mul<f32> for Matrix {
	type Output = Matrix;

	fn mul(self, f: f32) -> Matrix {

	}
}

impl Mul<Matrix> for Matrix {
	type Output = Matrix;

	fn mul(self, f: Matrix) -> Matrix {
		// Will use Strassen algorithm if large, traditional otherwise
	}
}

impl Add<Matrix> for Matrix {
	type Output = Matrix;

	fn mul(self, f: Matrix) -> Matrix {

	}
}

impl Div<f32> for Matrix {
	type Output = Matrix;

	fn mul(self, f: f32) -> Matrix {

	}
}<|endoftext|>


<commit_before>#![crate_name = "foo"]
#![feature(const_evaluatable_checked, const_generics)]
#![allow(incomplete_features)]
// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
pub struct Ice<const N: usize> where [(); N + 1]:;
<commit_msg>add `@has`<commit_after>#![crate_name = "foo"]
#![feature(const_evaluatable_checked, const_generics)]
#![allow(incomplete_features)]
// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \
//      'pub struct Ice<const N: usize> where [(); N + 1]: ;'
pub struct Ice<const N: usize> where [(); N + 1]:;
<|endoftext|>


<commit_before>extern crate walkdir;

use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use walkdir::{DirEntry, WalkDir};

macro_rules! forward_features {
	($cmd:expr, $($feature:literal,)+ ) => {
		let mut features = vec![];

		$(
			if cfg!(feature = $feature) {
				features.push($feature);
			}
		)+

		if !features.is_empty() {
			$cmd.arg("--features");
			$cmd.arg(features.join(" "));
		}
	};
}

fn build_hermit(src_dir: &Path, target_dir_opt: Option<&Path>) {
	let manifest_path = src_dir.join("Cargo.toml");
	assert!(
		manifest_path.exists(),
		"kernel manifest path `{}` does not exist",
		manifest_path.display()
	);
	let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");

	let kernel_triple = match target_arch.as_str() {
		"x86_64" => "x86_64-unknown-none-hermitkernel",
		"aarch64" => "aarch64-unknown-hermit",
		_ => panic!("Unsupported target arch: {}", target_arch),
	};

	cmd.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg(kernel_triple)
		.arg("--manifest-path")
		.arg("Cargo.toml");

	cmd.current_dir(src_dir);

	cmd.env_remove("RUSTUP_TOOLCHAIN");
	if option_env!("RUSTC_WORKSPACE_WRAPPER")
		.unwrap_or_default()
		.ends_with("clippy-driver")
	{
		cmd.env("RUSTC_WORKSPACE_WRAPPER", "clippy-driver");
	}

	cmd.env("CARGO_TERM_COLOR", "always");

	if let Some(target_dir) = target_dir_opt {
		cmd.arg("--target-dir").arg(target_dir);
	}
	let target_dir = match target_dir_opt {
		Some(target_dir) => target_dir.to_path_buf(),
		None => src_dir.join("target"),
	};

	if profile == "release" {
		cmd.arg("--release");
	}

	// Control enabled features via this crate's features
	cmd.arg("--no-default-features");
	forward_features!(cmd, "acpi", "fsgsbase", "pci", "smp", "vga",);

	let mut rustflags = vec!["-Zmutable-noalias=no".to_string()];
	let outer_rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();

	#[cfg(feature = "instrument")]
	{
		rustflags.push("-Zinstrument-mcount".to_string());
		// Add outer rustflags to command
		rustflags.push(outer_rustflags);
	}

	#[cfg(not(feature = "instrument"))]
	{
		// If the `instrument` feature feature is not enabled,
		// filter it from outer rustflags before adding them to the command.
		if !outer_rustflags.is_empty() {
			let flags = outer_rustflags
				.split('\x1f')
				.filter(|&flag| !flag.contains("instrument-mcount"))
				.map(String::from);
			rustflags.extend(flags);
		}
	}

	cmd.env("CARGO_ENCODED_RUSTFLAGS", rustflags.join("\x1f"));

	let status = cmd.status().expect("failed to start kernel build");
	assert!(status.success());

	let lib_location = target_dir
		.join(kernel_triple)
		.join(&profile)
		.canonicalize()
		.unwrap();

	println!("Lib location: {}", lib_location.display());

	let lib = lib_location.join("libhermit.a");

	let mut symbols = vec!["rust_begin_unwind", "rust_oom"];

	if target_arch == "aarch64" {
		symbols.extend(include_str!("aarch64-duplicate-symbols").lines());
	}

	rename_symbols(symbols, &lib);

	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

/// Kernel and user space has its own versions of panic handler, oom handler, memcpy, memset, etc,
/// Consequently, we rename the functions in the libos to avoid collisions.
fn rename_symbols(symbols: impl IntoIterator<Item = impl AsRef<OsStr>>, lib: impl AsRef<Path>) {
	let args = symbols.into_iter().flat_map(|symbol| {
		let option = OsStr::new("--redefine-sym");
		let arg = [symbol.as_ref(), "=kernel-".as_ref(), symbol.as_ref()]
			.into_iter()
			.collect::<OsString>();
		[Cow::Borrowed(option), Cow::Owned(arg)]
	});

	let status = Command::new("rust-objcopy")
		.args(args)
		.arg(lib.as_ref())
		.status()
		.expect("Failed to execute rust-objcopy. Is cargo-binutils installed?");
	assert!(status.success(), "rust-objcopy was not successful");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	if !src_dir.as_path().exists() {
		let status = Command::new(env!("CARGO"))
			.current_dir(out_dir)
			.arg("download")
			.arg("--output")
			.arg(src_dir.clone().into_os_string())
			.arg("--extract")
			.arg("rusty-hermit")
			.status()
			.expect("failed to start kernel download");
		assert!(
			status.success(),
			"Unable to download rusty-hermit. Is cargo-download installed?"
		);
	}

	build_hermit(src_dir.as_ref(), None);
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let target_dir = out_dir.join("target");
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref(), Some(target_dir.as_ref()));
	configure_cargo_rerun_if_changed(src_dir.as_ref());
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn configure_cargo_rerun_if_changed(src_dir: &Path) {
	fn is_not_ignored(entry: &DirEntry) -> bool {
		// Ignore .git .vscode and target directories, but not .cargo or .github
		if entry.depth() == 1
			&& entry.path().is_dir()
			&& (entry.path().ends_with("target")
				|| entry.path().ends_with(".git")
				|| entry.path().ends_with(".vscode"))
		{
			return false;
		}
		true
	}

	WalkDir::new(src_dir)
		.into_iter()
		.filter_entry(is_not_ignored)
		.filter_map(|v| v.ok())
		.filter_map(|v| v.path().canonicalize().ok())
		.for_each(|x| println!("cargo:rerun-if-changed={}", x.display()));
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(&mut f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(&mut f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway)
		.expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(&mut f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<commit_msg>Clippy: Fix needless_borrow<commit_after>extern crate walkdir;

use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use walkdir::{DirEntry, WalkDir};

macro_rules! forward_features {
	($cmd:expr, $($feature:literal,)+ ) => {
		let mut features = vec![];

		$(
			if cfg!(feature = $feature) {
				features.push($feature);
			}
		)+

		if !features.is_empty() {
			$cmd.arg("--features");
			$cmd.arg(features.join(" "));
		}
	};
}

fn build_hermit(src_dir: &Path, target_dir_opt: Option<&Path>) {
	let manifest_path = src_dir.join("Cargo.toml");
	assert!(
		manifest_path.exists(),
		"kernel manifest path `{}` does not exist",
		manifest_path.display()
	);
	let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");

	let kernel_triple = match target_arch.as_str() {
		"x86_64" => "x86_64-unknown-none-hermitkernel",
		"aarch64" => "aarch64-unknown-hermit",
		_ => panic!("Unsupported target arch: {}", target_arch),
	};

	cmd.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg(kernel_triple)
		.arg("--manifest-path")
		.arg("Cargo.toml");

	cmd.current_dir(src_dir);

	cmd.env_remove("RUSTUP_TOOLCHAIN");
	if option_env!("RUSTC_WORKSPACE_WRAPPER")
		.unwrap_or_default()
		.ends_with("clippy-driver")
	{
		cmd.env("RUSTC_WORKSPACE_WRAPPER", "clippy-driver");
	}

	cmd.env("CARGO_TERM_COLOR", "always");

	if let Some(target_dir) = target_dir_opt {
		cmd.arg("--target-dir").arg(target_dir);
	}
	let target_dir = match target_dir_opt {
		Some(target_dir) => target_dir.to_path_buf(),
		None => src_dir.join("target"),
	};

	if profile == "release" {
		cmd.arg("--release");
	}

	// Control enabled features via this crate's features
	cmd.arg("--no-default-features");
	forward_features!(cmd, "acpi", "fsgsbase", "pci", "smp", "vga",);

	let mut rustflags = vec!["-Zmutable-noalias=no".to_string()];
	let outer_rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();

	#[cfg(feature = "instrument")]
	{
		rustflags.push("-Zinstrument-mcount".to_string());
		// Add outer rustflags to command
		rustflags.push(outer_rustflags);
	}

	#[cfg(not(feature = "instrument"))]
	{
		// If the `instrument` feature feature is not enabled,
		// filter it from outer rustflags before adding them to the command.
		if !outer_rustflags.is_empty() {
			let flags = outer_rustflags
				.split('\x1f')
				.filter(|&flag| !flag.contains("instrument-mcount"))
				.map(String::from);
			rustflags.extend(flags);
		}
	}

	cmd.env("CARGO_ENCODED_RUSTFLAGS", rustflags.join("\x1f"));

	let status = cmd.status().expect("failed to start kernel build");
	assert!(status.success());

	let lib_location = target_dir
		.join(kernel_triple)
		.join(&profile)
		.canonicalize()
		.unwrap();

	println!("Lib location: {}", lib_location.display());

	let lib = lib_location.join("libhermit.a");

	let mut symbols = vec!["rust_begin_unwind", "rust_oom"];

	if target_arch == "aarch64" {
		symbols.extend(include_str!("aarch64-duplicate-symbols").lines());
	}

	rename_symbols(symbols, &lib);

	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

/// Kernel and user space has its own versions of panic handler, oom handler, memcpy, memset, etc,
/// Consequently, we rename the functions in the libos to avoid collisions.
fn rename_symbols(symbols: impl IntoIterator<Item = impl AsRef<OsStr>>, lib: impl AsRef<Path>) {
	let args = symbols.into_iter().flat_map(|symbol| {
		let option = OsStr::new("--redefine-sym");
		let arg = [symbol.as_ref(), "=kernel-".as_ref(), symbol.as_ref()]
			.into_iter()
			.collect::<OsString>();
		[Cow::Borrowed(option), Cow::Owned(arg)]
	});

	let status = Command::new("rust-objcopy")
		.args(args)
		.arg(lib.as_ref())
		.status()
		.expect("Failed to execute rust-objcopy. Is cargo-binutils installed?");
	assert!(status.success(), "rust-objcopy was not successful");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	if !src_dir.as_path().exists() {
		let status = Command::new(env!("CARGO"))
			.current_dir(out_dir)
			.arg("download")
			.arg("--output")
			.arg(src_dir.clone().into_os_string())
			.arg("--extract")
			.arg("rusty-hermit")
			.status()
			.expect("failed to start kernel download");
		assert!(
			status.success(),
			"Unable to download rusty-hermit. Is cargo-download installed?"
		);
	}

	build_hermit(src_dir.as_ref(), None);
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let target_dir = out_dir.join("target");
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref(), Some(target_dir.as_ref()));
	configure_cargo_rerun_if_changed(src_dir.as_ref());
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn configure_cargo_rerun_if_changed(src_dir: &Path) {
	fn is_not_ignored(entry: &DirEntry) -> bool {
		// Ignore .git .vscode and target directories, but not .cargo or .github
		if entry.depth() == 1
			&& entry.path().is_dir()
			&& (entry.path().ends_with("target")
				|| entry.path().ends_with(".git")
				|| entry.path().ends_with(".vscode"))
		{
			return false;
		}
		true
	}

	WalkDir::new(src_dir)
		.into_iter()
		.filter_entry(is_not_ignored)
		.filter_map(|v| v.ok())
		.filter_map(|v| v.path().canonicalize().ok())
		.for_each(|x| println!("cargo:rerun-if-changed={}", x.display()));
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<|endoftext|>


<commit_before>use crate::{rect::Rect, texture::Texture};
use std::borrow::Cow;

pub struct SubTexture<'a, T: 'a + Clone> {
    texture: Cow<'a, T>,
    source: Rect,
}

impl<'a, T: Texture + Clone> SubTexture<'a, T> {
    pub fn new(texture: T, source: Rect) -> SubTexture<'a, T> {
        SubTexture {
            texture: Cow::Owned(texture),
            source: source,
        }
    }

    pub fn from_ref(texture: &'a T, source: Rect) -> SubTexture<'a, T> {
        SubTexture {
            texture: Cow::Borrowed(texture),
            source: source,
        }
    }
}

impl<'a, T: Texture + Clone> Texture for SubTexture<'a, T> {
    type Pixel = T::Pixel;

    fn width(&self) -> u32 {
        self.source.w
    }

    fn height(&self) -> u32 {
        self.source.h
    }

    fn get(&self, x: u32, y: u32) -> Option<T::Pixel> {
        let x = self.source.x + x;
        let y = self.source.y + y;
        self.texture.get(x, y)
    }

    fn set(&mut self, x: u32, y: u32, val: T::Pixel) {
        if let Cow::Owned(ref mut t) = self.texture {
            let x = self.source.x + x;
            let y = self.source.y + y;
            t.set(x, y, val);
        } else {
            panic!("Can't set pixel by borrowed reference");
        }
    }
}
<commit_msg>docs: Document sub_texture module contents<commit_after>//! Sub-texture [Texture].
use crate::{rect::Rect, texture::Texture};
use std::borrow::Cow;

/// Texture that is a subset of another texture.
pub struct SubTexture<'a, T: 'a + Clone> {
    texture: Cow<'a, T>,
    source: Rect,
}

impl<'a, T: Texture + Clone> SubTexture<'a, T> {
    /// Get a `SubTexture` owning the parent texture.
    pub fn new(texture: T, source: Rect) -> SubTexture<'a, T> {
        SubTexture {
            texture: Cow::Owned(texture),
            source: source,
        }
    }

    /// Get a `SubTexture` referencing the parent texture.
    pub fn from_ref(texture: &'a T, source: Rect) -> SubTexture<'a, T> {
        SubTexture {
            texture: Cow::Borrowed(texture),
            source: source,
        }
    }
}

impl<'a, T: Texture + Clone> Texture for SubTexture<'a, T> {
    type Pixel = T::Pixel;

    fn width(&self) -> u32 {
        self.source.w
    }

    fn height(&self) -> u32 {
        self.source.h
    }

    fn get(&self, x: u32, y: u32) -> Option<T::Pixel> {
        let x = self.source.x + x;
        let y = self.source.y + y;
        self.texture.get(x, y)
    }

    fn set(&mut self, x: u32, y: u32, val: T::Pixel) {
        if let Cow::Owned(ref mut t) = self.texture {
            let x = self.source.x + x;
            let y = self.source.y + y;
            t.set(x, y, val);
        } else {
            panic!("Can't set pixel by borrowed reference");
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Helper module to build up a selector safely and efficiently.
//!
//! Our selector representation is designed to optimize matching, and has
//! several requirements:
//! * All simple selectors and combinators are stored inline in the same buffer
//!   as Component instances.
//! * We store the top-level compound selectors from right to left, i.e. in
//!   matching order.
//! * We store the simple selectors for each combinator from left to right, so
//!   that we match the cheaper simple selectors first.
//!
//! Meeting all these constraints without extra memmove traffic during parsing
//! is non-trivial. This module encapsulates those details and presents an
//! easy-to-use API for the parser.

use parser::{Combinator, Component, SelectorImpl};
use servo_arc::{Arc, HeaderWithLength, ThinArc};
use sink::Push;
use smallvec::{self, SmallVec};
use std::cmp;
use std::iter;
use std::ops::{AddAssign, Add};
use std::ptr;
use std::slice;

/// Top-level SelectorBuilder struct. This should be stack-allocated by the
/// consumer and never moved (because it contains a lot of inline data that
/// would be slow to memmov).
///
/// After instantation, callers may call the push_simple_selector() and
/// push_combinator() methods to append selector data as it is encountered
/// (from left to right). Once the process is complete, callers should invoke
/// build(), which transforms the contents of the SelectorBuilder into a heap-
/// allocated Selector and leaves the builder in a drained state.
#[derive(Debug)]
pub struct SelectorBuilder<Impl: SelectorImpl> {
    /// The entire sequence of simple selectors, from left to right, without combinators.
    ///
    /// We make this large because the result of parsing a selector is fed into a new
    /// Arc-ed allocation, so any spilled vec would be a wasted allocation. Also,
    /// Components are large enough that we don't have much cache locality benefit
    /// from reserving stack space for fewer of them.
    simple_selectors: SmallVec<[Component<Impl>; 32]>,
    /// The combinators, and the length of the compound selector to their left.
    combinators: SmallVec<[(Combinator, usize); 16]>,
    /// The length of the current compount selector.
    current_len: usize,
}

impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
    #[inline(always)]
    fn default() -> Self {
        SelectorBuilder {
            simple_selectors: SmallVec::new(),
            combinators: SmallVec::new(),
            current_len: 0,
        }
    }
}

impl<Impl: SelectorImpl> Push<Component<Impl>> for SelectorBuilder<Impl> {
    fn push(&mut self, value: Component<Impl>) {
        self.push_simple_selector(value);
    }
}

impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
    /// Pushes a simple selector onto the current compound selector.
    #[inline(always)]
    pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
        debug_assert!(!ss.is_combinator());
        self.simple_selectors.push(ss);
        self.current_len += 1;
    }

    /// Completes the current compound selector and starts a new one, delimited
    /// by the given combinator.
    #[inline(always)]
    pub fn push_combinator(&mut self, c: Combinator) {
        self.combinators.push((c, self.current_len));
        self.current_len = 0;
    }

    /// Returns true if no simple selectors have ever been pushed to this builder.
    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.simple_selectors.is_empty()
    }

    /// Returns true if combinators have ever been pushed to this builder.
    #[inline(always)]
    pub fn has_combinators(&self) -> bool {
        !self.combinators.is_empty()
    }

    /// Consumes the builder, producing a Selector.
    #[inline(always)]
    pub fn build(
        &mut self,
        parsed_pseudo: bool,
        parsed_slotted: bool,
    ) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
        // Compute the specificity and flags.
        let mut spec = SpecificityAndFlags(specificity(self.simple_selectors.iter()));
        if parsed_pseudo {
            spec.0 |= HAS_PSEUDO_BIT;
        }

        if parsed_slotted {
            spec.0 |= HAS_SLOTTED_BIT;
        }

        self.build_with_specificity_and_flags(spec)
    }

    /// Builds with an explicit SpecificityAndFlags. This is separated from build() so
    /// that unit tests can pass an explicit specificity.
    #[inline(always)]
    pub fn build_with_specificity_and_flags(
        &mut self,
        spec: SpecificityAndFlags,
    ) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
        // First, compute the total number of Components we'll need to allocate
        // space for.
        let full_len = self.simple_selectors.len() + self.combinators.len();

        // Create the header.
        let header = HeaderWithLength::new(spec, full_len);

        // Create the Arc using an iterator that drains our buffers.

        // Use a raw pointer to be able to call set_len despite "borrowing" the slice.
        // This is similar to SmallVec::drain, but we use a slice here because
        // we’re gonna traverse it non-linearly.
        let raw_simple_selectors: *const [Component<Impl>] = &*self.simple_selectors;
        unsafe {
            // Panic-safety: if SelectorBuilderIter is not iterated to the end,
            // some simple selectors will safely leak.
            self.simple_selectors.set_len(0)
        }
        let (rest, current) = split_from_end(unsafe { &*raw_simple_selectors }, self.current_len);
        let iter = SelectorBuilderIter {
            current_simple_selectors: current.iter(),
            rest_of_simple_selectors: rest,
            combinators: self.combinators.drain().rev(),
        };

        Arc::into_thin(Arc::from_header_and_iter(header, iter))
    }
}

struct SelectorBuilderIter<'a, Impl: SelectorImpl> {
    current_simple_selectors: slice::Iter<'a, Component<Impl>>,
    rest_of_simple_selectors: &'a [Component<Impl>],
    combinators: iter::Rev<smallvec::Drain<'a, (Combinator, usize)>>,
}

impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> {
    fn len(&self) -> usize {
        self.current_simple_selectors.len() +
            self.rest_of_simple_selectors.len() +
            self.combinators.len()
    }
}

impl<'a, Impl: SelectorImpl> Iterator for SelectorBuilderIter<'a, Impl> {
    type Item = Component<Impl>;
    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(simple_selector_ref) = self.current_simple_selectors.next() {
            // Move a simple selector out of this slice iterator.
            // This is safe because we’ve called SmallVec::set_len(0) above,
            // so SmallVec::drop won’t drop this simple selector.
            unsafe { Some(ptr::read(simple_selector_ref)) }
        } else {
            self.combinators.next().map(|(combinator, len)| {
                let (rest, current) = split_from_end(self.rest_of_simple_selectors, len);
                self.rest_of_simple_selectors = rest;
                self.current_simple_selectors = current.iter();
                Component::Combinator(combinator)
            })
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len(), Some(self.len()))
    }
}

fn split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T]) {
    s.split_at(s.len() - at)
}

pub const HAS_PSEUDO_BIT: u32 = 1 << 30;
pub const HAS_SLOTTED_BIT: u32 = 1 << 31;

/// We use ten bits for each specificity kind (id, class, element), and the two
/// high bits for the pseudo and slotted flags.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SpecificityAndFlags(pub u32);

impl SpecificityAndFlags {
    #[inline]
    pub fn specificity(&self) -> u32 {
        self.0 & !(HAS_PSEUDO_BIT | HAS_SLOTTED_BIT)
    }

    #[inline]
    pub fn has_pseudo_element(&self) -> bool {
        (self.0 & HAS_PSEUDO_BIT) != 0
    }

    #[inline]
    pub fn is_slotted(&self) -> bool {
        (self.0 & HAS_SLOTTED_BIT) != 0
    }
}

const MAX_10BIT: u32 = (1u32 << 10) - 1;

#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
struct Specificity {
    id_selectors: u32,
    class_like_selectors: u32,
    element_selectors: u32,
}

impl AddAssign for Specificity {
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        self.id_selectors += rhs.id_selectors;
        self.class_like_selectors += rhs.class_like_selectors;
        self.element_selectors += rhs.element_selectors;
    }
}

impl Add for Specificity {
    type Output = Specificity;

    fn add(self, rhs: Specificity) -> Specificity {
        Specificity {
            id_selectors: self.id_selectors + rhs.id_selectors,
            class_like_selectors: self.class_like_selectors + rhs.class_like_selectors,
            element_selectors: self.element_selectors + rhs.element_selectors,
        }
    }
}

impl Default for Specificity {
    fn default() -> Specificity {
        Specificity {
            id_selectors: 0,
            class_like_selectors: 0,
            element_selectors: 0,
        }
    }
}

impl From<u32> for Specificity {
    #[inline]
    fn from(value: u32) -> Specificity {
        assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
        Specificity {
            id_selectors: value >> 20,
            class_like_selectors: (value >> 10) & MAX_10BIT,
            element_selectors: value & MAX_10BIT,
        }
    }
}

impl From<Specificity> for u32 {
    #[inline]
    fn from(specificity: Specificity) -> u32 {
        cmp::min(specificity.id_selectors, MAX_10BIT) << 20 |
            cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10 |
            cmp::min(specificity.element_selectors, MAX_10BIT)
    }
}

fn specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> u32
where
    Impl: SelectorImpl,
{
    complex_selector_specificity(iter).into()
}

fn complex_selector_specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> Specificity
where
    Impl: SelectorImpl,
{
    fn simple_selector_specificity<Impl>(
        simple_selector: &Component<Impl>,
        specificity: &mut Specificity,
    ) where
        Impl: SelectorImpl,
    {
        match *simple_selector {
            Component::Combinator(..) => {
                unreachable!("Found combinator in simple selectors vector?");
            },
            Component::PseudoElement(..) | Component::LocalName(..) => {
                specificity.element_selectors += 1
            },
            Component::Slotted(ref selector) => {
                specificity.element_selectors += 1;
                // Note that due to the way ::slotted works we only compete with
                // other ::slotted rules, so the above rule doesn't really
                // matter, but we do it still for consistency with other
                // pseudo-elements.
                //
                // See: https://github.com/w3c/csswg-drafts/issues/1915
                *specificity += Specificity::from(selector.specificity());
            },
            Component::Host(ref selector) => {
                specificity.class_like_selectors += 1;
                if let Some(ref selector) = *selector {
                    // See: https://github.com/w3c/csswg-drafts/issues/1915
                    *specificity += Specificity::from(selector.specificity());
                }
            },
            Component::ID(..) => {
                specificity.id_selectors += 1;
            },
            Component::Class(..) |
            Component::AttributeInNoNamespace { .. } |
            Component::AttributeInNoNamespaceExists { .. } |
            Component::AttributeOther(..) |
            Component::FirstChild |
            Component::LastChild |
            Component::OnlyChild |
            Component::Root |
            Component::Empty |
            Component::Scope |
            Component::NthChild(..) |
            Component::NthLastChild(..) |
            Component::NthOfType(..) |
            Component::NthLastOfType(..) |
            Component::FirstOfType |
            Component::LastOfType |
            Component::OnlyOfType |
            Component::NonTSPseudoClass(..) => {
                specificity.class_like_selectors += 1;
            },
            Component::ExplicitUniversalType |
            Component::ExplicitAnyNamespace |
            Component::ExplicitNoNamespace |
            Component::DefaultNamespace(..) |
            Component::Namespace(..) => {
                // Does not affect specificity
            },
            Component::Negation(ref negated) => {
                for ss in negated.iter() {
                    simple_selector_specificity(&ss, specificity);
                }
            },
        }
    }

    let mut specificity = Default::default();
    for simple_selector in iter {
        simple_selector_specificity(&simple_selector, &mut specificity);
    }
    specificity
}
<commit_msg>style: Assert earlier to try to get a more helpful stack.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Helper module to build up a selector safely and efficiently.
//!
//! Our selector representation is designed to optimize matching, and has
//! several requirements:
//! * All simple selectors and combinators are stored inline in the same buffer
//!   as Component instances.
//! * We store the top-level compound selectors from right to left, i.e. in
//!   matching order.
//! * We store the simple selectors for each combinator from left to right, so
//!   that we match the cheaper simple selectors first.
//!
//! Meeting all these constraints without extra memmove traffic during parsing
//! is non-trivial. This module encapsulates those details and presents an
//! easy-to-use API for the parser.

use parser::{Combinator, Component, SelectorImpl};
use servo_arc::{Arc, HeaderWithLength, ThinArc};
use sink::Push;
use smallvec::{self, SmallVec};
use std::cmp;
use std::iter;
use std::ops::{AddAssign, Add};
use std::ptr;
use std::slice;

/// Top-level SelectorBuilder struct. This should be stack-allocated by the
/// consumer and never moved (because it contains a lot of inline data that
/// would be slow to memmov).
///
/// After instantation, callers may call the push_simple_selector() and
/// push_combinator() methods to append selector data as it is encountered
/// (from left to right). Once the process is complete, callers should invoke
/// build(), which transforms the contents of the SelectorBuilder into a heap-
/// allocated Selector and leaves the builder in a drained state.
#[derive(Debug)]
pub struct SelectorBuilder<Impl: SelectorImpl> {
    /// The entire sequence of simple selectors, from left to right, without combinators.
    ///
    /// We make this large because the result of parsing a selector is fed into a new
    /// Arc-ed allocation, so any spilled vec would be a wasted allocation. Also,
    /// Components are large enough that we don't have much cache locality benefit
    /// from reserving stack space for fewer of them.
    simple_selectors: SmallVec<[Component<Impl>; 32]>,
    /// The combinators, and the length of the compound selector to their left.
    combinators: SmallVec<[(Combinator, usize); 16]>,
    /// The length of the current compount selector.
    current_len: usize,
}

impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
    #[inline(always)]
    fn default() -> Self {
        SelectorBuilder {
            simple_selectors: SmallVec::new(),
            combinators: SmallVec::new(),
            current_len: 0,
        }
    }
}

impl<Impl: SelectorImpl> Push<Component<Impl>> for SelectorBuilder<Impl> {
    fn push(&mut self, value: Component<Impl>) {
        self.push_simple_selector(value);
    }
}

impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
    /// Pushes a simple selector onto the current compound selector.
    #[inline(always)]
    pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
        assert!(!ss.is_combinator());
        self.simple_selectors.push(ss);
        self.current_len += 1;
    }

    /// Completes the current compound selector and starts a new one, delimited
    /// by the given combinator.
    #[inline(always)]
    pub fn push_combinator(&mut self, c: Combinator) {
        self.combinators.push((c, self.current_len));
        self.current_len = 0;
    }

    /// Returns true if no simple selectors have ever been pushed to this builder.
    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.simple_selectors.is_empty()
    }

    /// Returns true if combinators have ever been pushed to this builder.
    #[inline(always)]
    pub fn has_combinators(&self) -> bool {
        !self.combinators.is_empty()
    }

    /// Consumes the builder, producing a Selector.
    #[inline(always)]
    pub fn build(
        &mut self,
        parsed_pseudo: bool,
        parsed_slotted: bool,
    ) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
        // Compute the specificity and flags.
        let mut spec = SpecificityAndFlags(specificity(self.simple_selectors.iter()));
        if parsed_pseudo {
            spec.0 |= HAS_PSEUDO_BIT;
        }

        if parsed_slotted {
            spec.0 |= HAS_SLOTTED_BIT;
        }

        self.build_with_specificity_and_flags(spec)
    }

    /// Builds with an explicit SpecificityAndFlags. This is separated from build() so
    /// that unit tests can pass an explicit specificity.
    #[inline(always)]
    pub fn build_with_specificity_and_flags(
        &mut self,
        spec: SpecificityAndFlags,
    ) -> ThinArc<SpecificityAndFlags, Component<Impl>> {
        // First, compute the total number of Components we'll need to allocate
        // space for.
        let full_len = self.simple_selectors.len() + self.combinators.len();

        // Create the header.
        let header = HeaderWithLength::new(spec, full_len);

        // Create the Arc using an iterator that drains our buffers.

        // Use a raw pointer to be able to call set_len despite "borrowing" the slice.
        // This is similar to SmallVec::drain, but we use a slice here because
        // we’re gonna traverse it non-linearly.
        let raw_simple_selectors: *const [Component<Impl>] = &*self.simple_selectors;
        unsafe {
            // Panic-safety: if SelectorBuilderIter is not iterated to the end,
            // some simple selectors will safely leak.
            self.simple_selectors.set_len(0)
        }
        let (rest, current) = split_from_end(unsafe { &*raw_simple_selectors }, self.current_len);
        let iter = SelectorBuilderIter {
            current_simple_selectors: current.iter(),
            rest_of_simple_selectors: rest,
            combinators: self.combinators.drain().rev(),
        };

        Arc::into_thin(Arc::from_header_and_iter(header, iter))
    }
}

struct SelectorBuilderIter<'a, Impl: SelectorImpl> {
    current_simple_selectors: slice::Iter<'a, Component<Impl>>,
    rest_of_simple_selectors: &'a [Component<Impl>],
    combinators: iter::Rev<smallvec::Drain<'a, (Combinator, usize)>>,
}

impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> {
    fn len(&self) -> usize {
        self.current_simple_selectors.len() +
            self.rest_of_simple_selectors.len() +
            self.combinators.len()
    }
}

impl<'a, Impl: SelectorImpl> Iterator for SelectorBuilderIter<'a, Impl> {
    type Item = Component<Impl>;
    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(simple_selector_ref) = self.current_simple_selectors.next() {
            // Move a simple selector out of this slice iterator.
            // This is safe because we’ve called SmallVec::set_len(0) above,
            // so SmallVec::drop won’t drop this simple selector.
            unsafe { Some(ptr::read(simple_selector_ref)) }
        } else {
            self.combinators.next().map(|(combinator, len)| {
                let (rest, current) = split_from_end(self.rest_of_simple_selectors, len);
                self.rest_of_simple_selectors = rest;
                self.current_simple_selectors = current.iter();
                Component::Combinator(combinator)
            })
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len(), Some(self.len()))
    }
}

fn split_from_end<T>(s: &[T], at: usize) -> (&[T], &[T]) {
    s.split_at(s.len() - at)
}

pub const HAS_PSEUDO_BIT: u32 = 1 << 30;
pub const HAS_SLOTTED_BIT: u32 = 1 << 31;

/// We use ten bits for each specificity kind (id, class, element), and the two
/// high bits for the pseudo and slotted flags.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SpecificityAndFlags(pub u32);

impl SpecificityAndFlags {
    #[inline]
    pub fn specificity(&self) -> u32 {
        self.0 & !(HAS_PSEUDO_BIT | HAS_SLOTTED_BIT)
    }

    #[inline]
    pub fn has_pseudo_element(&self) -> bool {
        (self.0 & HAS_PSEUDO_BIT) != 0
    }

    #[inline]
    pub fn is_slotted(&self) -> bool {
        (self.0 & HAS_SLOTTED_BIT) != 0
    }
}

const MAX_10BIT: u32 = (1u32 << 10) - 1;

#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
struct Specificity {
    id_selectors: u32,
    class_like_selectors: u32,
    element_selectors: u32,
}

impl AddAssign for Specificity {
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        self.id_selectors += rhs.id_selectors;
        self.class_like_selectors += rhs.class_like_selectors;
        self.element_selectors += rhs.element_selectors;
    }
}

impl Add for Specificity {
    type Output = Specificity;

    fn add(self, rhs: Specificity) -> Specificity {
        Specificity {
            id_selectors: self.id_selectors + rhs.id_selectors,
            class_like_selectors: self.class_like_selectors + rhs.class_like_selectors,
            element_selectors: self.element_selectors + rhs.element_selectors,
        }
    }
}

impl Default for Specificity {
    fn default() -> Specificity {
        Specificity {
            id_selectors: 0,
            class_like_selectors: 0,
            element_selectors: 0,
        }
    }
}

impl From<u32> for Specificity {
    #[inline]
    fn from(value: u32) -> Specificity {
        assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
        Specificity {
            id_selectors: value >> 20,
            class_like_selectors: (value >> 10) & MAX_10BIT,
            element_selectors: value & MAX_10BIT,
        }
    }
}

impl From<Specificity> for u32 {
    #[inline]
    fn from(specificity: Specificity) -> u32 {
        cmp::min(specificity.id_selectors, MAX_10BIT) << 20 |
            cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10 |
            cmp::min(specificity.element_selectors, MAX_10BIT)
    }
}

fn specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> u32
where
    Impl: SelectorImpl,
{
    complex_selector_specificity(iter).into()
}

fn complex_selector_specificity<Impl>(iter: slice::Iter<Component<Impl>>) -> Specificity
where
    Impl: SelectorImpl,
{
    fn simple_selector_specificity<Impl>(
        simple_selector: &Component<Impl>,
        specificity: &mut Specificity,
    ) where
        Impl: SelectorImpl,
    {
        match *simple_selector {
            Component::Combinator(..) => {
                unreachable!("Found combinator in simple selectors vector?");
            },
            Component::PseudoElement(..) | Component::LocalName(..) => {
                specificity.element_selectors += 1
            },
            Component::Slotted(ref selector) => {
                specificity.element_selectors += 1;
                // Note that due to the way ::slotted works we only compete with
                // other ::slotted rules, so the above rule doesn't really
                // matter, but we do it still for consistency with other
                // pseudo-elements.
                //
                // See: https://github.com/w3c/csswg-drafts/issues/1915
                *specificity += Specificity::from(selector.specificity());
            },
            Component::Host(ref selector) => {
                specificity.class_like_selectors += 1;
                if let Some(ref selector) = *selector {
                    // See: https://github.com/w3c/csswg-drafts/issues/1915
                    *specificity += Specificity::from(selector.specificity());
                }
            },
            Component::ID(..) => {
                specificity.id_selectors += 1;
            },
            Component::Class(..) |
            Component::AttributeInNoNamespace { .. } |
            Component::AttributeInNoNamespaceExists { .. } |
            Component::AttributeOther(..) |
            Component::FirstChild |
            Component::LastChild |
            Component::OnlyChild |
            Component::Root |
            Component::Empty |
            Component::Scope |
            Component::NthChild(..) |
            Component::NthLastChild(..) |
            Component::NthOfType(..) |
            Component::NthLastOfType(..) |
            Component::FirstOfType |
            Component::LastOfType |
            Component::OnlyOfType |
            Component::NonTSPseudoClass(..) => {
                specificity.class_like_selectors += 1;
            },
            Component::ExplicitUniversalType |
            Component::ExplicitAnyNamespace |
            Component::ExplicitNoNamespace |
            Component::DefaultNamespace(..) |
            Component::Namespace(..) => {
                // Does not affect specificity
            },
            Component::Negation(ref negated) => {
                for ss in negated.iter() {
                    simple_selector_specificity(&ss, specificity);
                }
            },
        }
    }

    let mut specificity = Default::default();
    for simple_selector in iter {
        simple_selector_specificity(&simple_selector, &mut specificity);
    }
    specificity
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::accept_type::AcceptType;
use crate::context::Context;
use crate::failpoint::fail_point_poem;
use crate::response::{
    build_not_found, AptosErrorResponse, BadRequestError, BasicErrorWith404, BasicResponse,
    BasicResponseStatus, BasicResultWith404, InternalError,
};
use crate::ApiTags;
use anyhow::Context as AnyhowContext;
use aptos_api_types::{
    AccountData, Address, AptosErrorCode, AsConverter, LedgerInfo, MoveModuleBytecode,
    MoveResource, MoveStructTag, TransactionId, U64,
};
use aptos_types::access_path::AccessPath;
use aptos_types::account_config::AccountResource;
use aptos_types::account_state::AccountState;
use aptos_types::event::EventHandle;
use aptos_types::event::EventKey;
use aptos_types::state_store::state_key::StateKey;
use move_deps::move_core_types::value::MoveValue;
use move_deps::move_core_types::{
    identifier::Identifier,
    language_storage::{ResourceKey, StructTag},
    move_resource::MoveStructType,
};
use poem_openapi::param::Query;
use poem_openapi::{param::Path, OpenApi};
use std::collections::BTreeMap;
use std::convert::TryInto;
use std::sync::Arc;

pub struct AccountsApi {
    pub context: Arc<Context>,
}

#[OpenApi]
impl AccountsApi {
    /// Get account
    ///
    /// Return high level information about an account such as its sequence number.
    #[oai(
        path = "/accounts/:address",
        method = "get",
        operation_id = "get_account",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<AccountData> {
        fail_point_poem("endpoint_get_account")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.account(&accept_type)
    }

    /// Get account resources
    ///
    /// This endpoint returns all account resources at a given address at a
    /// specific ledger version (AKA transaction version). If the ledger
    /// version is not specified in the request, the latest ledger version is used.
    ///
    /// The Aptos nodes prune account state history, via a configurable time window (link).
    /// If the requested data has been pruned, the server responds with a 404.
    #[oai(
        path = "/accounts/:address/resources",
        method = "get",
        operation_id = "get_account_resources",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account_resources(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<Vec<MoveResource>> {
        fail_point_poem("endpoint_get_account_resources")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.resources(&accept_type)
    }

    /// Get account modules
    ///
    /// This endpoint returns all account modules at a given address at a
    /// specific ledger version (AKA transaction version). If the ledger
    /// version is not specified in the request, the latest ledger version is used.
    ///
    /// The Aptos nodes prune account state history, via a configurable time window (link).
    /// If the requested data has been pruned, the server responds with a 404.
    #[oai(
        path = "/accounts/:address/modules",
        method = "get",
        operation_id = "get_account_modules",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account_modules(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<Vec<MoveModuleBytecode>> {
        fail_point_poem("endpoint_get_account_modules")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.modules(&accept_type)
    }
}

pub struct Account {
    context: Arc<Context>,
    address: Address,
    ledger_version: u64,
    latest_ledger_info: LedgerInfo,
}

impl Account {
    pub fn new(
        context: Arc<Context>,
        address: Address,
        requested_ledger_version: Option<U64>,
    ) -> Result<Self, BasicErrorWith404> {
        let latest_ledger_info = context.get_latest_ledger_info()?;
        let ledger_version: u64 = requested_ledger_version
            .map(|v| v.0)
            .unwrap_or_else(|| latest_ledger_info.version());

        if ledger_version > latest_ledger_info.version() {
            return Err(build_not_found(
                "ledger",
                TransactionId::Version(U64::from(ledger_version)),
                latest_ledger_info.version(),
            ));
        }

        Ok(Self {
            context,
            address,
            ledger_version,
            latest_ledger_info,
        })
    }

    // These functions map directly to endpoint functions.

    pub fn account(self, accept_type: &AcceptType) -> BasicResultWith404<AccountData> {
        let state_key = StateKey::AccessPath(AccessPath::resource_access_path(ResourceKey::new(
            self.address.into(),
            AccountResource::struct_tag(),
        )));

        let state_value = self
            .context
            .get_state_value_poem(&state_key, self.ledger_version)?;

        let state_value = match state_value {
            Some(state_value) => state_value,
            None => return Err(self.resource_not_found(&AccountResource::struct_tag())),
        };

        let account_resource: AccountResource = bcs::from_bytes(&state_value)
            .context("Internal error deserializing response from DB")
            .map_err(BasicErrorWith404::internal)?;
        let account_data: AccountData = account_resource.into();

        match accept_type {
            AcceptType::Json => BasicResponse::try_from_json((
                account_data,
                &self.latest_ledger_info,
                BasicResponseStatus::Ok,
            )),
            AcceptType::Bcs => BasicResponse::try_from_encoded((
                state_value,
                &self.latest_ledger_info,
                BasicResponseStatus::Ok,
            )),
        }
    }

    pub fn resources(self, accept_type: &AcceptType) -> BasicResultWith404<Vec<MoveResource>> {
        let account_state = self.account_state()?;
        let resources = account_state.get_resources();

        match accept_type {
            AcceptType::Json => {
                let move_resolver = self.context.move_resolver_poem()?;
                let converted_resources = move_resolver
                    .as_converter(self.context.db.clone())
                    .try_into_resources(resources)
                    .context("Failed to build move resource response from data in DB")
                    .map_err(BasicErrorWith404::internal)
                    .map_err(|e| e.error_code(AptosErrorCode::InvalidBcsInStorageError))?;

                BasicResponse::try_from_json((
                    converted_resources,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
            AcceptType::Bcs => {
                let resources: BTreeMap<StructTag, Vec<u8>> = resources
                    .map(|(key, value)| (key, value.to_vec()))
                    .collect();
                BasicResponse::try_from_bcs((
                    resources,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
        }
    }

    pub fn modules(self, accept_type: &AcceptType) -> BasicResultWith404<Vec<MoveModuleBytecode>> {
        let mut modules = Vec::new();
        for module in self.account_state()?.into_modules() {
            modules.push(
                MoveModuleBytecode::new(module)
                    .try_parse_abi()
                    .context("Failed to parse move module ABI")
                    .map_err(BasicErrorWith404::internal)
                    .map_err(|e| e.error_code(AptosErrorCode::InvalidBcsInStorageError))?,
            );
        }
        BasicResponse::try_from_rust_value((
            modules,
            &self.latest_ledger_info,
            BasicResponseStatus::Ok,
            accept_type,
        ))
    }

    // Helpers for processing account state.

    fn account_state(&self) -> Result<AccountState, BasicErrorWith404> {
        let state = self
            .context
            .get_account_state(self.address.into(), self.ledger_version)
            .map_err(BasicErrorWith404::internal)
            .map_err(|e| e.error_code(AptosErrorCode::ReadFromStorageError))?
            .ok_or_else(|| self.account_not_found())?;

        Ok(state)
    }

    // Helpers for building errors.

    fn account_not_found(&self) -> BasicErrorWith404 {
        build_not_found(
            "account",
            format!(
                "address({}) and ledger version({})",
                self.address, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    fn resource_not_found(&self, struct_tag: &StructTag) -> BasicErrorWith404 {
        build_not_found(
            "resource",
            format!(
                "address({}), struct tag({}) and ledger version({})",
                self.address, struct_tag, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    fn field_not_found(
        &self,
        struct_tag: &StructTag,
        field_name: &Identifier,
    ) -> BasicErrorWith404 {
        build_not_found(
            "resource",
            format!(
                "address({}), struct tag({}), field name({}) and ledger version({})",
                self.address, struct_tag, field_name, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    // Events specific stuff.

    pub fn find_event_key(
        &self,
        event_handle: MoveStructTag,
        field_name: Identifier,
    ) -> Result<EventKey, BasicErrorWith404> {
        let struct_tag: StructTag = event_handle
            .try_into()
            .context("Given event handle was invalid")
            .map_err(BasicErrorWith404::bad_request)?;

        let resource = self.find_resource(&struct_tag)?;

        let (_id, value) = resource
            .into_iter()
            .find(|(id, _)| id == &field_name)
            .ok_or_else(|| self.field_not_found(&struct_tag, &field_name))?;

        // Serialization should not fail, otherwise it's internal bug
        let event_handle_bytes = bcs::to_bytes(&value)
            .context("Failed to serialize event handle, this is an internal bug")
            .map_err(BasicErrorWith404::internal)?;
        // Deserialization may fail because the bytes are not EventHandle struct type.
        let event_handle: EventHandle = bcs::from_bytes(&event_handle_bytes)
            .context(format!(
                "Deserialization error, field({}) type is not EventHandle struct",
                field_name
            ))
            .map_err(BasicErrorWith404::bad_request)?;
        Ok(*event_handle.key())
    }

    fn find_resource(
        &self,
        struct_tag: &StructTag,
    ) -> Result<Vec<(Identifier, MoveValue)>, BasicErrorWith404> {
        let account_state = self.account_state()?;
        let (typ, data) = account_state
            .get_resources()
            .find(|(tag, _data)| tag == struct_tag)
            .ok_or_else(|| self.resource_not_found(struct_tag))?;
        let move_resolver = self.context.move_resolver_poem()?;
        move_resolver
            .as_converter(self.context.db.clone())
            .move_struct_fields(&typ, data)
            .context("Failed to convert move structs")
            .map_err(BasicErrorWith404::internal)
    }
}
<commit_msg>[api] Add get modules bcs<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::accept_type::AcceptType;
use crate::context::Context;
use crate::failpoint::fail_point_poem;
use crate::response::{
    build_not_found, AptosErrorResponse, BadRequestError, BasicErrorWith404, BasicResponse,
    BasicResponseStatus, BasicResultWith404, InternalError,
};
use crate::ApiTags;
use anyhow::Context as AnyhowContext;
use aptos_api_types::{
    AccountData, Address, AptosErrorCode, AsConverter, LedgerInfo, MoveModuleBytecode,
    MoveResource, MoveStructTag, TransactionId, U64,
};
use aptos_types::access_path::AccessPath;
use aptos_types::account_config::AccountResource;
use aptos_types::account_state::AccountState;
use aptos_types::event::EventHandle;
use aptos_types::event::EventKey;
use aptos_types::state_store::state_key::StateKey;
use move_deps::move_core_types::value::MoveValue;
use move_deps::move_core_types::{
    identifier::Identifier,
    language_storage::{ResourceKey, StructTag},
    move_resource::MoveStructType,
};
use poem_openapi::param::Query;
use poem_openapi::{param::Path, OpenApi};
use std::collections::BTreeMap;
use std::convert::TryInto;
use std::sync::Arc;

pub struct AccountsApi {
    pub context: Arc<Context>,
}

#[OpenApi]
impl AccountsApi {
    /// Get account
    ///
    /// Return high level information about an account such as its sequence number.
    #[oai(
        path = "/accounts/:address",
        method = "get",
        operation_id = "get_account",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<AccountData> {
        fail_point_poem("endpoint_get_account")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.account(&accept_type)
    }

    /// Get account resources
    ///
    /// This endpoint returns all account resources at a given address at a
    /// specific ledger version (AKA transaction version). If the ledger
    /// version is not specified in the request, the latest ledger version is used.
    ///
    /// The Aptos nodes prune account state history, via a configurable time window (link).
    /// If the requested data has been pruned, the server responds with a 404.
    #[oai(
        path = "/accounts/:address/resources",
        method = "get",
        operation_id = "get_account_resources",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account_resources(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<Vec<MoveResource>> {
        fail_point_poem("endpoint_get_account_resources")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.resources(&accept_type)
    }

    /// Get account modules
    ///
    /// This endpoint returns all account modules at a given address at a
    /// specific ledger version (AKA transaction version). If the ledger
    /// version is not specified in the request, the latest ledger version is used.
    ///
    /// The Aptos nodes prune account state history, via a configurable time window (link).
    /// If the requested data has been pruned, the server responds with a 404.
    #[oai(
        path = "/accounts/:address/modules",
        method = "get",
        operation_id = "get_account_modules",
        tag = "ApiTags::Accounts"
    )]
    async fn get_account_modules(
        &self,
        accept_type: AcceptType,
        address: Path<Address>,
        ledger_version: Query<Option<U64>>,
    ) -> BasicResultWith404<Vec<MoveModuleBytecode>> {
        fail_point_poem("endpoint_get_account_modules")?;
        let account = Account::new(self.context.clone(), address.0, ledger_version.0)?;
        account.modules(&accept_type)
    }
}

pub struct Account {
    context: Arc<Context>,
    address: Address,
    ledger_version: u64,
    latest_ledger_info: LedgerInfo,
}

impl Account {
    pub fn new(
        context: Arc<Context>,
        address: Address,
        requested_ledger_version: Option<U64>,
    ) -> Result<Self, BasicErrorWith404> {
        let latest_ledger_info = context.get_latest_ledger_info()?;
        let ledger_version: u64 = requested_ledger_version
            .map(|v| v.0)
            .unwrap_or_else(|| latest_ledger_info.version());

        if ledger_version > latest_ledger_info.version() {
            return Err(build_not_found(
                "ledger",
                TransactionId::Version(U64::from(ledger_version)),
                latest_ledger_info.version(),
            ));
        }

        Ok(Self {
            context,
            address,
            ledger_version,
            latest_ledger_info,
        })
    }

    // These functions map directly to endpoint functions.

    pub fn account(self, accept_type: &AcceptType) -> BasicResultWith404<AccountData> {
        let state_key = StateKey::AccessPath(AccessPath::resource_access_path(ResourceKey::new(
            self.address.into(),
            AccountResource::struct_tag(),
        )));

        let state_value = self
            .context
            .get_state_value_poem(&state_key, self.ledger_version)?;

        let state_value = match state_value {
            Some(state_value) => state_value,
            None => return Err(self.resource_not_found(&AccountResource::struct_tag())),
        };

        let account_resource: AccountResource = bcs::from_bytes(&state_value)
            .context("Internal error deserializing response from DB")
            .map_err(BasicErrorWith404::internal)?;
        let account_data: AccountData = account_resource.into();

        match accept_type {
            AcceptType::Json => BasicResponse::try_from_json((
                account_data,
                &self.latest_ledger_info,
                BasicResponseStatus::Ok,
            )),
            AcceptType::Bcs => BasicResponse::try_from_encoded((
                state_value,
                &self.latest_ledger_info,
                BasicResponseStatus::Ok,
            )),
        }
    }

    pub fn resources(self, accept_type: &AcceptType) -> BasicResultWith404<Vec<MoveResource>> {
        let account_state = self.account_state()?;
        let resources = account_state.get_resources();

        match accept_type {
            AcceptType::Json => {
                let move_resolver = self.context.move_resolver_poem()?;
                let converted_resources = move_resolver
                    .as_converter(self.context.db.clone())
                    .try_into_resources(resources)
                    .context("Failed to build move resource response from data in DB")
                    .map_err(BasicErrorWith404::internal)
                    .map_err(|e| e.error_code(AptosErrorCode::InvalidBcsInStorageError))?;

                BasicResponse::try_from_json((
                    converted_resources,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
            AcceptType::Bcs => {
                let resources: BTreeMap<StructTag, Vec<u8>> = resources
                    .map(|(key, value)| (key, value.to_vec()))
                    .collect();
                BasicResponse::try_from_bcs((
                    resources,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
        }
    }

    pub fn modules(self, accept_type: &AcceptType) -> BasicResultWith404<Vec<MoveModuleBytecode>> {
        let modules = self.account_state()?.into_modules();
        match accept_type {
            AcceptType::Json => {
                let mut converted_modules = Vec::new();
                for module in modules {
                    converted_modules.push(
                        MoveModuleBytecode::new(module)
                            .try_parse_abi()
                            .context("Failed to parse move module ABI")
                            .map_err(BasicErrorWith404::internal)
                            .map_err(|e| e.error_code(AptosErrorCode::InvalidBcsInStorageError))?,
                    );
                }
                BasicResponse::try_from_json((
                    converted_modules,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
            AcceptType::Bcs => {
                let modules: Vec<_> = modules.collect();
                BasicResponse::try_from_bcs((
                    modules,
                    &self.latest_ledger_info,
                    BasicResponseStatus::Ok,
                ))
            }
        }
    }

    // Helpers for processing account state.

    fn account_state(&self) -> Result<AccountState, BasicErrorWith404> {
        let state = self
            .context
            .get_account_state(self.address.into(), self.ledger_version)
            .map_err(BasicErrorWith404::internal)
            .map_err(|e| e.error_code(AptosErrorCode::ReadFromStorageError))?
            .ok_or_else(|| self.account_not_found())?;

        Ok(state)
    }

    // Helpers for building errors.

    fn account_not_found(&self) -> BasicErrorWith404 {
        build_not_found(
            "account",
            format!(
                "address({}) and ledger version({})",
                self.address, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    fn resource_not_found(&self, struct_tag: &StructTag) -> BasicErrorWith404 {
        build_not_found(
            "resource",
            format!(
                "address({}), struct tag({}) and ledger version({})",
                self.address, struct_tag, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    fn field_not_found(
        &self,
        struct_tag: &StructTag,
        field_name: &Identifier,
    ) -> BasicErrorWith404 {
        build_not_found(
            "resource",
            format!(
                "address({}), struct tag({}), field name({}) and ledger version({})",
                self.address, struct_tag, field_name, self.ledger_version
            ),
            self.latest_ledger_info.version(),
        )
    }

    // Events specific stuff.

    pub fn find_event_key(
        &self,
        event_handle: MoveStructTag,
        field_name: Identifier,
    ) -> Result<EventKey, BasicErrorWith404> {
        let struct_tag: StructTag = event_handle
            .try_into()
            .context("Given event handle was invalid")
            .map_err(BasicErrorWith404::bad_request)?;

        let resource = self.find_resource(&struct_tag)?;

        let (_id, value) = resource
            .into_iter()
            .find(|(id, _)| id == &field_name)
            .ok_or_else(|| self.field_not_found(&struct_tag, &field_name))?;

        // Serialization should not fail, otherwise it's internal bug
        let event_handle_bytes = bcs::to_bytes(&value)
            .context("Failed to serialize event handle, this is an internal bug")
            .map_err(BasicErrorWith404::internal)?;
        // Deserialization may fail because the bytes are not EventHandle struct type.
        let event_handle: EventHandle = bcs::from_bytes(&event_handle_bytes)
            .context(format!(
                "Deserialization error, field({}) type is not EventHandle struct",
                field_name
            ))
            .map_err(BasicErrorWith404::bad_request)?;
        Ok(*event_handle.key())
    }

    fn find_resource(
        &self,
        struct_tag: &StructTag,
    ) -> Result<Vec<(Identifier, MoveValue)>, BasicErrorWith404> {
        let account_state = self.account_state()?;
        let (typ, data) = account_state
            .get_resources()
            .find(|(tag, _data)| tag == struct_tag)
            .ok_or_else(|| self.resource_not_found(struct_tag))?;
        let move_resolver = self.context.move_resolver_poem()?;
        move_resolver
            .as_converter(self.context.db.clone())
            .move_struct_fields(&typ, data)
            .context("Failed to convert move structs")
            .map_err(BasicErrorWith404::internal)
    }
}
<|endoftext|>


<commit_before>extern crate staticdir;
extern crate iron;
extern crate hyper;

use iron::prelude::*;

use hyper::Client;
use hyper::status;
use hyper::header::{ ContentType };
use hyper::mime::{ Mime, TopLevel, SubLevel };

use std::io::Read;
use staticdir::{ StaticDir, AsJson };

use std::ops::Deref;

#[test]
fn handler_provides_json() {
    let mut server = Iron::new(StaticDir::new("tests/mount", AsJson)).http("localhost:3000").unwrap();

    let client = Client::new();
    let mut res = client.get("http://localhost:3000").send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    server.close().unwrap();

    assert_eq!(res.status, status::StatusCode::Ok);
    let &Mime(ref top, ref sub, _) = res.headers.get::<ContentType>().unwrap().deref();
    assert_eq!((top, sub), (&TopLevel::Application, &SubLevel::Json));
    assert_eq!(body,  "[{\"is_file\":true,\"is_dir\":false,\"is_symlink\":false,\"path\":\"tests/mount/1.txt\",\"file_name\":\"1.txt\"}]");
}
<commit_msg>passing tests<commit_after>extern crate staticdir;
extern crate iron;
extern crate hyper;

use iron::prelude::*;

use hyper::Client;
use hyper::status;
use hyper::header::{ ContentType };
use hyper::mime::{ Mime, TopLevel, SubLevel };

use std::io::Read;
use staticdir::{ StaticDir, AsJson };

use std::ops::Deref;

#[test]
fn handler_provides_json() {
    let mut server = Iron::new(StaticDir::new("tests/mount", AsJson)).http("localhost:3000").unwrap();

    let client = Client::new();
    let mut res = client.get("http://localhost:3000").send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    server.close().unwrap();

    assert_eq!(res.status, status::StatusCode::Ok);
    let &Mime(ref top, ref sub, _) = res.headers.get::<ContentType>().unwrap().deref();
    assert_eq!((top, sub), (&TopLevel::Application, &SubLevel::Json));
    assert_eq!(body,  "[{\"is_file\":true,\"is_dir\":false,\"is_symlink\":false,\"path\":\"tests/mount/1.txt\",\"file_name\":\"1.txt\"},{\"is_file\":false,\"is_dir\":true,\"is_symlink\":false,\"path\":\"tests/mount/nested\",\"file_name\":\"nested\"}]");
}
<|endoftext|>


<commit_before>extern crate presort;

use presort::PresortedVec;
use std::rc::Rc;
use std::cell::RefCell;

struct TreeNode<T> {
    //whether this node's data has changed
    dirty_val: bool,
    //whether this node or decendents have changed
    needs_update: bool,
    //the old size of the tree
    old_size: usize,
    //parent and index in parent's child vec
    parent: Option<(Tree<T>, usize)>,
    //this node's data
    data: T,
    children: Vec<Tree<T>>,
}

type Tree<T> = Rc<RefCell<TreeNode<T>>>;

trait IncTree<T: PartialEq + Clone> {
    fn new_node(data: T) -> Tree<T>;
    fn flag_as_new(&self);
    fn flag_as_updated(&self);
    fn get_data(&self) -> T;
    fn set_data(&self, data: T);
    fn get_child(&self, child_num: usize) -> Tree<T>;
    fn set_child(&self, child_num: usize, child: Tree<T>);
    fn push_child(&self, child: Tree<T>);
    fn pop_child(&self) -> Option<Tree<T>>;
}

impl<T: PartialEq + Clone> IncTree<T> for Tree<T> {
    fn new_node(data: T) -> Tree<T>{
        Rc::new(RefCell::new(TreeNode {
            dirty_val: true,
            needs_update: true,
            old_size: 0,
            parent: None,
            data: data,
            children: vec![]
        }))
    }

    //sets dirty flags on all children and parents
    fn flag_as_new(&self) {
        let mut tree = self.borrow_mut();
        tree.dirty_val = true;
        tree.needs_update = true;
        for kid in &tree.children {
            kid.flag_as_new();
        }
    }

    //sets dirty flags on self and parents
    fn flag_as_updated(&self){
            let mut node = self.borrow_mut();
            node.needs_update = true;
            if let Some((ref parent, _)) = node.parent {
                parent.flag_as_updated();
            }
    }

    fn get_data(&self) -> T {
        self.borrow().data.clone()
    }

    fn set_data(&self, data: T) {
        {
            let mut tree = self.borrow_mut();
            if tree.data == data {return}
            tree.data = data;
            tree.dirty_val = true;
        }
        self.flag_as_updated();
    }

    fn get_child(&self, child_num: usize) -> Tree<T> {
        self.borrow().children[child_num].clone() //Rc clone
    }

    fn set_child(&self, child_num: usize, child: Tree<T>) {
        child.flag_as_new();
        child.borrow_mut().parent = Some((self.clone(), child_num)); //Rc clone
        child.flag_as_updated();
        self.borrow_mut().children[child_num] = child;
    }

    fn push_child(&self, child: Tree<T>) {
        child.flag_as_new();
        child.borrow_mut().parent = Some((self.clone(), self.borrow().children.len())); //Rc clone
        child.flag_as_updated();
        self.borrow_mut().children.push(child);
    }

    fn pop_child(&self) -> Option<Tree<T>> {
        let child = self.borrow_mut().children.pop();
        if let Some(ref child) = child {
            self.borrow_mut().dirty_val = true;
            self.flag_as_updated();
            child.borrow_mut().parent = None;
        }
        child
    }
}

fn dump<T: Ord+Clone>(tree: &Tree<T>, vec: &mut PresortedVec<T>) -> usize {
    let mut tree = tree.borrow_mut();
    let mut size = 1;
    vec.push(tree.data.clone());
    tree.dirty_val = false;
    for kid in &tree.children { size += dump(&kid, vec); }
    tree.needs_update = false;
    tree.old_size = size;
    size
}

fn update<T: Ord+Clone>(tree: &Tree<T>, start_index: usize, vec: &mut PresortedVec<T>) -> usize {
    let mut tree = tree.borrow_mut();
    let mut size = tree.old_size;
    if tree.needs_update || vec.len() < start_index + size {
        if vec.len() <= start_index {
            vec.push(tree.data.clone());
        } else if tree.dirty_val {
            vec.set(start_index, tree.data.clone());
        }
        tree.dirty_val = false;
        size = 1;
        for kid in &tree.children { size += update(&kid, start_index + size, vec); }
        tree.needs_update = false;
        if tree.old_size != size {
            vec.truncate(start_index + size);
            tree.old_size = size;
        }
    }
    size
}

#[test]
fn test_tree() {
    let main_tree = Tree::new_node(37);
    let mut vec = PresortedVec::new();
    dump(&main_tree, &mut vec);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&37]);
}

#[test]
fn test_update() {
    println!("start first dump");
    let main_tree = Tree::new_node(37);
    main_tree.push_child(Tree::new_node(42));
    main_tree.push_child(Tree::new_node(20));
    main_tree.push_child(Tree::new_node(63));
    let mut vec = PresortedVec::new();
    dump(&main_tree, &mut vec);
    println!("finished first dump");
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&20,&37,&42,&63]);

    println!("start first update");
    main_tree.get_child(1).set_data(25);
    update(&main_tree, 0, &mut vec);
    println!("finished first update");
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&25,&37,&42,&63]);

    println!("start add branch");
    let branch = main_tree.get_child(2);
    branch.push_child(Tree::new_node(47));
    branch.push_child(Tree::new_node(53));
    branch.push_child(Tree::new_node(61));
    branch.push_child(Tree::new_node(57));
    update(&main_tree, 0, &mut vec);
    println!("finished add branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&25,&37,&42,&47,&53,&57,&61,&63]
    );

    println!("start update branch");
    branch.get_child(2).set_data(77);
    update(&main_tree, 0, &mut vec);
    println!("finished update branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&25,&37,&42,&47,&53,&57,&63,&77]
    );

    println!("start early insertion");
    let branch = main_tree.get_child(1);
    branch.push_child(Tree::new_node(1));
    update(&main_tree, 0, &mut vec);
    println!("finished early insertion");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77]
    );

    println!("start deep add");
    let branch = main_tree.get_child(2).get_child(2);
    let new_branch = Tree::new_node(100);
    new_branch.push_child(Tree::new_node(101));
    branch.push_child(new_branch);
    update(&main_tree, 0, &mut vec);
    println!("finished deep add");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77,&100,&101]
    );

    println!("start deep edit");
    let branch = branch.get_child(0).get_child(0);
    branch.set_data(105);
    update(&main_tree, 0, &mut vec);
    println!("finished deep edit");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77,&100,&105]
    );

    println!("start pop branch");
    let branch = main_tree.get_child(2).get_child(2);
    branch.pop_child();
    update(&main_tree, 0, &mut vec);
    println!("finished pop branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77]
    );

}
<commit_msg>Fixed indentation.<commit_after>extern crate presort;

use presort::PresortedVec;
use std::rc::Rc;
use std::cell::RefCell;

struct TreeNode<T> {
    //whether this node's data has changed
    dirty_val: bool,
    //whether this node or decendents have changed
    needs_update: bool,
    //the old size of the tree
    old_size: usize,
    //parent and index in parent's child vec
    parent: Option<(Tree<T>, usize)>,
    //this node's data
    data: T,
    children: Vec<Tree<T>>,
}

type Tree<T> = Rc<RefCell<TreeNode<T>>>;

trait IncTree<T: PartialEq + Clone> {
    fn new_node(data: T) -> Tree<T>;
    fn flag_as_new(&self);
    fn flag_as_updated(&self);
    fn get_data(&self) -> T;
    fn set_data(&self, data: T);
    fn get_child(&self, child_num: usize) -> Tree<T>;
    fn set_child(&self, child_num: usize, child: Tree<T>);
    fn push_child(&self, child: Tree<T>);
    fn pop_child(&self) -> Option<Tree<T>>;
}

impl<T: PartialEq + Clone> IncTree<T> for Tree<T> {
    fn new_node(data: T) -> Tree<T>{
        Rc::new(RefCell::new(TreeNode {
            dirty_val: true,
            needs_update: true,
            old_size: 0,
            parent: None,
            data: data,
            children: vec![]
        }))
    }

    //sets dirty flags on all children and parents
    fn flag_as_new(&self) {
        let mut tree = self.borrow_mut();
        tree.dirty_val = true;
        tree.needs_update = true;
        for kid in &tree.children {
            kid.flag_as_new();
        }
    }

    //sets dirty flags on self and parents
    fn flag_as_updated(&self){
        let mut node = self.borrow_mut();
        node.needs_update = true;
        if let Some((ref parent, _)) = node.parent {
            parent.flag_as_updated();
        }
    }

    fn get_data(&self) -> T {
        self.borrow().data.clone()
    }

    fn set_data(&self, data: T) {
        {
            let mut tree = self.borrow_mut();
            if tree.data == data {return}
            tree.data = data;
            tree.dirty_val = true;
        }
        self.flag_as_updated();
    }

    fn get_child(&self, child_num: usize) -> Tree<T> {
        self.borrow().children[child_num].clone() //Rc clone
    }

    fn set_child(&self, child_num: usize, child: Tree<T>) {
        child.flag_as_new();
        child.borrow_mut().parent = Some((self.clone(), child_num)); //Rc clone
        child.flag_as_updated();
        self.borrow_mut().children[child_num] = child;
    }

    fn push_child(&self, child: Tree<T>) {
        child.flag_as_new();
        child.borrow_mut().parent = Some((self.clone(), self.borrow().children.len())); //Rc clone
        child.flag_as_updated();
        self.borrow_mut().children.push(child);
    }

    fn pop_child(&self) -> Option<Tree<T>> {
        let child = self.borrow_mut().children.pop();
        if let Some(ref child) = child {
            self.borrow_mut().dirty_val = true;
            self.flag_as_updated();
            child.borrow_mut().parent = None;
        }
        child
    }
}

fn dump<T: Ord+Clone>(tree: &Tree<T>, vec: &mut PresortedVec<T>) -> usize {
    let mut tree = tree.borrow_mut();
    let mut size = 1;
    vec.push(tree.data.clone());
    tree.dirty_val = false;
    for kid in &tree.children { size += dump(&kid, vec); }
    tree.needs_update = false;
    tree.old_size = size;
    size
}

fn update<T: Ord+Clone>(tree: &Tree<T>, start_index: usize, vec: &mut PresortedVec<T>) -> usize {
    let mut tree = tree.borrow_mut();
    let mut size = tree.old_size;
    if tree.needs_update || vec.len() < start_index + size {
        if vec.len() <= start_index {
            vec.push(tree.data.clone());
        } else if tree.dirty_val {
            vec.set(start_index, tree.data.clone());
        }
        tree.dirty_val = false;
        size = 1;
        for kid in &tree.children { size += update(&kid, start_index + size, vec); }
        tree.needs_update = false;
        if tree.old_size != size {
            vec.truncate(start_index + size);
            tree.old_size = size;
        }
    }
    size
}

#[test]
fn test_tree() {
    let main_tree = Tree::new_node(37);
    let mut vec = PresortedVec::new();
    dump(&main_tree, &mut vec);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&37]);
}

#[test]
fn test_update() {
    println!("start first dump");
    let main_tree = Tree::new_node(37);
    main_tree.push_child(Tree::new_node(42));
    main_tree.push_child(Tree::new_node(20));
    main_tree.push_child(Tree::new_node(63));
    let mut vec = PresortedVec::new();
    dump(&main_tree, &mut vec);
    println!("finished first dump");
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&20,&37,&42,&63]);

    println!("start first update");
    main_tree.get_child(1).set_data(25);
    update(&main_tree, 0, &mut vec);
    println!("finished first update");
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&25,&37,&42,&63]);

    println!("start add branch");
    let branch = main_tree.get_child(2);
    branch.push_child(Tree::new_node(47));
    branch.push_child(Tree::new_node(53));
    branch.push_child(Tree::new_node(61));
    branch.push_child(Tree::new_node(57));
    update(&main_tree, 0, &mut vec);
    println!("finished add branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&25,&37,&42,&47,&53,&57,&61,&63]
    );

    println!("start update branch");
    branch.get_child(2).set_data(77);
    update(&main_tree, 0, &mut vec);
    println!("finished update branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&25,&37,&42,&47,&53,&57,&63,&77]
    );

    println!("start early insertion");
    let branch = main_tree.get_child(1);
    branch.push_child(Tree::new_node(1));
    update(&main_tree, 0, &mut vec);
    println!("finished early insertion");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77]
    );

    println!("start deep add");
    let branch = main_tree.get_child(2).get_child(2);
    let new_branch = Tree::new_node(100);
    new_branch.push_child(Tree::new_node(101));
    branch.push_child(new_branch);
    update(&main_tree, 0, &mut vec);
    println!("finished deep add");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77,&100,&101]
    );

    println!("start deep edit");
    let branch = branch.get_child(0).get_child(0);
    branch.set_data(105);
    update(&main_tree, 0, &mut vec);
    println!("finished deep edit");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77,&100,&105]
    );

    println!("start pop branch");
    let branch = main_tree.get_child(2).get_child(2);
    branch.pop_child();
    update(&main_tree, 0, &mut vec);
    println!("finished pop branch");
    assert_eq!(
        vec.sorted_iter().collect::<Vec<&usize>>(),
        vec![&1,&25,&37,&42,&47,&53,&57,&63,&77]
    );

}
<|endoftext|>