<commit_before>//! Sanity checking performed by rustbuild before actually executing anything.
//!
//! This module contains the implementation of ensuring that the build
//! environment looks reasonable before progressing. This will verify that
//! various programs like git and python exist, along with ensuring that all C
//! compilers for cross-compiling are found.
//!
//! In theory if we get past this phase it's a bug if a build fails, but in
//! practice that's likely not true!

use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::PathBuf;
use std::process::Command;

use build_helper::{output, t};

use crate::cache::INTERNER;
use crate::config::Target;
use crate::Build;

pub struct Finder {
    cache: HashMap<OsString, Option<PathBuf>>,
    path: OsString,
}

impl Finder {
    pub fn new() -> Self {
        Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
    }

    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
        let cmd: OsString = cmd.into();
        let path = &self.path;
        self.cache
            .entry(cmd.clone())
            .or_insert_with(|| {
                for path in env::split_paths(path) {
                    let target = path.join(&cmd);
                    let mut cmd_exe = cmd.clone();
                    cmd_exe.push(".exe");

                    if target.is_file()                   // some/path/git
                    || path.join(&cmd_exe).exists()   // some/path/git.exe
                    || target.join(&cmd_exe).exists()
                    // some/path/git/git.exe
                    {
                        return Some(target);
                    }
                }
                None
            })
            .clone()
    }

    pub fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
        self.maybe_have(&cmd).unwrap_or_else(|| {
            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
        })
    }
}

pub fn check(build: &mut Build) {
    let path = env::var_os("PATH").unwrap_or_default();
    // On Windows, quotes are invalid characters for filename paths, and if
    // one is present as part of the PATH then that can lead to the system
    // being unable to identify the files properly. See
    // https://github.com/rust-lang/rust/issues/34959 for more details.
    if cfg!(windows) && path.to_string_lossy().contains('\"') {
        panic!("PATH contains invalid character '\"'");
    }

    let mut cmd_finder = Finder::new();
    // If we've got a git directory we're gonna need git to update
    // submodules and learn about various other aspects.
    if build.rust_info.is_git() {
        cmd_finder.must_have("git");
    }

    // We need cmake, but only if we're actually building LLVM or sanitizers.
    let building_llvm = build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
        && build
            .hosts
            .iter()
            .map(|host| {
                build
                    .config
                    .target_config
                    .get(host)
                    .map(|config| config.llvm_config.is_none())
                    .unwrap_or(true)
            })
            .any(|build_llvm_ourselves| build_llvm_ourselves);
    if building_llvm || build.config.any_sanitizers_enabled() {
        cmd_finder.must_have("cmake");
    }

    build.config.python = build
        .config
        .python
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
        .or_else(|| Some(cmd_finder.must_have("python")));

    build.config.nodejs = build
        .config
        .nodejs
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("node"))
        .or_else(|| cmd_finder.maybe_have("nodejs"));

    build.config.npm = build
        .config
        .npm
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("npm"));

    build.config.gdb = build
        .config
        .gdb
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("gdb"));

    // We're gonna build some custom C code here and there, host triples
    // also build some C++ shims for LLVM so we need a C++ compiler.
    for target in &build.targets {
        // On emscripten we don't actually need the C compiler to just
        // build the target artifacts, only for testing. For the sake
        // of easier bot configuration, just skip detection.
        if target.contains("emscripten") {
            continue;
        }

        // We don't use a C compiler on wasm32
        if target.contains("wasm32") {
            continue;
        }

        if !build.config.dry_run {
            cmd_finder.must_have(build.cc(*target));
            if let Some(ar) = build.ar(*target) {
                cmd_finder.must_have(ar);
            }
        }
    }

    for host in &build.hosts {
        if !build.config.dry_run {
            cmd_finder.must_have(build.cxx(*host).unwrap());
        }
    }

    if build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
        // Externally configured LLVM requires FileCheck to exist
        let filecheck = build.llvm_filecheck(build.build);
        if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
            panic!("FileCheck executable {:?} does not exist", filecheck);
        }
    }

    for target in &build.targets {
        // Can't compile for iOS unless we're on macOS
        if target.contains("apple-ios") && !build.build.contains("apple-darwin") {
            panic!("the iOS target is only supported on macOS");
        }

        build
            .config
            .target_config
            .entry(*target)
            .or_insert_with(|| Target::from_triple(&target.triple));

        if target.contains("-none-") || target.contains("nvptx") {
            if build.no_std(*target) == Some(false) {
                panic!("All the *-none-* and nvptx* targets are no-std targets")
            }
        }

        // Make sure musl-root is valid
        if target.contains("musl") {
            // If this is a native target (host is also musl) and no musl-root is given,
            // fall back to the system toolchain in /usr before giving up
            if build.musl_root(*target).is_none() && build.config.build == *target {
                let target = build.config.target_config.entry(*target).or_default();
                target.musl_root = Some("/usr".into());
            }
            match build.musl_libdir(*target) {
                Some(libdir) => {
                    if fs::metadata(libdir.join("libc.a")).is_err() {
                        panic!("couldn't find libc.a in musl libdir: {}", libdir.display());
                    }
                }
                None => panic!(
                    "when targeting MUSL either the rust.musl-root \
                            option or the target.$TARGET.musl-root option must \
                            be specified in config.toml"
                ),
            }
        }

        if target.contains("msvc") {
            // There are three builds of cmake on windows: MSVC, MinGW, and
            // Cygwin. The Cygwin build does not have generators for Visual
            // Studio, so detect that here and error.
            let out = output(Command::new("cmake").arg("--help"));
            if !out.contains("Visual Studio") {
                panic!(
                    "
cmake does not support Visual Studio generators.

This is likely due to it being an msys/cygwin build of cmake,
rather than the required windows version, built using MinGW
or Visual Studio.

If you are building under msys2 try installing the mingw-w64-x86_64-cmake
package instead of cmake:

$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
"
                );
            }
        }
    }

    if let Some(ref s) = build.config.ccache {
        cmd_finder.must_have(s);
    }

    if build.config.channel == "stable" {
        let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
        if stage0.contains("\ndev:") {
            panic!(
                "bootstrapping from a dev compiler in a stable release, but \
                    should only be bootstrapping from a released compiler!"
            );
        }
    }
}
<commit_msg>Rollup merge of #85423 - jyn514:cmake, r=Mark-Simulacrum<commit_after>//! Sanity checking performed by rustbuild before actually executing anything.
//!
//! This module contains the implementation of ensuring that the build
//! environment looks reasonable before progressing. This will verify that
//! various programs like git and python exist, along with ensuring that all C
//! compilers for cross-compiling are found.
//!
//! In theory if we get past this phase it's a bug if a build fails, but in
//! practice that's likely not true!

use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::PathBuf;
use std::process::Command;

use build_helper::{output, t};

use crate::cache::INTERNER;
use crate::config::Target;
use crate::Build;

pub struct Finder {
    cache: HashMap<OsString, Option<PathBuf>>,
    path: OsString,
}

impl Finder {
    pub fn new() -> Self {
        Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
    }

    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
        let cmd: OsString = cmd.into();
        let path = &self.path;
        self.cache
            .entry(cmd.clone())
            .or_insert_with(|| {
                for path in env::split_paths(path) {
                    let target = path.join(&cmd);
                    let mut cmd_exe = cmd.clone();
                    cmd_exe.push(".exe");

                    if target.is_file()                   // some/path/git
                    || path.join(&cmd_exe).exists()   // some/path/git.exe
                    || target.join(&cmd_exe).exists()
                    // some/path/git/git.exe
                    {
                        return Some(target);
                    }
                }
                None
            })
            .clone()
    }

    pub fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
        self.maybe_have(&cmd).unwrap_or_else(|| {
            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
        })
    }
}

pub fn check(build: &mut Build) {
    let path = env::var_os("PATH").unwrap_or_default();
    // On Windows, quotes are invalid characters for filename paths, and if
    // one is present as part of the PATH then that can lead to the system
    // being unable to identify the files properly. See
    // https://github.com/rust-lang/rust/issues/34959 for more details.
    if cfg!(windows) && path.to_string_lossy().contains('\"') {
        panic!("PATH contains invalid character '\"'");
    }

    let mut cmd_finder = Finder::new();
    // If we've got a git directory we're gonna need git to update
    // submodules and learn about various other aspects.
    if build.rust_info.is_git() {
        cmd_finder.must_have("git");
    }

    // We need cmake, but only if we're actually building LLVM or sanitizers.
    let building_llvm = build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
        && build
            .hosts
            .iter()
            .map(|host| {
                build
                    .config
                    .target_config
                    .get(host)
                    .map(|config| config.llvm_config.is_none())
                    .unwrap_or(true)
            })
            .any(|build_llvm_ourselves| build_llvm_ourselves);
    let need_cmake = building_llvm || build.config.any_sanitizers_enabled();
    if need_cmake {
        cmd_finder.must_have("cmake");
    }

    build.config.python = build
        .config
        .python
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
        .or_else(|| Some(cmd_finder.must_have("python")));

    build.config.nodejs = build
        .config
        .nodejs
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("node"))
        .or_else(|| cmd_finder.maybe_have("nodejs"));

    build.config.npm = build
        .config
        .npm
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("npm"));

    build.config.gdb = build
        .config
        .gdb
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("gdb"));

    // We're gonna build some custom C code here and there, host triples
    // also build some C++ shims for LLVM so we need a C++ compiler.
    for target in &build.targets {
        // On emscripten we don't actually need the C compiler to just
        // build the target artifacts, only for testing. For the sake
        // of easier bot configuration, just skip detection.
        if target.contains("emscripten") {
            continue;
        }

        // We don't use a C compiler on wasm32
        if target.contains("wasm32") {
            continue;
        }

        if !build.config.dry_run {
            cmd_finder.must_have(build.cc(*target));
            if let Some(ar) = build.ar(*target) {
                cmd_finder.must_have(ar);
            }
        }
    }

    for host in &build.hosts {
        if !build.config.dry_run {
            cmd_finder.must_have(build.cxx(*host).unwrap());
        }
    }

    if build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
        // Externally configured LLVM requires FileCheck to exist
        let filecheck = build.llvm_filecheck(build.build);
        if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
            panic!("FileCheck executable {:?} does not exist", filecheck);
        }
    }

    for target in &build.targets {
        // Can't compile for iOS unless we're on macOS
        if target.contains("apple-ios") && !build.build.contains("apple-darwin") {
            panic!("the iOS target is only supported on macOS");
        }

        build
            .config
            .target_config
            .entry(*target)
            .or_insert_with(|| Target::from_triple(&target.triple));

        if target.contains("-none-") || target.contains("nvptx") {
            if build.no_std(*target) == Some(false) {
                panic!("All the *-none-* and nvptx* targets are no-std targets")
            }
        }

        // Make sure musl-root is valid
        if target.contains("musl") {
            // If this is a native target (host is also musl) and no musl-root is given,
            // fall back to the system toolchain in /usr before giving up
            if build.musl_root(*target).is_none() && build.config.build == *target {
                let target = build.config.target_config.entry(*target).or_default();
                target.musl_root = Some("/usr".into());
            }
            match build.musl_libdir(*target) {
                Some(libdir) => {
                    if fs::metadata(libdir.join("libc.a")).is_err() {
                        panic!("couldn't find libc.a in musl libdir: {}", libdir.display());
                    }
                }
                None => panic!(
                    "when targeting MUSL either the rust.musl-root \
                            option or the target.$TARGET.musl-root option must \
                            be specified in config.toml"
                ),
            }
        }

        if need_cmake && target.contains("msvc") {
            // There are three builds of cmake on windows: MSVC, MinGW, and
            // Cygwin. The Cygwin build does not have generators for Visual
            // Studio, so detect that here and error.
            let out = output(Command::new("cmake").arg("--help"));
            if !out.contains("Visual Studio") {
                panic!(
                    "
cmake does not support Visual Studio generators.

This is likely due to it being an msys/cygwin build of cmake,
rather than the required windows version, built using MinGW
or Visual Studio.

If you are building under msys2 try installing the mingw-w64-x86_64-cmake
package instead of cmake:

$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
"
                );
            }
        }
    }

    if let Some(ref s) = build.config.ccache {
        cmd_finder.must_have(s);
    }

    if build.config.channel == "stable" {
        let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
        if stage0.contains("\ndev:") {
            panic!(
                "bootstrapping from a dev compiler in a stable release, but \
                    should only be bootstrapping from a released compiler!"
            );
        }
    }
}
<|endoftext|>


<commit_before>use native;
use rustrt::rtio;
use rustrt::rtio::RtioFileStream;
use std::cell::Cell;
use std::os;

use array::*;
use chunk::{
    BiomeId,
    BlockState,
    Chunk,
    ChunkColumn,
    EMPTY_CHUNK,
    LightLevel,
    SIZE
};
use minecraft::nbt::Nbt;

pub struct Region {
    mmap: os::MemoryMap
}

impl Region {
    pub fn open(filename: &Path) -> Region {
        let mut file = native::io::file::open(
                &filename.as_str().unwrap().to_c_str(),
                rtio::Open,
                rtio::Read
            ).ok().unwrap();
        let min_len = file.fstat().ok().unwrap().size as uint;
        let options = [
                os::MapFd(file.fd()),
                os::MapReadable
            ];

        Region {
            mmap: os::MemoryMap::new(min_len, options).unwrap()
        }
    }

    fn as_slice<'a>(&'a self) -> &'a [u8] {
        use std::mem;
        use std::raw::Slice;
        let slice = Slice {
                data: self.mmap.data() as *const u8,
                len: self.mmap.len()
            };

        unsafe { mem::transmute(slice) }
    }

    pub fn get_chunk_column(&self, x: u8, z: u8) -> Option<ChunkColumn> {
        let locations = self.as_slice().slice_to(4096);
        let i = 4 * ((x % 32) as uint + (z % 32) as uint * 32);
        let start = (locations[i] as uint << 16)
                  | (locations[i + 1] as uint << 8)
                  | locations[i + 2] as uint;
        let num = locations[i + 3] as uint;
        if start == 0 || num == 0 { return None; }

        let sectors = self.as_slice().slice(start * 4096, (start + num) * 4096);
        let len = (sectors[0] as uint << 24)
                | (sectors[1] as uint << 16)
                | (sectors[2] as uint << 8)
                | sectors[3] as uint;
        let nbt = match sectors[4] {
            1 => Nbt::from_gzip(sectors.slice(5, 4 + len)),
            2 => Nbt::from_zlib(sectors.slice(5, 4 + len)),
            c => panic!("unknown region chunk compression method {}", c)
        };

        let mut c = nbt.unwrap().into_compound().unwrap();
        let mut level = c.pop_equiv("Level").unwrap().into_compound().unwrap();
        let mut chunks = Vec::new();
        for chunk in level.pop_equiv("Sections")
            .unwrap().into_compound_list().unwrap().into_iter() {

            let y = chunk.find_equiv("Y")
                .unwrap().as_byte().unwrap();
            let blocks = chunk.find_equiv("Blocks")
                .unwrap().as_bytearray().unwrap();
            let blocks_top = chunk.find_equiv("Add")
                .and_then(|x| x.as_bytearray());
            let blocks_data = chunk.find_equiv("Data")
                .unwrap().as_bytearray().unwrap();
            let block_light = chunk.find_equiv("BlockLight")
                .unwrap().as_bytearray().unwrap();
            let sky_light = chunk.find_equiv("SkyLight")
                .unwrap().as_bytearray().unwrap();

            fn array_16x16x16<T>(
                f: |uint, uint, uint| -> T
            ) -> [[[T, ..SIZE], ..SIZE], ..SIZE] {
                Array::from_fn(|y| -> [[T, ..SIZE], ..SIZE]
                    Array::from_fn(|z| -> [T, ..16]
                        Array::from_fn(|x| f(x, y, z))
                    )
                )
            }

            let chunk = Chunk {
                blocks: array_16x16x16(|x, y, z| {
                    let i = (y * SIZE + z) * SIZE + x;
                    let top = match blocks_top {
                        Some(blocks_top) => {
                            (blocks_top[i >> 1] >> ((i & 1) * 4)) & 0x0f
                        }
                        None => 0
                    };
                    let data = (blocks_data[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    BlockState {
                        value: (blocks[i] as u16 << 4)
                             | (top as u16 << 12)
                             | (data as u16)
                    }
                }),
                light_levels: array_16x16x16(|x, y, z| {
                    let i = (y * 16 + z) * 16 + x;
                    let block = (block_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    let sky = (sky_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    LightLevel {
                        value: block | (sky << 4)
                    }
                }),
            };
            let len = chunks.len();
            if y as uint >= len {
                chunks.grow(y as uint - len + 1, *EMPTY_CHUNK);
            }
            chunks[y as uint] = chunk;
        }
        let biomes = level.find_equiv("Biomes")
            .unwrap().as_bytearray().unwrap();
        Some(ChunkColumn {
            chunks: chunks,
            buffers: Array::from_fn(|_| Cell::new(None)),
            biomes: Array::from_fn(|z| -> [BiomeId, ..SIZE] Array::from_fn(|x| {
                BiomeId {
                    value: biomes[z * SIZE + x]
                }
            }))
        })
    }
}
<commit_msg>Replaced rustrt::trio::RtioFileStream with libc calls<commit_after>use libc;
use std::cell::Cell;
use std::os;

use array::*;
use chunk::{
    BiomeId,
    BlockState,
    Chunk,
    ChunkColumn,
    EMPTY_CHUNK,
    LightLevel,
    SIZE
};
use minecraft::nbt::Nbt;

pub struct Region {
    mmap: os::MemoryMap
}

impl Region {
    pub fn open(filename: &Path) -> Region {
        use std::mem::zeroed;

        unsafe {
            let fd = libc::open(
                    filename.as_str().unwrap().to_c_str().as_ptr(),
                    libc::consts::os::posix88::O_RDONLY,
                    libc::consts::os::posix88::S_IREAD
                );
            let mut stat = zeroed();
            libc::fstat(fd, &mut stat);
            let min_len = stat.st_size as uint;
            let options = [
                os::MapFd(fd),
                os::MapReadable
            ];

            Region {
                mmap: os::MemoryMap::new(min_len, options).unwrap()
            }
        }
    }

    fn as_slice<'a>(&'a self) -> &'a [u8] {
        use std::mem;
        use std::raw::Slice;
        let slice = Slice {
                data: self.mmap.data() as *const u8,
                len: self.mmap.len()
            };

        unsafe { mem::transmute(slice) }
    }

    pub fn get_chunk_column(&self, x: u8, z: u8) -> Option<ChunkColumn> {
        let locations = self.as_slice().slice_to(4096);
        let i = 4 * ((x % 32) as uint + (z % 32) as uint * 32);
        let start = (locations[i] as uint << 16)
                  | (locations[i + 1] as uint << 8)
                  | locations[i + 2] as uint;
        let num = locations[i + 3] as uint;
        if start == 0 || num == 0 { return None; }

        let sectors = self.as_slice().slice(start * 4096, (start + num) * 4096);
        let len = (sectors[0] as uint << 24)
                | (sectors[1] as uint << 16)
                | (sectors[2] as uint << 8)
                | sectors[3] as uint;
        let nbt = match sectors[4] {
            1 => Nbt::from_gzip(sectors.slice(5, 4 + len)),
            2 => Nbt::from_zlib(sectors.slice(5, 4 + len)),
            c => panic!("unknown region chunk compression method {}", c)
        };

        let mut c = nbt.unwrap().into_compound().unwrap();
        let mut level = c.pop_equiv("Level").unwrap().into_compound().unwrap();
        let mut chunks = Vec::new();
        for chunk in level.pop_equiv("Sections")
            .unwrap().into_compound_list().unwrap().into_iter() {

            let y = chunk.find_equiv("Y")
                .unwrap().as_byte().unwrap();
            let blocks = chunk.find_equiv("Blocks")
                .unwrap().as_bytearray().unwrap();
            let blocks_top = chunk.find_equiv("Add")
                .and_then(|x| x.as_bytearray());
            let blocks_data = chunk.find_equiv("Data")
                .unwrap().as_bytearray().unwrap();
            let block_light = chunk.find_equiv("BlockLight")
                .unwrap().as_bytearray().unwrap();
            let sky_light = chunk.find_equiv("SkyLight")
                .unwrap().as_bytearray().unwrap();

            fn array_16x16x16<T>(
                f: |uint, uint, uint| -> T
            ) -> [[[T, ..SIZE], ..SIZE], ..SIZE] {
                Array::from_fn(|y| -> [[T, ..SIZE], ..SIZE]
                    Array::from_fn(|z| -> [T, ..16]
                        Array::from_fn(|x| f(x, y, z))
                    )
                )
            }

            let chunk = Chunk {
                blocks: array_16x16x16(|x, y, z| {
                    let i = (y * SIZE + z) * SIZE + x;
                    let top = match blocks_top {
                        Some(blocks_top) => {
                            (blocks_top[i >> 1] >> ((i & 1) * 4)) & 0x0f
                        }
                        None => 0
                    };
                    let data = (blocks_data[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    BlockState {
                        value: (blocks[i] as u16 << 4)
                             | (top as u16 << 12)
                             | (data as u16)
                    }
                }),
                light_levels: array_16x16x16(|x, y, z| {
                    let i = (y * 16 + z) * 16 + x;
                    let block = (block_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    let sky = (sky_light[i >> 1] >> ((i & 1) * 4)) & 0x0f;
                    LightLevel {
                        value: block | (sky << 4)
                    }
                }),
            };
            let len = chunks.len();
            if y as uint >= len {
                chunks.grow(y as uint - len + 1, *EMPTY_CHUNK);
            }
            chunks[y as uint] = chunk;
        }
        let biomes = level.find_equiv("Biomes")
            .unwrap().as_bytearray().unwrap();
        Some(ChunkColumn {
            chunks: chunks,
            buffers: Array::from_fn(|_| Cell::new(None)),
            biomes: Array::from_fn(|z| -> [BiomeId, ..SIZE] Array::from_fn(|x| {
                BiomeId {
                    value: biomes[z * SIZE + x]
                }
            }))
        })
    }
}
<|endoftext|>


<commit_before>extern crate reqwest;

use model::card::{Card, CardPage, Variation};
use self::reqwest::Url;
use std::collections::HashMap;

macro_rules! get_card {
    ($query: expr, $query_type: ty) => (
        {
            let mut resp = reqwest::get($query)?;
            println!("Query: {:?}", $query);
            println!("Status: {:?}", resp.status());
            match resp.json::<$query_type>() {
                Err(e) => Err(e),
                Ok(card) => Ok(card)
            }
        }
    )
}

/// Structure used to construct an url to query the gwent api.
///
/// Functions on the QueryBuilder are chainable, provided it has been
/// initialized first.
///
/// Links to the [gwent api](https://gwentapi.com/) and its [documentation](https://gwentapi.com/swagger/index.html).
pub struct QueryBuilder(pub HashMap<String, String>);

impl QueryBuilder {
    /// Constructs a new QueryBuilder. It is necessary to do so before chaining other operations.
    pub fn new() -> QueryBuilder {
        QueryBuilder(HashMap::new())
    }

    /// Returns an Url with all parameters set.
    ///
    /// # Arguments
    ///
    /// * `base_url` - the url targetted by the request
    ///
    /// # Examples
    ///
    /// ```
    /// use reqwest::Url;
    ///
    /// let url = QueryBuilder::new()
    ///     .card_name("Alchemist")
    ///     .as_url("https://api.gwentapi.com/v0/cards/");
    /// ```
    pub fn as_url(&self, base_url: &str) -> Result<Url, reqwest::UrlError> {
        Url::parse_with_params(base_url, &self.0)
    }

    /// Sets the language of the returned response.
    ///
    /// # Arguments
    ///
    /// * `language` - string ∈ {en-US, de-DE, es-ES, es-MX, fr-FR, it-IT, ja-JP, pl-PL, pt-BR, ru-RU}
    ///
    /// # Examples
    ///
    /// ```
    /// use reqwest::Url;
    ///
    /// let url = QueryBuilder::new()
    ///     .lang("fr-FR")
    ///     .as_url("https://api.gwentapi.com/v0/cards/bLkeCcb0VeaNNS2J73VLVA");
    /// ```
    pub fn lang<'a>(&'a mut self, language: &str) -> &'a mut Self {
        self.0.insert(String::from("lang"), String::from(language));
        self
    }

    /// Sets the name of the searched card.
    ///
    /// # Arguments
    ///
    /// * `card_name` - name of the card
    ///
    /// # Examples
    ///
    /// ```
    /// let url = QueryBuilder::new()
    ///     .card_name("Geralt: Igni")
    ///     .as_url("https://api.gwentapi.com/v0/cards/");
    /// ```
    ///
    /// # Errors
    ///
    /// Not available on certain API requests.
    ///
    /// Will fail with:
    ///
    /// * GET /v0/cards
    pub fn card_name<'a>(&'a mut self, card_name: &str) -> &'a mut Self {
        self.0.insert(String::from("name"), String::from(card_name));
        self
    }

    /// Generic parameter setting.
    ///
    /// # Arguments
    ///
    /// * `param` - name of the request parameter
    /// * `value` - value of the request parameter
    pub fn with_arg<'a>(&'a mut self, param: &str, value: &str) -> &'a mut Self {
        self.0.insert(String::from(param), String::from(value));
        self
    }
}

/// Gateway offering specific functions through the gwent api.
pub struct Client { }

impl Client {
    fn get_query_card_by_name(card_name: &str) -> Result<Url, reqwest::UrlError> {
        QueryBuilder::new()
            .card_name(card_name)
            .as_url("https://api.gwentapi.com/v0/cards/")
    }

    /// Retrieves a Card object based on its name.
    ///
    /// # Arguments
    ///
    /// * `card_name` - the name of the desired card
    ///
    /// # Errors
    ///
    /// Will fail if the provided string doesn't correspons to any card in the API.
    /// All pattern matching and partial recognition is handled by the server.
    pub fn get_card_by_name(card_name: &str) -> reqwest::Result<Card> {
        let search_query = Self::get_query_card_by_name(card_name).unwrap();
        let mut search_result = get_card!(search_query.as_str(), CardPage).unwrap();
        let card_uri = if search_result.count >= 1 {
                let uri = search_result.results.pop().unwrap();
                uri.href.clone()
            }
            else {
                String::new()
            };
        get_card!(card_uri.as_str(), Card)
    }

    /// Retrieves the default Variation object of a given card.
    ///
    /// This object contains a link to the art representing the card in the game.
    ///
    /// # Arguments
    ///
    /// * `card`: a reference to the Card
    pub fn get_card_default_art(card: &Card) -> reqwest::Result<Variation> {
        let search_query = card.variations[0].href.clone();
        get_card!(search_query.as_str(), Variation)
    }
}<commit_msg>Fixed documentation testing<commit_after>extern crate reqwest;

use model::card::{Card, CardPage, Variation};
use self::reqwest::Url;
use std::collections::HashMap;

macro_rules! get_card {
    ($query: expr, $query_type: ty) => (
        {
            let mut resp = reqwest::get($query)?;
            println!("Query: {:?}", $query);
            println!("Status: {:?}", resp.status());
            match resp.json::<$query_type>() {
                Err(e) => Err(e),
                Ok(card) => Ok(card)
            }
        }
    )
}

/// Structure used to construct an url to query the gwent api.
///
/// Functions on the QueryBuilder are chainable, provided it has been
/// initialized first.
///
/// Links to the [gwent api](https://gwentapi.com/) and its [documentation](https://gwentapi.com/swagger/index.html).
pub struct QueryBuilder(pub HashMap<String, String>);

impl QueryBuilder {
    /// Constructs a new QueryBuilder. It is necessary to do so before chaining other operations.
    pub fn new() -> QueryBuilder {
        QueryBuilder(HashMap::new())
    }

    /// Returns an Url with all parameters set.
    ///
    /// # Arguments
    ///
    /// * `base_url` - the url targetted by the request
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate reqwest;
    /// extern crate gwent_api;
    ///
    /// fn main() {
    ///
    ///     use reqwest::Url;
    ///     use gwent_api::client::gw_client::QueryBuilder;
    ///
    ///     let url = QueryBuilder::new()
    ///         .card_name("Alchemist")
    ///         .as_url("https://api.gwentapi.com/v0/cards/");
    /// }
    /// ```
    pub fn as_url(&self, base_url: &str) -> Result<Url, reqwest::UrlError> {
        Url::parse_with_params(base_url, &self.0)
    }

    /// Sets the language of the returned response.
    ///
    /// # Arguments
    ///
    /// * `language` - string ∈ {en-US, de-DE, es-ES, es-MX, fr-FR, it-IT, ja-JP, pl-PL, pt-BR, ru-RU}
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate reqwest;
    /// extern crate gwent_api;
    ///
    /// fn main() {
    ///
    ///     use reqwest::Url;
    ///     use gwent_api::client::gw_client::QueryBuilder;
    ///
    ///     let url = QueryBuilder::new()
    ///         .lang("fr-FR")
    ///         .as_url("https://api.gwentapi.com/v0/cards/bLkeCcb0VeaNNS2J73VLVA");
    /// }
    /// ```
    pub fn lang<'a>(&'a mut self, language: &str) -> &'a mut Self {
        self.0.insert(String::from("lang"), String::from(language));
        self
    }

    /// Sets the name of the searched card.
    ///
    /// # Arguments
    ///
    /// * `card_name` - name of the card
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate reqwest;
    /// extern crate gwent_api;
    ///
    /// fn main() {
    ///
    ///     use reqwest::Url;
    ///     use gwent_api::client::gw_client::QueryBuilder;
    ///
    ///     let url = QueryBuilder::new()
    ///         .card_name("Geralt: Igni")
    ///         .as_url("https://api.gwentapi.com/v0/cards/");
    /// }
    /// ```
    ///
    /// # Errors
    ///
    /// Not available on certain API requests.
    ///
    /// Will fail with:
    ///
    /// * GET /v0/cards
    pub fn card_name<'a>(&'a mut self, card_name: &str) -> &'a mut Self {
        self.0.insert(String::from("name"), String::from(card_name));
        self
    }

    /// Generic parameter setting.
    ///
    /// # Arguments
    ///
    /// * `param` - name of the request parameter
    /// * `value` - value of the request parameter
    pub fn with_arg<'a>(&'a mut self, param: &str, value: &str) -> &'a mut Self {
        self.0.insert(String::from(param), String::from(value));
        self
    }
}

/// Gateway offering specific functions through the gwent api.
pub struct Client { }

impl Client {
    fn get_query_card_by_name(card_name: &str) -> Result<Url, reqwest::UrlError> {
        QueryBuilder::new()
            .card_name(card_name)
            .as_url("https://api.gwentapi.com/v0/cards/")
    }

    /// Retrieves a Card object based on its name.
    ///
    /// # Arguments
    ///
    /// * `card_name` - the name of the desired card
    ///
    /// # Errors
    ///
    /// Will fail if the provided string doesn't correspons to any card in the API.
    /// All pattern matching and partial recognition is handled by the server.
    pub fn get_card_by_name(card_name: &str) -> reqwest::Result<Card> {
        let search_query = Self::get_query_card_by_name(card_name).unwrap();
        let mut search_result = get_card!(search_query.as_str(), CardPage).unwrap();
        let card_uri = if search_result.count >= 1 {
                let uri = search_result.results.pop().unwrap();
                uri.href.clone()
            }
            else {
                String::new()
            };
        get_card!(card_uri.as_str(), Card)
    }

    /// Retrieves the default Variation object of a given card.
    ///
    /// This object contains a link to the art representing the card in the game.
    ///
    /// # Arguments
    ///
    /// * `card`: a reference to the Card
    pub fn get_card_default_art(card: &Card) -> reqwest::Result<Variation> {
        let search_query = card.variations[0].href.clone();
        get_card!(search_query.as_str(), Variation)
    }
}<|endoftext|>


<commit_before>//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
//
// SPDX-License-Identifier: MPL-2.0

use glib::prelude::*;

mod imp;
mod playlist;

glib::wrapper! {
    pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends gst::Bin, gst::Element, gst::Object;
}

unsafe impl Send for HlsSink3 {}
unsafe impl Sync for HlsSink3 {}

pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gst::Element::register(
        Some(plugin),
        "hlssink3",
        gst::Rank::None,
        HlsSink3::static_type(),
    )?;

    Ok(())
}

gst::plugin_define!(
    hlssink3,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    "MIT/X11",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<commit_msg>Fix license in hlssink3 plugin<commit_after>//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
//
// SPDX-License-Identifier: MPL-2.0

use glib::prelude::*;

mod imp;
mod playlist;

glib::wrapper! {
    pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends gst::Bin, gst::Element, gst::Object;
}

unsafe impl Send for HlsSink3 {}
unsafe impl Sync for HlsSink3 {}

pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    gst::Element::register(
        Some(plugin),
        "hlssink3",
        gst::Rank::None,
        HlsSink3::static_type(),
    )?;

    Ok(())
}

gst::plugin_define!(
    hlssink3,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    // FIXME: MPL-2.0 is only allowed since 1.18.3 (as unknown) and 1.20 (as known)
    "MPL",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate mio;

use helper::Log;

use self::mio::tcp::{TcpListener, TcpStream};
use self::mio::{Ready, PollOpt, Token};
use self::mio::channel::Sender;

use node::{Node, NET_TCP_SERVER_TOKEN};
use network::{CONNECTION_COUNT_PRE_ALLOC, TcpConnection
              , Connection, Networking
              , TcpHandlerCommand, TcpHandlerCMD};
use helper::NetHelper;

use std::net::SocketAddr;
use std::error::Error;
use std::process;
use std::str::FromStr;
use std::io::ErrorKind;
use std::sync::Arc;

/// TcpNetwork Trait for implementing TCP networking capabilities
/// On top of Node structure
pub trait TcpNetwork {
    /// Min function to attach TCP service functionality to existing POLL service
    fn register_tcp(&mut self);

    /// Make TCP server socket listener from given address
    fn make_tcp_server(address: &str) -> TcpListener;

    /// Handler for event loop ready event
    /// This is general event processing for TCP connections/servers
    /// If event token not in the TCP list it will return false
    /// To let other components to handle event
    fn tcp_ready(&mut self, token: Token, event_kind: Ready) -> bool;

    /// Function for accepting TCP connections as a pending connections
    fn tcp_acceptable(&mut self);

    /// Function for reading TCP data from pending connections
    fn tcp_readable(&mut self, token: Token);

    /// Function for writing TCP data from pending connections
    fn tcp_writable(&mut self, token: Token);

    /// closing TCP connection
    fn tcp_close(&mut self, token: Token);

    /// getting one of the TCP handler channels
    /// using Round Rubin algorithm
    fn tcp_get_handler(&mut self) -> Sender<TcpHandlerCommand>;

    /// making client connection to given address
    fn tcp_connect(&mut self, address: &str) -> bool;

    /// Inserting connection socket
    fn add_connection(&mut self, socket: TcpStream, from_server: bool);
}

impl TcpNetwork for Node {
    fn register_tcp(&mut self) {
        match self.poll.register(&self.net_tcp_server, NET_TCP_SERVER_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {}
            Err(e) => {
                Log::error("Unable to register TCP server to Node POLL service", e.description());
                process::exit(1);
            }
        }
    }

    fn make_tcp_server(address: &str) -> TcpListener {
        let addr = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(e) => {
                Log::error("Unable to parse given TCP server address", e.description());
                process::exit(1);
            }
        };

        match TcpListener::bind(&addr) {
            Ok(s) => s,
            Err(e) => {
                Log::error("Unable to bind given TCP server address", e.description());
                process::exit(1);
            }
        }
    }

    #[inline(always)]
    fn tcp_ready(&mut self, token: Token, event_kind: Ready) -> bool {
        if token == NET_TCP_SERVER_TOKEN {
            if event_kind != Ready::readable() {
                Log::error("Unexpected TCP Server event kind", "Ignoring for now!");
                return false;
            }

            self.tcp_acceptable();
            return true;
        }

        if self.net_tcp_pending_connections.contains(token) {
            if event_kind == Ready::readable() {

                self.tcp_readable(token);

            } else if event_kind == Ready::writable() {

                self.tcp_writable(token);

            } else if event_kind == Ready::error()
                || event_kind == Ready::hup() {

                self.tcp_close(token);

            }

            return true;
        }

        false
    }

    #[inline(always)]
    fn tcp_acceptable(&mut self) {
        loop {
            let sock = match self.net_tcp_server.accept() {
                Ok((s, _)) => s,
                Err(e) => {
                    // if we got WouldBlock, then this is Non Blocking socket
                    // and data still not available for this, so it's not a connection error
                    if e.kind() != ErrorKind::WouldBlock {
                        Log::error("Unable to accept connection from TCP server socket", e.description());
                    }
                    return;
                }
            };

            self.add_connection(sock, true);
        };
    }

    #[inline(always)]
    fn tcp_readable(&mut self, token: Token) {
        // if we got here then we have connection with this token
        let mut close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            // if we don't have yet API version defined
            if !Connection::check_api_version(conn.api_version) {
                match conn.read_api_version() {
                    Some((done, version)) => {
                        // if we not done with reading API version
                        // Just returning and waiting until next readable cycle
                        if !done {
                            return;
                        }

                        // if we got wrong API version just closing connection
                        if !Connection::check_api_version(version) {
                            true
                        } else {
                            // if we got valid API version
                            // saving it as a connection version
                            conn.api_version = version;
                            false
                        }
                    }

                    // if we have connection error closing it
                    None => true
                }
            } else {
                false
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            // reading Connection Token and Value
            match conn.read_token_value() {
                Some((done, token_str, value)) => {
                    // if we not done with reading API version
                    // Just returning and waiting until next readable cycle
                    if !done {
                        return;
                    }

                    // checking if we got valid Prime Value or not
                    // if it's invalid just closing connection
                    if !NetHelper::validate_value(value) {
                        true
                    } else {
                        // if we done with token and value
                        // just setting them for connection
                        // and writing API handshake information
                        conn.conn_token = token_str;
                        conn.conn_value = value;

                        false
                    }
                }

                // if we have connection error closing it
                None => true
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        // if we got here then we have connection information
        // so now we need to send our handshake information
        // and after write will succeed, we will transfer connection
        // to one of the TCP handlers
        let info = Arc::new(self.handshake_info());
        self.net_tcp_pending_connections[token].write(info, &self.poll);
    }

    #[inline(always)]
    fn tcp_writable(&mut self, token: Token) {
        // if we got here then we have connection with this token
        let close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            match conn.flush() {
                Some(done) => {
                    // if Write queue is not empty, just returning
                    // and waiting for the next cycle
                    if !done {
                        return;
                    }

                    // letting know to keep connection
                    // so that we can make sure that queue is empty
                    false
                }

                // closing connection if we have write error
                None => true
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        // if we got here then write is done
        // so moving connection to one of the TCP handlers
        let mut command = TcpHandlerCommand::new();
        // removing connection from pending connections list
        let conn = self.net_tcp_pending_connections.remove(token).unwrap();
        // de-registering from current event loop
        let _ = self.poll.deregister(&conn.socket);

        command.cmd = TcpHandlerCMD::HandleConnection;
        command.conn.push(conn);
        match self.tcp_get_handler().send(command) {
            Ok(_) => {},
            Err(e) => {
                Log::error("Unable to send HandleConnection command to TCP handler", e.description());
                return;
            }
        }
    }

    #[inline(always)]
    fn tcp_close(&mut self, token: Token) {
        // just removing connection
        // it would be closed automatically when
        // connection object de-allocated from memory
        self.net_tcp_pending_connections.remove(token);
    }

    #[inline(always)]
    fn tcp_get_handler(&mut self) -> Sender<TcpHandlerCommand> {
        if self.net_tcp_handler_index >= self.net_tcp_handler_sender_chan.len() {
            self.net_tcp_handler_index = 0;
        }

        let i = self.net_tcp_handler_index;
        self.net_tcp_handler_index += 1;

        self.net_tcp_handler_sender_chan[i].clone()
    }

    #[inline(always)]
    fn tcp_connect(&mut self, address: &str) -> bool {
        let sock_address = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(e) => {
                Log::error(format!("Unable to parse address for making connection to TCP server {}", address).as_str(), e.description());
                return false;
            }
        };

        let sock = match TcpStream::connect(&sock_address) {
            Ok(s) => s,
            Err(e) => {
                Log::error(format!("Unable to connect with given tcp address {}", address).as_str(), e.description());
                return false;
            }
        };

        self.add_connection(sock, false);
        true
    }

    #[inline(always)]
    fn add_connection(&mut self, socket: TcpStream, from_server: bool) {
        // inserting connection to pending connections and registering to the loop
        if self.net_tcp_pending_connections.vacant_entry().is_none() {
            self.net_tcp_pending_connections.reserve_exact(CONNECTION_COUNT_PRE_ALLOC);
        }

        let data = Arc::new(self.handshake_info());

        let entry = match self.net_tcp_pending_connections.vacant_entry() {
            Some(e) => e,
            None => {
                Log::error("Unable to insert accepted connection to TcpNetwork pending connections"
                           , "Not enough place in Slab");
                return;
            }
        };

        // creating connection and registering to current Node poll service
        let mut conn = TcpConnection::new(socket, entry.index(), true);
        conn.register(&self.poll);
        if !from_server {
            conn.write(data, &self.poll);
        }
        entry.insert(conn);
    }
}

<commit_msg>tcp connect with some bug fixes<commit_after>#![allow(dead_code)]
extern crate mio;

use helper::Log;

use self::mio::tcp::{TcpListener, TcpStream};
use self::mio::{Ready, PollOpt, Token};
use self::mio::channel::Sender;

use node::{Node, NET_TCP_SERVER_TOKEN};
use network::{CONNECTION_COUNT_PRE_ALLOC, TcpConnection
              , Connection, Networking
              , TcpHandlerCommand, TcpHandlerCMD};
use helper::NetHelper;

use std::net::SocketAddr;
use std::error::Error;
use std::process;
use std::str::FromStr;
use std::io::ErrorKind;
use std::sync::Arc;

/// TcpNetwork Trait for implementing TCP networking capabilities
/// On top of Node structure
pub trait TcpNetwork {
    /// Min function to attach TCP service functionality to existing POLL service
    fn register_tcp(&mut self);

    /// Make TCP server socket listener from given address
    fn make_tcp_server(address: &str) -> TcpListener;

    /// Handler for event loop ready event
    /// This is general event processing for TCP connections/servers
    /// If event token not in the TCP list it will return false
    /// To let other components to handle event
    fn tcp_ready(&mut self, token: Token, event_kind: Ready) -> bool;

    /// Function for accepting TCP connections as a pending connections
    fn tcp_acceptable(&mut self);

    /// Function for reading TCP data from pending connections
    fn tcp_readable(&mut self, token: Token);

    /// Function for writing TCP data from pending connections
    fn tcp_writable(&mut self, token: Token);

    /// closing TCP connection
    fn tcp_close(&mut self, token: Token);

    /// getting one of the TCP handler channels
    /// using Round Rubin algorithm
    fn tcp_get_handler(&mut self) -> Sender<TcpHandlerCommand>;

    /// making client connection to given address
    fn tcp_connect(&mut self, address: &str) -> bool;

    /// Inserting connection socket
    fn tcp_add_connection(&mut self, socket: TcpStream, from_server: bool);

    /// Transferring connection from pending to one of the TCP handlers
    fn tcp_transfer_connection(&mut self, token: Token);
}

impl TcpNetwork for Node {
    fn register_tcp(&mut self) {
        match self.poll.register(&self.net_tcp_server, NET_TCP_SERVER_TOKEN, Ready::readable(), PollOpt::edge()) {
            Ok(_) => {}
            Err(e) => {
                Log::error("Unable to register TCP server to Node POLL service", e.description());
                process::exit(1);
            }
        }
    }

    fn make_tcp_server(address: &str) -> TcpListener {
        let addr = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(e) => {
                Log::error("Unable to parse given TCP server address", e.description());
                process::exit(1);
            }
        };

        match TcpListener::bind(&addr) {
            Ok(s) => s,
            Err(e) => {
                Log::error("Unable to bind given TCP server address", e.description());
                process::exit(1);
            }
        }
    }

    #[inline(always)]
    fn tcp_ready(&mut self, token: Token, event_kind: Ready) -> bool {
        if token == NET_TCP_SERVER_TOKEN {
            if event_kind != Ready::readable() {
                Log::error("Unexpected TCP Server event kind", "Ignoring for now!");
                return false;
            }

            self.tcp_acceptable();
            return true;
        }

        if self.net_tcp_pending_connections.contains(token) {
            if event_kind == Ready::readable() {

                self.tcp_readable(token);

            } else if event_kind == Ready::writable() {

                self.tcp_writable(token);

            } else if event_kind == Ready::error()
                || event_kind == Ready::hup() {

                self.tcp_close(token);

            }

            return true;
        }

        false
    }

    #[inline(always)]
    fn tcp_acceptable(&mut self) {
        loop {
            let sock = match self.net_tcp_server.accept() {
                Ok((s, _)) => s,
                Err(e) => {
                    // if we got WouldBlock, then this is Non Blocking socket
                    // and data still not available for this, so it's not a connection error
                    if e.kind() != ErrorKind::WouldBlock {
                        Log::error("Unable to accept connection from TCP server socket", e.description());
                    }
                    return;
                }
            };

            self.tcp_add_connection(sock, true);
        };
    }

    #[inline(always)]
    fn tcp_readable(&mut self, token: Token) {
        // if we got here then we have connection with this token
        let mut close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            // if we don't have yet API version defined
            if !Connection::check_api_version(conn.api_version) {
                match conn.read_api_version() {
                    Some((done, version)) => {
                        // if we not done with reading API version
                        // Just returning and waiting until next readable cycle
                        if !done {
                            return;
                        }

                        // if we got wrong API version just closing connection
                        if !Connection::check_api_version(version) {
                            true
                        } else {
                            // if we got valid API version
                            // saving it as a connection version
                            conn.api_version = version;
                            false
                        }
                    }

                    // if we have connection error closing it
                    None => true
                }
            } else {
                false
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            // reading Connection Token and Value
            match conn.read_token_value() {
                Some((done, token_str, value)) => {
                    // if we not done with reading API version
                    // Just returning and waiting until next readable cycle
                    if !done {
                        return;
                    }

                    // checking if we got valid Prime Value or not
                    // if it's invalid just closing connection
                    if !NetHelper::validate_value(value) {
                        true
                    } else {
                        // if we done with token and value
                        // just setting them for connection
                        // and writing API handshake information
                        conn.conn_token = token_str;
                        conn.conn_value = value;

                        false
                    }
                }

                // if we have connection error closing it
                None => true
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        // if we got connection from client connect
        // then we have already written our handshake information
        // so we have already also his token value, and we can transfer connection
        // NOTE: connections from server would be transferred from tcp_writable function
        if !self.net_tcp_pending_connections[token].from_server {
            self.tcp_transfer_connection(token);
        }

        // if we got here then we have connection information
        // so now we need to send our handshake information
        // and after write will succeed, we will transfer connection
        // to one of the TCP handlers
        let info = Arc::new(self.handshake_info());
        self.net_tcp_pending_connections[token].write(info, &self.poll);
    }

    #[inline(always)]
    fn tcp_writable(&mut self, token: Token) {
        // if we got here then we have connection with this token
        let close_conn = {
            let ref mut conn: TcpConnection = self.net_tcp_pending_connections[token];
            match conn.flush() {
                Some(done) => {
                    // if Write queue is not empty, just returning
                    // and waiting for the next cycle
                    if !done {
                        return;
                    }

                    // letting know to keep connection
                    // so that we can make sure that queue is empty
                    false
                }

                // closing connection if we have write error
                None => true
            }
        };

        if close_conn {
            self.tcp_close(token);
            return;
        }

        // if we got connection from server
        // then we have already token and value from client connection
        // so we can transfer connection
        // NOTE: connections from "tcp_connect" would be transferred from tcp_readable function
        if self.net_tcp_pending_connections[token].from_server {
            self.tcp_transfer_connection(token);
        }
    }

    #[inline(always)]
    fn tcp_close(&mut self, token: Token) {
        // just removing connection
        // it would be closed automatically when
        // connection object de-allocated from memory
        self.net_tcp_pending_connections.remove(token);
    }

    #[inline(always)]
    fn tcp_get_handler(&mut self) -> Sender<TcpHandlerCommand> {
        if self.net_tcp_handler_index >= self.net_tcp_handler_sender_chan.len() {
            self.net_tcp_handler_index = 0;
        }

        let i = self.net_tcp_handler_index;
        self.net_tcp_handler_index += 1;

        self.net_tcp_handler_sender_chan[i].clone()
    }

    #[inline(always)]
    fn tcp_connect(&mut self, address: &str) -> bool {
        let sock_address = match SocketAddr::from_str(address) {
            Ok(a) => a,
            Err(e) => {
                Log::error(format!("Unable to parse address for making connection to TCP server {}", address).as_str(), e.description());
                return false;
            }
        };

        let sock = match TcpStream::connect(&sock_address) {
            Ok(s) => s,
            Err(e) => {
                Log::error(format!("Unable to connect with given tcp address {}", address).as_str(), e.description());
                return false;
            }
        };

        self.tcp_add_connection(sock, false);
        true
    }

    #[inline(always)]
    fn tcp_add_connection(&mut self, socket: TcpStream, from_server: bool) {
        // inserting connection to pending connections and registering to the loop
        if self.net_tcp_pending_connections.vacant_entry().is_none() {
            self.net_tcp_pending_connections.reserve_exact(CONNECTION_COUNT_PRE_ALLOC);
        }

        let data = Arc::new(self.handshake_info());

        let entry = match self.net_tcp_pending_connections.vacant_entry() {
            Some(e) => e,
            None => {
                Log::error("Unable to insert accepted connection to TcpNetwork pending connections"
                           , "Not enough place in Slab");
                return;
            }
        };

        // creating connection and registering to current Node poll service
        let mut conn = TcpConnection::new(socket, entry.index(), true);
        conn.register(&self.poll);
        if !from_server {
            conn.write(data, &self.poll);
        }
        entry.insert(conn);
    }

    fn tcp_transfer_connection(&mut self, token: Token) {
        // if we got here then write is done
        // so moving connection to one of the TCP handlers
        let mut command = TcpHandlerCommand::new();
        // removing connection from pending connections list
        let conn = self.net_tcp_pending_connections.remove(token).unwrap();
        // de-registering from current event loop
        let _ = self.poll.deregister(&conn.socket);

        command.cmd = TcpHandlerCMD::HandleConnection;
        command.conn.push(conn);
        match self.tcp_get_handler().send(command) {
            Ok(_) => {},
            Err(e) => {
                Log::error("Unable to send HandleConnection command to TCP handler", e.description());
                return;
            }
        }
    }
}

<|endoftext|>


<commit_before>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

#[doc(hidden)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        Element { name: name.into(), attributes: Attributes::new(), children: Children::new() }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                },
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                },
                _ => {},
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T) where T: Node {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U) where T: Into<String>, U: Into<Value> {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident($tag_name:expr))*) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new() -> Self {
                    $struct_name { inner: Element::new($tag_name) }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`animate`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateElement"]
    struct Animate("animate")

    #[doc = "An [`animateColor`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateColorElement"]
    struct AnimateColor("animateColor")

    #[doc = "An [`animateMotion`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement"]
    struct AnimateMotion("animateMotion")

    #[doc = "An [`animateTransform`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement"]
    struct AnimateTransform("animateTransform")

    #[doc = "A [`circle`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#CircleElement"]
    struct Circle("circle")

    #[doc = "A [`clipPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#ClipPathElement"]
    struct ClipPath("clipPath")

    #[doc = "A [`defs`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DefsElement"]
    struct Definitions("defs")

    #[doc = "A [`desc`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DescElement"]
    struct Description("desc")

    #[doc = "An [`ellipse`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#EllipseElement"]
    struct Ellipse("ellipse")

    #[doc = "A [`filter`][1] element.
    [1]: https://www.w3.org/TR/SVG/filters.html#FilterElement"]
    struct Filter("filter")

    #[doc = "A [`g`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#GElement"]
    struct Group("g")

    #[doc = "An [`image`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#ImageElement"]
    struct Image("image")

    #[doc = "A [`line`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#LineElement"]
    struct Line("line")

    #[doc = "A [`linearGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement"]
    struct LinearGradient("linearGradient")

    #[doc = "An [`a`][1] element.
    [1]: https://www.w3.org/TR/SVG/linking.html#AElement"]
    struct Link("a")

    #[doc = "A [`marker`][1] element.
    [1]: https://www.w3.org/TR/SVG/painting.html#MarkerElement"]
    struct Marker("marker")

    #[doc = "A [`mask`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#MaskElement"]
    struct Mask("mask")

    #[doc = "An [`mpath`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#MPathElement"]
    struct MotionPath("mpath")

    #[doc = "A [`path`][1] element.
    [1]: https://www.w3.org/TR/SVG/paths.html#PathElement"]
    struct Path("path")

    #[doc = "A [`polygon`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolygonElement"]
    struct Polygon("polygon")

    #[doc = "A [`polyline`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolylineElement"]
    struct Polyline("polyline")

    #[doc = "A [`radialGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement"]
    struct RadialGradient("radialGradient")

    #[doc = "A [`rect`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#RectElement"]
    struct Rectangle("rect")

    #[doc = "A [`stop`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#StopElement"]
    struct Stop("stop")

    #[doc = "A [`symbol`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SymbolElement"]
    struct Symbol("symbol")

    #[doc = "A [`text`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextElement"]
    struct Text("text")

    #[doc = "A [`textPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextPathElement"]
    struct TextPath("textPath")

    #[doc = "A [`title`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#TitleElement"]
    struct Title("title")

    #[doc = "A [`use`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#UseElement"]
    struct Use("use")
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    (
        $(
            #[$doc:meta]
            struct $struct_name:ident($tag_name:expr)
            [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
        )*
    ) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            implement! { @itemize
                impl $struct_name {
                    /// Create a node.
                    #[inline]
                    pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                        #[inline(always)]
                        fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                        let mut inner = Element::new($tag_name);
                        initialize(&mut inner $(, $an)*);
                        $struct_name { inner: inner }
                    }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`svg`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SVGElement"]
    struct SVG("svg") [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`][1] element.
    [1]: https://www.w3.org/TR/SVG/script.html#ScriptElement"]
    struct Script("script") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`][1] element.
    [1]: https://www.w3.org/TR/SVG/styling.html#StyleElement"]
    struct Style("style") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

pub mod path;

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));
        assert_eq!(element.to_string(), "\
            <foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
            <bar/>\n\
            </foo>\
        ");
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);
        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");
        assert_eq!(element.to_string(), "\
            <style>\n\
            * { font-family: foo; }\n\
            </style>\
        ");
    }
}
<commit_msg>Make a cosmetic adjustment<commit_after>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

#[doc(hidden)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        Element { name: name.into(), attributes: Attributes::new(), children: Children::new() }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                },
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                },
                _ => {},
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T) where T: Node {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U) where T: Into<String>, U: Into<Value> {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident($tag_name:expr))*) => ($(
        #[$doc]
        pub struct $struct_name {
            inner: Element,
        }

        impl $struct_name {
            /// Create a node.
            #[inline]
            pub fn new() -> Self {
                $struct_name { inner: Element::new($tag_name) }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`animate`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateElement"]
    struct Animate("animate")

    #[doc = "An [`animateColor`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateColorElement"]
    struct AnimateColor("animateColor")

    #[doc = "An [`animateMotion`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement"]
    struct AnimateMotion("animateMotion")

    #[doc = "An [`animateTransform`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement"]
    struct AnimateTransform("animateTransform")

    #[doc = "A [`circle`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#CircleElement"]
    struct Circle("circle")

    #[doc = "A [`clipPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#ClipPathElement"]
    struct ClipPath("clipPath")

    #[doc = "A [`defs`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DefsElement"]
    struct Definitions("defs")

    #[doc = "A [`desc`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DescElement"]
    struct Description("desc")

    #[doc = "An [`ellipse`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#EllipseElement"]
    struct Ellipse("ellipse")

    #[doc = "A [`filter`][1] element.
    [1]: https://www.w3.org/TR/SVG/filters.html#FilterElement"]
    struct Filter("filter")

    #[doc = "A [`g`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#GElement"]
    struct Group("g")

    #[doc = "An [`image`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#ImageElement"]
    struct Image("image")

    #[doc = "A [`line`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#LineElement"]
    struct Line("line")

    #[doc = "A [`linearGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement"]
    struct LinearGradient("linearGradient")

    #[doc = "An [`a`][1] element.
    [1]: https://www.w3.org/TR/SVG/linking.html#AElement"]
    struct Link("a")

    #[doc = "A [`marker`][1] element.
    [1]: https://www.w3.org/TR/SVG/painting.html#MarkerElement"]
    struct Marker("marker")

    #[doc = "A [`mask`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#MaskElement"]
    struct Mask("mask")

    #[doc = "An [`mpath`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#MPathElement"]
    struct MotionPath("mpath")

    #[doc = "A [`path`][1] element.
    [1]: https://www.w3.org/TR/SVG/paths.html#PathElement"]
    struct Path("path")

    #[doc = "A [`polygon`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolygonElement"]
    struct Polygon("polygon")

    #[doc = "A [`polyline`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolylineElement"]
    struct Polyline("polyline")

    #[doc = "A [`radialGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement"]
    struct RadialGradient("radialGradient")

    #[doc = "A [`rect`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#RectElement"]
    struct Rectangle("rect")

    #[doc = "A [`stop`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#StopElement"]
    struct Stop("stop")

    #[doc = "A [`symbol`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SymbolElement"]
    struct Symbol("symbol")

    #[doc = "A [`text`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextElement"]
    struct Text("text")

    #[doc = "A [`textPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextPathElement"]
    struct TextPath("textPath")

    #[doc = "A [`title`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#TitleElement"]
    struct Title("title")

    #[doc = "A [`use`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#UseElement"]
    struct Use("use")
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    ($(
        #[$doc:meta]
        struct $struct_name:ident($tag_name:expr)
        [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
    )*) => ($(
        #[$doc]
        pub struct $struct_name {
            inner: Element,
        }

        implement! { @itemize
            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                    #[inline(always)]
                    fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                    let mut inner = Element::new($tag_name);
                    initialize(&mut inner $(, $an)*);
                    $struct_name { inner: inner }
                }
            }
        }

        node! { $struct_name::inner }
    )*);
}

implement! {
    #[doc = "An [`svg`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SVGElement"]
    struct SVG("svg") [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`][1] element.
    [1]: https://www.w3.org/TR/SVG/script.html#ScriptElement"]
    struct Script("script") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`][1] element.
    [1]: https://www.w3.org/TR/SVG/styling.html#StyleElement"]
    struct Style("style") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

pub mod path;

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));
        assert_eq!(element.to_string(), "\
            <foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
            <bar/>\n\
            </foo>\
        ");
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);
        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");
        assert_eq!(element.to_string(), "\
            <style>\n\
            * { font-family: foo; }\n\
            </style>\
        ");
    }
}
<|endoftext|>


<commit_before>use crate::eval::AssignmentTarget;
use crate::syntax::IdentifierIndex;
use crate::syntax::identifiers::{SEMICOLON, COMMA};
use crate::value::implement::*;
use AmbiguousSyntax::*;
use ExpressionErrorPosition::*;
use crate::value::RightOperand;

#[derive(Debug, Clone)]
pub enum AmbiguousSyntax<'a> {
    MissingExpression,
    PartialTuple(Vec<BergVal<'a>>),
    TrailingComma(Vec<BergVal<'a>>),
    TrailingSemicolon,
    RawIdentifier(IdentifierIndex),
    Target(AssignmentTarget<'a>),
}

impl<'a> BergValue<'a> for AmbiguousSyntax<'a> {
    fn into_val(self) -> BergResult<'a> {
        self.err()
    }
    fn next_val(self) -> BergResult<'a, Option<NextVal<'a>>> {
        self.disambiguate().next_val()
    }
    fn into_native<T: TryFromBergVal<'a>>(self) -> BergResult<'a, T> {
        self.disambiguate().into_native()
    }
    fn try_into_native<T: TryFromBergVal<'a>>(self) -> BergResult<'a, Option<T>> {
        self.disambiguate().try_into_native()
    }

    fn infix(self, operator: IdentifierIndex, right: RightOperand<'a, impl BergValue<'a>>) -> BergResult<'a> {
        match self {
            Target(v) => v.infix(operator, right),
            RawIdentifier(v) => v.infix(operator, right),
            TrailingSemicolon if operator == SEMICOLON => BergError::MissingOperand.operand_err(LeftRight),
            TrailingComma(_) if operator == COMMA => BergError::MissingOperand.operand_err(LeftRight),
            PartialTuple(mut vec) => match operator {
                COMMA => { vec.push(right.into_val()?); PartialTuple(vec).disambiguate() },
                _ => PartialTuple(vec).disambiguate().infix(operator, right),
            }
            MissingExpression | TrailingSemicolon | TrailingComma(_) => self.disambiguate().infix(operator, right),
        }
    }

    fn infix_assign(self, operator: IdentifierIndex, right: RightOperand<'a, impl BergValue<'a>>) -> BergResult<'a> {
        match self {
            Target(v) => v.infix_assign(operator, right),
            RawIdentifier(v) => v.infix_assign(operator, right),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().infix_assign(operator, right),
        }
    }

    fn prefix(self, operator: IdentifierIndex) -> BergResult<'a> {
        match self {
            Target(v) => v.prefix(operator),
            RawIdentifier(v) => v.prefix(operator),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().prefix(operator),
        }
    }

    fn postfix(self, operator: IdentifierIndex) -> BergResult<'a> {
        match self {
            Target(v) => v.postfix(operator),
            RawIdentifier(v) => v.prefix(operator),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().postfix(operator),
        }
    }

    fn subexpression_result(self, boundary: ExpressionBoundary) -> BergResult<'a> {
        use ExpressionBoundary::*;
        match self {
            Target(v) => v.subexpression_result(boundary),
            RawIdentifier(v) => v.subexpression_result(boundary),
            MissingExpression if boundary == Parentheses || boundary == CurlyBraces => BergVal::empty_tuple().ok(),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().subexpression_result(boundary),
        }
    }

    fn field(self, name: IdentifierIndex) -> BergResult<'a, BergResult<'a>> {
        match self {
            Target(v) => v.field(name),
            RawIdentifier(v) => v.field(name),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().field(name),
        }
    }

    fn set_field(&mut self, name: IdentifierIndex, value: BergResult<'a>) -> BergResult<'a, ()> {
        match self {
            Target(v) => v.set_field(name, value),
            RawIdentifier(v) => v.set_field(name, value),
            MissingExpression => BergError::MissingOperand.err(),
            PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => panic!("not yet implemented: can't set field {} on {:?} to {}", name, self, value.display()),
        }
    }
}

impl<'a> From<AmbiguousSyntax<'a>> for ControlVal<'a> {
    fn from(from: AmbiguousSyntax<'a>) -> Self {
        ControlVal::AmbiguousSyntax(from)
    }
}

impl<'a> AmbiguousSyntax<'a> {
    pub fn result<T>(self) -> BergResult<'a, T> {
        Err(ControlVal::AmbiguousSyntax(self))
    }
    pub fn disambiguate(self) -> BergResult<'a> {
        use AmbiguousSyntax::*;
        match self {
            MissingExpression => BergError::MissingOperand.err(),
            PartialTuple(vec) | TrailingComma(vec) => Tuple::from(vec).ok(),
            TrailingSemicolon => BergVal::empty_tuple().ok(),
            RawIdentifier(v) => v.into_val(),
            Target(v) => v.get(),
        }
    }
}
<commit_msg>Fix infinite recursion with into_val/into_native/try_into_native<commit_after>use crate::eval::AssignmentTarget;
use crate::syntax::IdentifierIndex;
use crate::syntax::identifiers::{SEMICOLON, COMMA};
use crate::value::implement::*;
use AmbiguousSyntax::*;
use ExpressionErrorPosition::*;
use crate::value::RightOperand;

#[derive(Debug, Clone)]
pub enum AmbiguousSyntax<'a> {
    MissingExpression,
    PartialTuple(Vec<BergVal<'a>>),
    TrailingComma(Vec<BergVal<'a>>),
    TrailingSemicolon,
    RawIdentifier(IdentifierIndex),
    Target(AssignmentTarget<'a>),
}

impl<'a> BergValue<'a> for AmbiguousSyntax<'a> {
    fn into_val(self) -> BergResult<'a> {
        self.err()
    }
    fn next_val(self) -> BergResult<'a, Option<NextVal<'a>>> {
        match self {
            Target(v) => v.next_val(),
            RawIdentifier(v) => v.next_val(),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().next_val(),
        }
    }
    fn into_native<T: TryFromBergVal<'a>>(self) -> BergResult<'a, T> {
        match self {
            Target(v) => v.into_native(),
            RawIdentifier(v) => v.into_native(),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().into_native(),
        }
    }
    fn try_into_native<T: TryFromBergVal<'a>>(self) -> BergResult<'a, Option<T>> {
        match self {
            Target(v) => v.try_into_native(),
            RawIdentifier(v) => v.try_into_native(),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().try_into_native(),
        }
    }

    fn infix(self, operator: IdentifierIndex, right: RightOperand<'a, impl BergValue<'a>>) -> BergResult<'a> {
        match self {
            Target(v) => v.infix(operator, right),
            RawIdentifier(v) => v.infix(operator, right),
            TrailingSemicolon if operator == SEMICOLON => BergError::MissingOperand.operand_err(LeftRight),
            TrailingComma(_) if operator == COMMA => BergError::MissingOperand.operand_err(LeftRight),
            PartialTuple(mut vec) => match operator {
                COMMA => { vec.push(right.into_val()?); PartialTuple(vec).disambiguate() },
                _ => PartialTuple(vec).disambiguate().infix(operator, right),
            }
            MissingExpression | TrailingSemicolon | TrailingComma(_) => self.disambiguate().infix(operator, right),
        }
    }

    fn infix_assign(self, operator: IdentifierIndex, right: RightOperand<'a, impl BergValue<'a>>) -> BergResult<'a> {
        match self {
            Target(v) => v.infix_assign(operator, right),
            RawIdentifier(v) => v.infix_assign(operator, right),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().infix_assign(operator, right),
        }
    }

    fn prefix(self, operator: IdentifierIndex) -> BergResult<'a> {
        match self {
            Target(v) => v.prefix(operator),
            RawIdentifier(v) => v.prefix(operator),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().prefix(operator),
        }
    }

    fn postfix(self, operator: IdentifierIndex) -> BergResult<'a> {
        match self {
            Target(v) => v.postfix(operator),
            RawIdentifier(v) => v.prefix(operator),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().postfix(operator),
        }
    }

    fn subexpression_result(self, boundary: ExpressionBoundary) -> BergResult<'a> {
        use ExpressionBoundary::*;
        match self {
            Target(v) => v.subexpression_result(boundary),
            RawIdentifier(v) => v.subexpression_result(boundary),
            MissingExpression if boundary == Parentheses || boundary == CurlyBraces => BergVal::empty_tuple().ok(),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().subexpression_result(boundary),
        }
    }

    fn field(self, name: IdentifierIndex) -> BergResult<'a, BergResult<'a>> {
        match self {
            Target(v) => v.field(name),
            RawIdentifier(v) => v.field(name),
            MissingExpression | PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => self.disambiguate().field(name),
        }
    }

    fn set_field(&mut self, name: IdentifierIndex, value: BergResult<'a>) -> BergResult<'a, ()> {
        match self {
            Target(v) => v.set_field(name, value),
            RawIdentifier(v) => v.set_field(name, value),
            MissingExpression => BergError::MissingOperand.err(),
            PartialTuple(_) | TrailingComma(_) | TrailingSemicolon => panic!("not yet implemented: can't set field {} on {:?} to {}", name, self, value.display()),
        }
    }
}

impl<'a> From<AmbiguousSyntax<'a>> for ControlVal<'a> {
    fn from(from: AmbiguousSyntax<'a>) -> Self {
        ControlVal::AmbiguousSyntax(from)
    }
}

impl<'a> AmbiguousSyntax<'a> {
    pub fn result<T>(self) -> BergResult<'a, T> {
        Err(ControlVal::AmbiguousSyntax(self))
    }
    pub fn disambiguate(self) -> BergResult<'a> {
        use AmbiguousSyntax::*;
        match self {
            MissingExpression => BergError::MissingOperand.err(),
            PartialTuple(vec) | TrailingComma(vec) => Tuple::from(vec).ok(),
            TrailingSemicolon => BergVal::empty_tuple().ok(),
            RawIdentifier(v) => v.into_val(),
            Target(v) => v.get(),
        }
    }
}
<|endoftext|>


<commit_before>extern crate shootr;

extern crate specs;
extern crate chrono;

use self::specs::{DispatcherBuilder, World};
use self::chrono::prelude::*;

use shootr::engine::{Msg, Engine, EventHandler, Id};
use shootr::util::{read_env_var, elapsed_ms};
use shootr::model::{Vel, Pos, Ids};
use shootr::system::{Physics, Sending};

use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;

fn main() {
    shootr::engine::execute::<Handler>();
}
struct Handler {
    engine: Engine,
    ids: Ids,
}
impl EventHandler for Handler {
    fn new(engine: Engine) -> Self {
        Handler {
            engine,
            ids: Ids(Arc::new(RwLock::new(Vec::new()))),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        world.register::<Pos>();
        world.register::<Vel>();
        world.add_resource(self.engine.clone());
        world.add_resource(self.ids.clone());
        for _ in 0..1 {
            world
                .create_entity()
                .with(Vel { x: 8, y: 6 })
                .with(Pos { x: 500, y: 500 })
                .build();
        }

        let mut physics = DispatcherBuilder::new()
            .add(Physics, "physics", &[])
            .build();
        let mut renderer = DispatcherBuilder::new().add(Sending, "send", &[]).build();
        physics.dispatch(&mut world.res);

        let mut lag: u64 = 0;
        let mut previous = Utc::now();
        let updates_per_sec = read_env_var("CORE_UPDATES_PER_SEC").parse::<u64>().expect(
            "Failed to parse environmental variable as integer",
        );
        let ms_per_update = 1000 / updates_per_sec;
        loop {
            let current = Utc::now();
            let elapsed = elapsed_ms(previous, current);
            previous = current;
            lag += elapsed;
            while lag >= ms_per_update {
                physics.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            renderer.dispatch(&mut world.res);
            sleep(Duration::from_millis(ms_per_update - lag));
        }
    }
    fn message(&self, msg: &Msg) {
        println!("Received message: {}", msg.content);
    }
    fn connect(&self, id: Id) -> bool {
        self.ids.write().unwrap().push(id);
        true
    }
    fn disconnect(&self, id: Id) {
        let mut ids = self.ids.write().unwrap();
        let pos = ids.iter().position(|&x| x == id).expect(
            "Tried to remove id that was not added in the first place",
        );

        ids.remove(pos);
    }
}
<commit_msg>Core: Make ball faster<commit_after>extern crate shootr;

extern crate specs;
extern crate chrono;

use self::specs::{DispatcherBuilder, World};
use self::chrono::prelude::*;

use shootr::engine::{Msg, Engine, EventHandler, Id};
use shootr::util::{read_env_var, elapsed_ms};
use shootr::model::{Vel, Pos, Ids};
use shootr::system::{Physics, Sending};

use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;

fn main() {
    shootr::engine::execute::<Handler>();
}
struct Handler {
    engine: Engine,
    ids: Ids,
}
impl EventHandler for Handler {
    fn new(engine: Engine) -> Self {
        Handler {
            engine,
            ids: Ids(Arc::new(RwLock::new(Vec::new()))),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        world.register::<Pos>();
        world.register::<Vel>();
        world.add_resource(self.engine.clone());
        world.add_resource(self.ids.clone());
        for _ in 0..1 {
            world
                .create_entity()
                .with(Vel { x: 60, y: 40 })
                .with(Pos { x: 500, y: 500 })
                .build();
        }

        let mut physics = DispatcherBuilder::new()
            .add(Physics, "physics", &[])
            .build();
        let mut renderer = DispatcherBuilder::new().add(Sending, "send", &[]).build();
        physics.dispatch(&mut world.res);

        let mut lag: u64 = 0;
        let mut previous = Utc::now();
        let updates_per_sec = read_env_var("CORE_UPDATES_PER_SEC").parse::<u64>().expect(
            "Failed to parse environmental variable as integer",
        );
        let ms_per_update = 1000 / updates_per_sec;
        loop {
            let current = Utc::now();
            let elapsed = elapsed_ms(previous, current);
            previous = current;
            lag += elapsed;
            while lag >= ms_per_update {
                physics.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            renderer.dispatch(&mut world.res);
            sleep(Duration::from_millis(ms_per_update - lag));
        }
    }
    fn message(&self, msg: &Msg) {
        println!("Received message: {}", msg.content);
    }
    fn connect(&self, id: Id) -> bool {
        self.ids.write().unwrap().push(id);
        true
    }
    fn disconnect(&self, id: Id) {
        let mut ids = self.ids.write().unwrap();
        let pos = ids.iter().position(|&x| x == id).expect(
            "Tried to remove id that was not added in the first place",
        );

        ids.remove(pos);
    }
}
<|endoftext|>