<commit_before>use servo_media::player::frame::{Frame, FrameRenderer};
use std::mem;
use std::sync::{Arc, Mutex};
use webrender_api::{
    ImageData, ImageDescriptor, ImageFormat, ImageKey, RenderApi, RenderApiSender, Transaction,
};

#[derive(Clone)]
pub struct MediaFrameRenderer {
    inner: Arc<Mutex<MediaFrameRendererInner>>,
}

impl MediaFrameRenderer {
    pub fn new(render_api_sender: RenderApiSender) -> MediaFrameRenderer {
        MediaFrameRenderer {
            inner: Arc::new(Mutex::new(MediaFrameRendererInner {
                api: render_api_sender.create_api(),
                current_frame: None,
                old_frame: None,
                very_old_frame: None,
            })),
        }
    }
}

impl FrameRenderer for MediaFrameRenderer {
    fn render(&self, frame: Frame) {
        self.inner.lock().unwrap().render(frame);
    }
}

struct MediaFrameRendererInner {
    api: RenderApi,
    current_frame: Option<(ImageKey, i32, i32)>,
    old_frame: Option<ImageKey>,
    very_old_frame: Option<ImageKey>,
}

impl MediaFrameRendererInner {
    fn render(&mut self, frame: Frame) {
        let descriptor = ImageDescriptor::new(
            frame.get_width() as u32,
            frame.get_height() as u32,
            ImageFormat::BGRA8,
            false,
            false,
        );

        let mut txn = Transaction::new();

        //let image_data = ImageData::new_shared(frame.get_data().clone());
        let image_data = ImageData::Raw(frame.get_data().clone());

        if let Some(old_image_key) = mem::replace(&mut self.very_old_frame, self.old_frame.take()) {
            txn.delete_image(old_image_key);
        }

        match self.current_frame {
            Some((ref image_key, ref mut width, ref mut height))
                if *width == frame.get_width() && *height == frame.get_height() =>
            {
                txn.update_image(*image_key, descriptor, image_data, None);

                if let Some(old_image_key) = self.old_frame.take() {
                    txn.delete_image(old_image_key);
                }
            }
            Some((ref mut image_key, ref mut width, ref mut height)) => {
                self.old_frame = Some(*image_key);

                let new_image_key = self.api.generate_image_key();
                txn.add_image(new_image_key, descriptor, image_data, None);
                *image_key = new_image_key;
                *width = frame.get_width();
                *height = frame.get_height();
            }
            None => {
                let image_key = self.api.generate_image_key();
                txn.add_image(image_key, descriptor, image_data, None);
                self.current_frame = Some((image_key, frame.get_width(), frame.get_height()));
            }
        }

        self.api.update_resources(txn.resource_updates);
    }
}
<commit_msg>dom: framerenderer: implement HTMLMediaFrameSource trait for MediaFrameRenderer<commit_after>use servo_media::player::frame::{Frame, FrameRenderer};
use script_layout_interface::HTMLMediaFrameSource;
use std::mem;
use std::sync::{Arc, Mutex};
use webrender_api::{
    ImageData, ImageDescriptor, ImageFormat, ImageKey, RenderApi, RenderApiSender, Transaction,
};

#[derive(Clone)]
pub struct MediaFrameRenderer {
    inner: Arc<Mutex<MediaFrameRendererInner>>,
}

impl MediaFrameRenderer {
    pub fn new(render_api_sender: RenderApiSender) -> MediaFrameRenderer {
        MediaFrameRenderer {
            inner: Arc::new(Mutex::new(MediaFrameRendererInner {
                api: render_api_sender.create_api(),
                current_frame: None,
                old_frame: None,
                very_old_frame: None,
            })),
        }
    }
}

impl FrameRenderer for MediaFrameRenderer {
    fn render(&self, frame: Frame) {
        self.inner.lock().unwrap().render(frame);
    }
}

impl HTMLMediaFrameSource for MediaFrameRenderer {
    fn get_current_frame(&self) -> Option<(ImageKey, i32, i32)> {
        let inner = self.inner.lock().unwrap();
        inner.current_frame.clone()
    }

    fn clone_boxed(&self) -> Box<HTMLMediaFrameSource> {
        Box::new(self.clone())
    }
}

struct MediaFrameRendererInner {
    api: RenderApi,
    current_frame: Option<(ImageKey, i32, i32)>,
    old_frame: Option<ImageKey>,
    very_old_frame: Option<ImageKey>,
}

impl MediaFrameRendererInner {
    fn render(&mut self, frame: Frame) {
        let descriptor = ImageDescriptor::new(
            frame.get_width() as u32,
            frame.get_height() as u32,
            ImageFormat::BGRA8,
            false,
            false,
        );

        let mut txn = Transaction::new();

        //let image_data = ImageData::new_shared(frame.get_data().clone());
        let image_data = ImageData::Raw(frame.get_data().clone());

        if let Some(old_image_key) = mem::replace(&mut self.very_old_frame, self.old_frame.take()) {
            txn.delete_image(old_image_key);
        }

        match self.current_frame {
            Some((ref image_key, ref mut width, ref mut height))
                if *width == frame.get_width() && *height == frame.get_height() =>
            {
                txn.update_image(*image_key, descriptor, image_data, None);

                if let Some(old_image_key) = self.old_frame.take() {
                    txn.delete_image(old_image_key);
                }
            }
            Some((ref mut image_key, ref mut width, ref mut height)) => {
                self.old_frame = Some(*image_key);

                let new_image_key = self.api.generate_image_key();
                txn.add_image(new_image_key, descriptor, image_data, None);
                *image_key = new_image_key;
                *width = frame.get_width();
                *height = frame.get_height();
            }
            None => {
                let image_key = self.api.generate_image_key();
                txn.add_image(image_key, descriptor, image_data, None);
                self.current_frame = Some((image_key, frame.get_width(), frame.get_height()));
            }
        }

        self.api.update_resources(txn.resource_updates);
    }
}
<|endoftext|>


<commit_before>//! Completion tests for use trees.
use expect_test::{expect, Expect};

use crate::tests::completion_list;

fn check(ra_fixture: &str, expect: Expect) {
    let actual = completion_list(ra_fixture);
    expect.assert_eq(&actual)
}

#[test]
fn use_tree_start() {
    cov_mark::check!(only_completes_modules_in_import);
    check(
        r#"
//- /lib.rs crate:main deps:other_crate
use f$0

struct Foo;
mod foo {}
//- /other_crate/lib.rs crate:other_crate
// nothing here
"#,
        expect![[r#"
            md foo
            md other_crate
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}

#[test]
fn dont_complete_current_use() {
    cov_mark::check!(dont_complete_current_use);
    check(r#"use self::foo$0;"#, expect![[r#""#]]);
    check(
        r#"
mod foo { pub struct S; }
use self::{foo::*, bar$0};
"#,
        expect![[r#"
            st S
            md foo
        "#]],
    );
}

#[test]
fn nested_use_tree() {
    check(
        r#"
mod foo {
    pub mod bar {
        pub struct FooBar;
    }
}
use foo::{bar::$0}
"#,
        expect![[r#"
            st FooBar
        "#]],
    );
    check(
        r#"
mod foo {
    pub mod bar {
        pub struct FooBar;
    }
}
use foo::{$0}
"#,
        expect![[r#"
            kw self
            md bar
        "#]],
    );
}

#[test]
fn deeply_nested_use_tree() {
    check(
        r#"
mod foo {
    pub mod bar {
        pub mod baz {
            pub struct FooBarBaz;
        }
    }
}
use foo::{bar::{baz::$0}}
"#,
        expect![[r#"
            st FooBarBaz
        "#]],
    );
    check(
        r#"
mod foo {
    pub mod bar {
        pub mod baz {
            pub struct FooBarBaz;
        }
    }
}
use foo::{bar::{$0}}
"#,
        expect![[r#"
            kw self
            md baz
        "#]],
    );
}

#[test]
fn plain_qualified_use_tree() {
    check(
        r#"
use foo::$0

mod foo {
    struct Private;
    pub struct Foo;
}
struct Bar;
"#,
        expect![[r#"
            st Foo
        "#]],
    );
}

#[test]
fn self_qualified_use_tree() {
    check(
        r#"
use self::$0

mod foo {}
struct Bar;
"#,
        expect![[r#"
            md foo
            st Bar
        "#]],
    );
}

#[test]
fn super_qualified_use_tree() {
    check(
        r#"
mod bar {
    use super::$0
}

mod foo {}
struct Bar;
"#,
        expect![[r#"
            kw super::
            st Bar
            md bar
            md foo
        "#]],
    );
}

#[test]
fn super_super_qualified_use_tree() {
    check(
        r#"
mod a {
    const A: usize = 0;
    mod b {
        const B: usize = 0;
        mod c { use super::super::$0 }
    }
}
"#,
        expect![[r#"
            kw super::
            md b
            ct A
        "#]],
    );
}

#[test]
fn crate_qualified_use_tree() {
    check(
        r#"
use crate::$0

mod foo {}
struct Bar;
"#,
        expect![[r#"
            md foo
            st Bar
        "#]],
    );
}

#[test]
fn extern_crate_qualified_use_tree() {
    check(
        r#"
//- /lib.rs crate:main deps:other_crate
use other_crate::$0
//- /other_crate/lib.rs crate:other_crate
pub struct Foo;
pub mod foo {}
"#,
        expect![[r#"
            st Foo
            md foo
        "#]],
    );
}

#[test]
fn pub_use_tree() {
    check(
        r#"
pub struct X;
pub mod bar {}
pub use $0;
"#,
        expect![[r#"
            md bar
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}

#[test]
fn use_tree_braces_at_start() {
    check(
        r#"
struct X;
mod bar {}
use {$0};
"#,
        expect![[r#"
            md bar
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}
<commit_msg>Add regression test fo #7222<commit_after>//! Completion tests for use trees.
use expect_test::{expect, Expect};

use crate::tests::completion_list;

fn check(ra_fixture: &str, expect: Expect) {
    let actual = completion_list(ra_fixture);
    expect.assert_eq(&actual)
}

#[test]
fn use_tree_start() {
    cov_mark::check!(only_completes_modules_in_import);
    check(
        r#"
//- /lib.rs crate:main deps:other_crate
use f$0

struct Foo;
mod foo {}
//- /other_crate/lib.rs crate:other_crate
// nothing here
"#,
        expect![[r#"
            md foo
            md other_crate
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}

#[test]
fn dont_complete_current_use() {
    cov_mark::check!(dont_complete_current_use);
    check(r#"use self::foo$0;"#, expect![[r#""#]]);
    check(
        r#"
mod foo { pub struct S; }
use self::{foo::*, bar$0};
"#,
        expect![[r#"
            st S
            md foo
        "#]],
    );
}

#[test]
fn nested_use_tree() {
    check(
        r#"
mod foo {
    pub mod bar {
        pub struct FooBar;
    }
}
use foo::{bar::$0}
"#,
        expect![[r#"
            st FooBar
        "#]],
    );
    check(
        r#"
mod foo {
    pub mod bar {
        pub struct FooBar;
    }
}
use foo::{$0}
"#,
        expect![[r#"
            kw self
            md bar
        "#]],
    );
}

#[test]
fn deeply_nested_use_tree() {
    check(
        r#"
mod foo {
    pub mod bar {
        pub mod baz {
            pub struct FooBarBaz;
        }
    }
}
use foo::{bar::{baz::$0}}
"#,
        expect![[r#"
            st FooBarBaz
        "#]],
    );
    check(
        r#"
mod foo {
    pub mod bar {
        pub mod baz {
            pub struct FooBarBaz;
        }
    }
}
use foo::{bar::{$0}}
"#,
        expect![[r#"
            kw self
            md baz
        "#]],
    );
}

#[test]
fn plain_qualified_use_tree() {
    check(
        r#"
use foo::$0

mod foo {
    struct Private;
    pub struct Foo;
}
struct Bar;
"#,
        expect![[r#"
            st Foo
        "#]],
    );
}

#[test]
fn self_qualified_use_tree() {
    check(
        r#"
use self::$0

mod foo {}
struct Bar;
"#,
        expect![[r#"
            md foo
            st Bar
        "#]],
    );
}

#[test]
fn super_qualified_use_tree() {
    check(
        r#"
mod bar {
    use super::$0
}

mod foo {}
struct Bar;
"#,
        expect![[r#"
            kw super::
            st Bar
            md bar
            md foo
        "#]],
    );
}

#[test]
fn super_super_qualified_use_tree() {
    check(
        r#"
mod a {
    const A: usize = 0;
    mod b {
        const B: usize = 0;
        mod c { use super::super::$0 }
    }
}
"#,
        expect![[r#"
            kw super::
            md b
            ct A
        "#]],
    );
}

#[test]
fn crate_qualified_use_tree() {
    check(
        r#"
use crate::$0

mod foo {}
struct Bar;
"#,
        expect![[r#"
            md foo
            st Bar
        "#]],
    );
}

#[test]
fn extern_crate_qualified_use_tree() {
    check(
        r#"
//- /lib.rs crate:main deps:other_crate
use other_crate::$0
//- /other_crate/lib.rs crate:other_crate
pub struct Foo;
pub mod foo {}
"#,
        expect![[r#"
            st Foo
            md foo
        "#]],
    );
}

#[test]
fn pub_use_tree() {
    check(
        r#"
pub struct X;
pub mod bar {}
pub use $0;
"#,
        expect![[r#"
            md bar
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}

#[test]
fn use_tree_braces_at_start() {
    check(
        r#"
struct X;
mod bar {}
use {$0};
"#,
        expect![[r#"
            md bar
            kw self::
            kw super::
            kw crate::
        "#]],
    );
}

#[test]
fn impl_prefix_does_not_add_fn_snippet() {
    // regression test for 7222
    check(
        r#"
mod foo {
    pub fn bar(x: u32) {}
}
use self::foo::impl$0
"#,
        expect![[r#"
            fn bar fn(u32)
        "#]],
    );
}
<|endoftext|>


<commit_before>use petgraph::graph::NodeIndex;

use std::collections::BTreeMap;
use std::cmp::Ordering;

use libsmt::backends::smtlib2::SMTLib2;
use libsmt::backends::backend::SMTBackend;
use libsmt::logics::qf_abv;

use libsmt::theories::bitvec::OpCodes::*;
use libsmt::theories::core::OpCodes::*;

use r2api::structs::Endian;

use crate::memory::memory::Memory;
use crate::utils::utils::simplify_constant;

#[derive(Copy, Clone, Debug)]
pub struct MemRange {
    start: u64,
    end: u64
}

impl MemRange {
    fn new(start: u64, end: u64) -> MemRange {
        MemRange {
            start: start,
            end: end,
        }
    }

    fn get_width(&self) -> usize {
        (self.end - self.start) as usize * 8
    }

    fn contains(&self, num: u64) -> bool {
        if num >= self.start && num < self.end {
            true
        } else {
            false
        }
    }
}

impl PartialEq for MemRange {
    fn eq(&self, other:&MemRange) -> bool {
        if self.start == other.start && self.end == other.end {
            true
        } else {
            false
        }
    }
}

impl Eq for MemRange {}

impl PartialOrd for MemRange {
    fn partial_cmp(&self, other: &MemRange) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for MemRange {
    fn cmp(&self, other: &MemRange) -> Ordering {
        if self.start == other.start && self.end == other.end {
            Ordering::Equal
        } else if self.start < other.start {
            Ordering::Less
        } else {
            Ordering::Greater
        }
    }
}

#[derive(Clone, Debug)]
pub struct MemBlock {
    range: MemRange,
    solver_idx: Option<NodeIndex>,
}

impl MemBlock {
    pub fn new(m_range: MemRange, solver_idx: Option<NodeIndex>) -> MemBlock {
        MemBlock {
            range: m_range,
            solver_idx: solver_idx,
        }
    }
}

#[derive(Clone, Debug)]
pub struct SegMem {
    addr_width: usize,
    endian: Endian,
    segments: BTreeMap<MemRange, MemBlock>,
}

impl SegMem {
    fn read_segment(&mut self, cov: u64, start: u64, end: u64, low: u64, high: u64, width: u64, e_mem: Option<NodeIndex>, solver: &mut SMTLib2<qf_abv::QF_ABV>) -> NodeIndex {
        let shift = cov;
        let ext   = width - (high - low);

        if let Some(mem) = e_mem {
            let int1 = solver.assert(Extract(high - 1, low), &[mem]);
            let int2 = solver.assert(ZeroExtend(ext), &[int1]);
            let int3 = solver.new_const(Const(shift, width as usize));
            let int4 = solver.assert(BvShl, &[int2, int3]);

            int4
        } else {
            let size = high - low;
            let key = format!("mem_{}_{}", start, size/8);

            let int1 = solver.new_var(Some(&key), qf_abv::bv_sort(size as usize));
            // let int2 = solver.assert(ZeroExtend(ext), &[int1]);
            // let int3 = solver.new_const(Const(shift, width as usize));
            // let int4 = solver.assert(BvShl, &[int2, int3]);

            let r = MemRange::new(start, end);
            let m = MemBlock::new(r, Some(int1));

            self.segments.insert(r, m);

            int1
        }
    }
}

impl Memory for SegMem {
    type VarRef = NodeIndex;

    fn new(address_width: usize, endian: Endian) -> SegMem {
        SegMem {
            addr_width: address_width,
            endian: endian,
            segments: BTreeMap::new(),
        }
    }

    fn init_memory(&mut self, _solver: &mut SMTLib2<qf_abv::QF_ABV>) {
        self.segments = BTreeMap::new();
    }

    fn read(&mut self, addr: NodeIndex, read_size: usize, solver: &mut SMTLib2<qf_abv::QF_ABV>) -> NodeIndex {
        // Assert that address is valid
        let addr = simplify_constant(addr, solver);

        let read_range = MemRange::new(addr, addr+(read_size/8) as u64);

        let mem = self.segments.clone();
        let ranges: Vec<MemRange> = mem.keys().cloned().collect();

        let pos = match ranges.binary_search(&&read_range) {
            Ok(0) | Err(0) => 0,
            Ok(pos) | Err(pos) => pos - 1,
        };

        let mut iterator = ranges.split_at(pos).1.iter().peekable();

        let width = read_range.get_width() as u64;
        let start = read_range.start;
        let end   = read_range.end;

        let mut low:  u64;
        let mut high: u64;

        let mut result = solver.new_const(Const(0, width as usize));

        let mut ptr = start;
        let mut cov;

        while ptr != end {
            cov = (ptr - start)*8;
            if let Some(&current) = iterator.peek() {
                if current.start == start && current.end == end {
                    // current is the mem requested
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    result = node_idx;

                    ptr = end;
                } else if current.start == ptr && current.end <= end {
                    // Use current
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    result = solver.assert(BvOr, &[result, node_idx]);

                    ptr = current.end;
                    iterator.next();
                } else if current.contains(ptr) && current.contains(end) {
                    // extract entire
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    low  = (ptr - current.start)*8;
                    high = (end - current.start)*8;

                    let int = self.read_segment(cov, ptr, end,
                                                low, high, width,
                                                Some(node_idx), solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = end;
                    iterator.next();
                } else if current.contains(ptr) && !current.contains(end) {
                    // extract till end of current
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    low  = (ptr - current.start)*8;
                    high = (current.end - current.start)*8;

                    let int = self.read_segment(cov, ptr, current.end,
                                                low, high, width,
                                                Some(node_idx), solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = current.end;
                    iterator.next();
                } else if current.start < end && current.end >= end {
                    // create free var till current.start
                    low  = 0;
                    high = (current.start - ptr)*8;

                    let int = self.read_segment(cov, ptr, current.start,
                                                low, high, width,
                                                None, solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = current.start;
                } else {
                    // create free var till end
                    low  = 0;
                    high = (end - ptr)*8;

                    let int = self.read_segment(cov, ptr, end,
                                                low, high, width,
                                                None, solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = end;
                }
            } else {
                // create free var till end
                low  = 0;
                high = (end - ptr)*8;

                let int = self.read_segment(cov, ptr, end,
                                            low, high, width,
                                            None, solver);
                result  = solver.assert(BvOr, &[result, int]);

                ptr = end;
            }
        }
        println!("{}", solver.generate_asserts());
        result
    }

    fn write(&mut self, addr: NodeIndex, data: NodeIndex, write_size: usize, solver: &mut SMTLib2<qf_abv::QF_ABV>) {
        let idx = self.read(addr, write_size, solver);
        solver.assert(Cmp, &[idx, data]);
    }
}

mod test {

    #[test]
    fn check_read() {
        use libsmt::backends::smtlib2::{SMTLib2, SMTProc};
        use libsmt::backends::backend::SMTBackend;
        use libsmt::backends::z3::Z3;
        use libsmt::theories::bitvec::OpCodes::Const;
        use libsmt::theories::core::OpCodes::*;
        use libsmt::logics::qf_abv;
        use r2api::structs::Endian;
        use super::{SegMem, Memory};

        let mut z3: Z3 = Default::default();
        let mut solver = SMTLib2::new(Some(qf_abv::QF_ABV));
        let mut mem: SegMem = Memory::new(64, Endian::Big);

        let addr = solver.new_const(Const(0x9000, 64));
        let data = solver.new_const(Const(0x70, 8));
        mem.write(addr, data, 8, &mut solver);

        let addr = solver.new_const(Const(0x9001, 64));
        let data = solver.new_const(Const(0x79, 8));
        mem.write(addr, data, 8, &mut solver);

        let addr = solver.new_const(Const(0x9000, 64));
        let var  = mem.read(addr, 16, &mut solver);

        let c   = solver.new_const(Const(0x7970, 16));
        let cmp = solver.assert(Cmp, &[var, c]);

        println!("{}", solver.generate_asserts());

        panic!("ZZ");
    }
}

<commit_msg>Fix test in Rune<commit_after>use petgraph::graph::NodeIndex;

use std::collections::BTreeMap;
use std::cmp::Ordering;

use libsmt::backends::smtlib2::SMTLib2;
use libsmt::backends::backend::SMTBackend;
use libsmt::logics::qf_abv;

use libsmt::theories::bitvec::OpCodes::*;
use libsmt::theories::core::OpCodes::*;

use r2api::structs::Endian;

use crate::memory::memory::Memory;
use crate::utils::utils::simplify_constant;

#[derive(Copy, Clone, Debug)]
pub struct MemRange {
    start: u64,
    end: u64
}

impl MemRange {
    fn new(start: u64, end: u64) -> MemRange {
        MemRange {
            start: start,
            end: end,
        }
    }

    fn get_width(&self) -> usize {
        (self.end - self.start) as usize * 8
    }

    fn contains(&self, num: u64) -> bool {
        if num >= self.start && num < self.end {
            true
        } else {
            false
        }
    }
}

impl PartialEq for MemRange {
    fn eq(&self, other:&MemRange) -> bool {
        if self.start == other.start && self.end == other.end {
            true
        } else {
            false
        }
    }
}

impl Eq for MemRange {}

impl PartialOrd for MemRange {
    fn partial_cmp(&self, other: &MemRange) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for MemRange {
    fn cmp(&self, other: &MemRange) -> Ordering {
        if self.start == other.start && self.end == other.end {
            Ordering::Equal
        } else if self.start < other.start {
            Ordering::Less
        } else {
            Ordering::Greater
        }
    }
}

#[derive(Clone, Debug)]
pub struct MemBlock {
    range: MemRange,
    solver_idx: Option<NodeIndex>,
}

impl MemBlock {
    pub fn new(m_range: MemRange, solver_idx: Option<NodeIndex>) -> MemBlock {
        MemBlock {
            range: m_range,
            solver_idx: solver_idx,
        }
    }
}

#[derive(Clone, Debug)]
pub struct SegMem {
    addr_width: usize,
    endian: Endian,
    segments: BTreeMap<MemRange, MemBlock>,
}

impl SegMem {
    fn read_segment(&mut self, cov: u64, start: u64, end: u64, low: u64, high: u64, width: u64, e_mem: Option<NodeIndex>, solver: &mut SMTLib2<qf_abv::QF_ABV>) -> NodeIndex {
        let shift = cov;
        let ext   = width - (high - low);

        if let Some(mem) = e_mem {
            let int1 = solver.assert(Extract(high - 1, low), &[mem]);
            let int2 = solver.assert(ZeroExtend(ext), &[int1]);
            let int3 = solver.new_const(Const(shift, width as usize));
            let int4 = solver.assert(BvShl, &[int2, int3]);

            int4
        } else {
            let size = high - low;
            let key = format!("mem_{}_{}", start, size/8);

            let int1 = solver.new_var(Some(&key), qf_abv::bv_sort(size as usize));
            // let int2 = solver.assert(ZeroExtend(ext), &[int1]);
            // let int3 = solver.new_const(Const(shift, width as usize));
            // let int4 = solver.assert(BvShl, &[int2, int3]);

            let r = MemRange::new(start, end);
            let m = MemBlock::new(r, Some(int1));

            self.segments.insert(r, m);

            int1
        }
    }
}

impl Memory for SegMem {
    type VarRef = NodeIndex;

    fn new(address_width: usize, endian: Endian) -> SegMem {
        SegMem {
            addr_width: address_width,
            endian: endian,
            segments: BTreeMap::new(),
        }
    }

    fn init_memory(&mut self, _solver: &mut SMTLib2<qf_abv::QF_ABV>) {
        self.segments = BTreeMap::new();
    }

    fn read(&mut self, addr: NodeIndex, read_size: usize, solver: &mut SMTLib2<qf_abv::QF_ABV>) -> NodeIndex {
        // Assert that address is valid
        let addr = simplify_constant(addr, solver);

        let read_range = MemRange::new(addr, addr+(read_size/8) as u64);

        let mem = self.segments.clone();
        let ranges: Vec<MemRange> = mem.keys().cloned().collect();

        let pos = match ranges.binary_search(&&read_range) {
            Ok(0) | Err(0) => 0,
            Ok(pos) | Err(pos) => pos - 1,
        };

        let mut iterator = ranges.split_at(pos).1.iter().peekable();

        let width = read_range.get_width() as u64;
        let start = read_range.start;
        let end   = read_range.end;

        let mut low:  u64;
        let mut high: u64;

        let mut result = solver.new_const(Const(0, width as usize));

        let mut ptr = start;
        let mut cov;

        while ptr != end {
            cov = (ptr - start)*8;
            if let Some(&current) = iterator.peek() {
                if current.start == start && current.end == end {
                    // current is the mem requested
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    result = node_idx;

                    ptr = end;
                } else if current.start == ptr && current.end <= end {
                    // Use current
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    result = solver.assert(BvOr, &[result, node_idx]);

                    ptr = current.end;
                    iterator.next();
                } else if current.contains(ptr) && current.contains(end) {
                    // extract entire
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    low  = (ptr - current.start)*8;
                    high = (end - current.start)*8;

                    let int = self.read_segment(cov, ptr, end,
                                                low, high, width,
                                                Some(node_idx), solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = end;
                    iterator.next();
                } else if current.contains(ptr) && !current.contains(end) {
                    // extract till end of current
                    let node     = mem.get(&current).unwrap();
                    let node_idx = node.solver_idx.unwrap();

                    low  = (ptr - current.start)*8;
                    high = (current.end - current.start)*8;

                    let int = self.read_segment(cov, ptr, current.end,
                                                low, high, width,
                                                Some(node_idx), solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = current.end;
                    iterator.next();
                } else if current.start < end && current.end >= end {
                    // create free var till current.start
                    low  = 0;
                    high = (current.start - ptr)*8;

                    let int = self.read_segment(cov, ptr, current.start,
                                                low, high, width,
                                                None, solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = current.start;
                } else {
                    // create free var till end
                    low  = 0;
                    high = (end - ptr)*8;

                    let int = self.read_segment(cov, ptr, end,
                                                low, high, width,
                                                None, solver);
                    result  = solver.assert(BvOr, &[result, int]);

                    ptr = end;
                }
            } else {
                // create free var till end
                low  = 0;
                high = (end - ptr)*8;

                let int = self.read_segment(cov, ptr, end,
                                            low, high, width,
                                            None, solver);
                result  = solver.assert(BvOr, &[result, int]);

                ptr = end;
            }
        }
        println!("{}", solver.generate_asserts());
        result
    }

    fn write(&mut self, addr: NodeIndex, data: NodeIndex, write_size: usize, solver: &mut SMTLib2<qf_abv::QF_ABV>) {
        let idx = self.read(addr, write_size, solver);
        solver.assert(Cmp, &[idx, data]);
    }
}

mod test {

    #[test]
    fn check_read() {
        use libsmt::backends::smtlib2::{SMTLib2, SMTProc};
        use libsmt::backends::backend::SMTBackend;
        use libsmt::backends::z3::Z3;
        use libsmt::theories::bitvec::OpCodes::Const;
        use libsmt::theories::core::OpCodes::*;
        use libsmt::logics::qf_abv;
        use r2api::structs::Endian;
        use super::{SegMem, Memory};

        let mut z3: Z3 = Default::default();
        let mut solver = SMTLib2::new(Some(qf_abv::QF_ABV));
        let mut mem: SegMem = Memory::new(64, Endian::Big);

        let addr = solver.new_const(Const(0x9000, 64));
        let data = solver.new_const(Const(0x70, 8));
        mem.write(addr, data, 8, &mut solver);

        let addr = solver.new_const(Const(0x9001, 64));
        let data = solver.new_const(Const(0x79, 8));
        mem.write(addr, data, 8, &mut solver);

        let addr = solver.new_const(Const(0x9000, 64));
        let var  = mem.read(addr, 16, &mut solver);

        let c   = solver.new_const(Const(0x7970, 16));
        let cmp = solver.assert(Cmp, &[var, c]);

        println!("{}", solver.generate_asserts());

    }
}

<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-macos apparently gargantuan mmap requests are ok?

#![feature(phase)]

#[phase(plugin)]
extern crate green;
extern crate native;

use std::task::TaskBuilder;
use native::NativeTaskBuilder;

green_start!(main)

fn main() {
    test();

    let (tx, rx) = channel();
    TaskBuilder::new().native().spawn(proc() {
        tx.send(test());
    });
    rx.recv();
}

#[cfg(not(target_word_size = "64"))]
fn test() {}

#[cfg(target_word_size = "64")]
fn test() {
    let (tx, rx) = channel();
    spawn(proc() {
        TaskBuilder::new().stack_size(1024 * 1024 * 1024 * 64).spawn(proc() {
        });
        tx.send(());
    });

    assert!(rx.recv_opt().is_err());
}
<commit_msg>Remove spawn-stack-too-big.rs, which is too flaky.<commit_after><|endoftext|>


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

#[doc = "Rust wrappers around the raw JS apis"];

use std::libc::types::os::arch::c95::{size_t, c_uint};
use std::libc::{c_char, uintptr_t};
use std::hashmap::HashMap;
use jsapi::*;
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSVAL_NULL;
use ERR;
use name_pool::*;
use std::ptr;
use std::ptr::null;
use result;
use result_obj;
use std::uint;
use std::str::raw::from_c_str;
use std::cast;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = @rt_rsrc;

pub struct rt_rsrc {
    ptr : *JSRuntime,
}

impl Drop for rt_rsrc {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *JSRuntime) -> rt {
    return @rt_rsrc {
        ptr: p
    }
}

impl rt_rsrc {
    #[fixed_stack_segment]
    pub fn cx(@self) -> @Cx {
        unsafe {
            new_context(JS_NewContext(self.ptr, default_stacksize as size_t), self)
        }
    }
}

// FIXME: Is this safe once we have more than one stack segment?
extern fn gc_callback(rt: *JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        do Local::borrow |task: &mut Task| {
            match task.coroutine {
                Some(ref c) => {
                    let start = c.current_stack_segment.start() as uintptr_t;
                    let end = c.current_stack_segment.end() as uintptr_t;
                    JS_SetNativeStackBounds(rt, uint::min(start, end), uint::max(start, end));
                }
                None => {
                    fail!("gc_callback: cannot get stack for JS_SetNativeStackBounds");
                }
            }
        }
    }
}

#[fixed_stack_segment]
pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, gc_callback);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    ptr: *JSContext,
    rt: rt,
    classes: @mut HashMap<~str, @JSClass>,
}

#[unsafe_destructor]
impl Drop for Cx {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *JSContext, rt: rt) -> @Cx {
    return @Cx {
        ptr: ptr,
        rt: rt,
        classes: @mut HashMap::new()
    }
}

impl Cx {
    #[fixed_stack_segment]
    pub fn rooted_obj(@self, obj: *JSObject) -> jsobj {
        let jsobj = @jsobj_rsrc {cx: self, cxptr: self.ptr, ptr: obj};
        unsafe {
            JS_AddObjectRoot(self.ptr, ptr::to_unsafe_ptr(&jsobj.ptr));
        }
        jsobj
    }

    pub fn set_default_options_and_version(@self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    #[fixed_stack_segment]
    pub fn set_options(@self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    #[fixed_stack_segment]
    pub fn set_version(@self, v: i32) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    #[fixed_stack_segment]
    pub fn set_logging_error_reporter(@self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportError);
        }
    }

    #[fixed_stack_segment]
    pub fn set_error_reporter(@self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportfn);
        }
    }

    #[fixed_stack_segment]
    pub fn new_compartment(@self,
                       globclsfn: &fn(@mut NamePool) -> JSClass)
                    -> Result<@mut Compartment,()> {
        unsafe {
            let np = NamePool();
            let globcls = @globclsfn(np);
            let globobj = JS_NewGlobalObject(self.ptr, ptr::to_unsafe_ptr(&*globcls), null());
            result(JS_InitStandardClasses(self.ptr, globobj)).chain(|_ok| {
                let compartment = @mut Compartment {
                    cx: self,
                    name_pool: np,
                    global_funcs: ~[],
                    global_props: ~[],
                    global_class: globcls,
                    global_obj: self.rooted_obj(globobj),
                    global_protos: @mut HashMap::new()
                };
                self.set_cx_private(ptr::to_unsafe_ptr(&*compartment) as *());
                Ok(compartment)
            })
        }
    }

    #[fixed_stack_segment]
    pub fn evaluate_script(@self, glob: jsobj, bytes: ~[u8], filename: ~str, line_num: uint)
                    -> Result<(),()> {
        do bytes.as_imm_buf |bytes_ptr, bytes_len| {
            do filename.to_c_str().with_ref |filename_cstr| {
                let bytes_ptr = bytes_ptr as *c_char;
                let rval: JSVal = JSVAL_NULL;
                debug!("Evaluating script from %s with bytes %?", filename, bytes);
                unsafe {
                    if JS_EvaluateScript(self.ptr, glob.ptr,
                                         bytes_ptr, bytes_len as c_uint,
                                         filename_cstr, line_num as c_uint,
                                         ptr::to_unsafe_ptr(&rval)) == ERR {
                        debug!("...err!");
                        Err(())
                    } else {
                        // we could return the script result but then we'd have
                        // to root it and so forth and, really, who cares?
                        debug!("...ok!");
                        Ok(())
                    }
                }
            }
        }
    }

    pub fn lookup_class_name(@self, s: ~str) ->  @JSClass {
        // FIXME: expect should really take a lambda...
        let error_msg = fmt!("class %s not found in class table", s);
        let name = self.classes.find(&s);
        *(name.expect(error_msg))
    }

    #[fixed_stack_segment]
    pub unsafe fn get_cx_private(@self) -> *() {
        cast::transmute(JS_GetContextPrivate(self.ptr))
    }

    #[fixed_stack_segment]
    pub unsafe fn set_cx_private(@self, data: *()) {
        JS_SetContextPrivate(self.ptr, cast::transmute(data));
    }

    #[fixed_stack_segment]
    pub unsafe fn get_obj_private(@self, obj: *JSObject) -> *() {
        cast::transmute(JS_GetPrivate(obj))
    }

    #[fixed_stack_segment]
    pub unsafe fn set_obj_private(@self, obj: *JSObject, data: *()) {
        JS_SetPrivate(obj, cast::transmute(data));
    }
}

pub extern fn reportError(_cx: *JSContext, msg: *c_char, report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {~"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at %s:%?: %s\n", fname, lineno, msg);
    }
}

// ___________________________________________________________________________
// compartment

pub struct Compartment {
    cx: @Cx,
    name_pool: @mut NamePool,
    global_funcs: ~[@~[JSFunctionSpec]],
    global_props: ~[@~[JSPropertySpec]],
    global_class: @JSClass,
    global_obj: jsobj,
    global_protos: @mut HashMap<~str, jsobj>
}

impl Compartment {
    #[fixed_stack_segment]
    pub fn define_functions(@mut self,
                        specfn: &fn(@mut NamePool) -> ~[JSFunctionSpec])
                     -> Result<(),()> {
        let specvec = @specfn(self.name_pool);
        self.global_funcs.push(specvec);
        do specvec.as_imm_buf |specs, _len| {
            unsafe {
                result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specs))
            }
        }
    }
    #[fixed_stack_segment]
    pub fn define_properties(@mut self, specfn: &fn() -> ~[JSPropertySpec]) -> Result<(),()> {
        let specvec = @specfn();
        self.global_props.push(specvec);
        do specvec.as_imm_buf |specs, _len| {
            unsafe {
                result(JS_DefineProperties(self.cx.ptr, self.global_obj.ptr, specs))
            }
        }
    }
    #[fixed_stack_segment]
    pub fn define_property(@mut self,
                       name: ~str,
                       value: JSVal,
                       getter: JSPropertyOp, setter: JSStrictPropertyOp,
                       attrs: c_uint)
                    -> Result<(),()> {
        unsafe {
            result(JS_DefineProperty(self.cx.ptr,
                                     self.global_obj.ptr,
                                     self.add_name(name),
                                     value,
                                     Some(getter),
                                     Some(setter),
                                     attrs))
        }
    }
    #[fixed_stack_segment]
    pub fn new_object(@mut self, class_name: ~str, proto: *JSObject, parent: *JSObject)
               -> Result<jsobj, ()> {
        unsafe {
            let classptr = self.cx.lookup_class_name(class_name);
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, &*classptr, proto, parent));
            result_obj(obj)
        }
    }
    #[fixed_stack_segment]
    pub fn new_object_with_proto(@mut self, class_name: ~str, proto_name: ~str, parent: *JSObject)
                          -> Result<jsobj, ()> {
        let classptr = self.cx.lookup_class_name(class_name);
        let proto = self.global_protos.find(&proto_name.clone()).expect(
            fmt!("new_object_with_proto: expected to find %s in the proto \
                  table", proto_name));
        unsafe {
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, ptr::to_unsafe_ptr(&*classptr),
                                                      proto.ptr, parent));
            result_obj(obj)
        }
    }
    pub fn get_global_proto(@mut self, name: ~str) -> jsobj {
        let proto = self.global_protos.get(&name);
        *proto
    }
    pub fn stash_global_proto(@mut self, name: ~str, proto: jsobj) {
        let global_protos = self.global_protos;
        if !global_protos.insert(name, proto) {
            fail!(~"Duplicate global prototype registered; you're gonna have a bad time.")
        }
    }
    pub fn register_class(@mut self, class_fn: &fn(x: @mut Compartment) -> JSClass) {
        let classptr = @class_fn(self);
        if !self.cx.classes.insert(
            unsafe { from_c_str(classptr.name) },
            classptr) {
            fail!(~"Duplicate JSClass registered; you're gonna have a bad time.")
        }
    }
    pub fn add_name(@mut self, name: ~str) -> *c_char {
        self.name_pool.add(name.clone())
    }
}

// ___________________________________________________________________________
// objects

pub type jsobj = @jsobj_rsrc;

pub struct jsobj_rsrc {
    cx: @Cx,
    cxptr: *JSContext,
    ptr: *JSObject,
}

#[unsafe_destructor]
impl Drop for jsobj_rsrc {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_RemoveObjectRoot(self.cxptr, ptr::to_unsafe_ptr(&self.ptr));
        }
    }
}

impl jsobj_rsrc {
    fn new_object(&self, cx: @Cx, cxptr: *JSContext, ptr: *JSObject) -> jsobj {
        return @jsobj_rsrc {
            cx: cx,
            cxptr: cxptr,
            ptr: ptr
        }
    }
}

// ___________________________________________________________________________
// random utilities

pub trait to_jsstr {
    fn to_jsstr(self, cx: @Cx) -> *JSString;
}

impl to_jsstr for ~str {
    #[fixed_stack_segment]
    fn to_jsstr(self, cx: @Cx) -> *JSString {
        do self.as_imm_buf |buf, len| {
            unsafe {
                let cbuf = cast::transmute(buf);
                JS_NewStringCopyN(cx.ptr, cbuf, len as size_t)
            }
        }
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::super::global;
    use super::super::jsapi::{JS_GC, JS_GetRuntime};

    #[test]
    #[fixed_stack_segment]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.set_default_options_and_version();
        cx.set_logging_error_reporter();
        cx.new_compartment(global::global_class).chain(|comp| {
            unsafe { JS_GC(JS_GetRuntime(comp.cx.ptr)); }

            comp.define_functions(global::debug_fns);

            let s = ~"debug(22);";
            let bytes = s.as_bytes().to_owned();
            cx.evaluate_script(comp.global_obj, bytes, ~"test", 1u)
        });
    }

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

#[doc = "Rust wrappers around the raw JS apis"];

use std::libc::types::os::arch::c95::{size_t, c_uint};
use std::libc::{c_char, uintptr_t};
use std::hashmap::HashMap;
use jsapi::*;
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSVAL_NULL;
use ERR;
use name_pool::*;
use global::global_class;
use std::ptr;
use std::ptr::null;
use result;
use result_obj;
use std::uint;
use std::str::raw::from_c_str;
use std::cast;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = @rt_rsrc;

pub struct rt_rsrc {
    ptr : *JSRuntime,
}

impl Drop for rt_rsrc {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *JSRuntime) -> rt {
    return @rt_rsrc {
        ptr: p
    }
}

impl rt_rsrc {
    #[fixed_stack_segment]
    pub fn cx(@self) -> @Cx {
        unsafe {
            new_context(JS_NewContext(self.ptr, default_stacksize as size_t), self)
        }
    }
}

// FIXME: Is this safe once we have more than one stack segment?
extern fn gc_callback(rt: *JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        do Local::borrow |task: &mut Task| {
            match task.coroutine {
                Some(ref c) => {
                    let start = c.current_stack_segment.start() as uintptr_t;
                    let end = c.current_stack_segment.end() as uintptr_t;
                    JS_SetNativeStackBounds(rt, uint::min(start, end), uint::max(start, end));
                }
                None => {
                    fail!("gc_callback: cannot get stack for JS_SetNativeStackBounds");
                }
            }
        }
    }
}

#[fixed_stack_segment]
pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, gc_callback);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    ptr: *JSContext,
    rt: rt,
    classes: @mut HashMap<~str, @JSClass>,
}

#[unsafe_destructor]
impl Drop for Cx {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *JSContext, rt: rt) -> @Cx {
    return @Cx {
        ptr: ptr,
        rt: rt,
        classes: @mut HashMap::new()
    }
}

impl Cx {
    #[fixed_stack_segment]
    pub fn rooted_obj(@self, obj: *JSObject) -> jsobj {
        let jsobj = @jsobj_rsrc {cx: self, cxptr: self.ptr, ptr: obj};
        unsafe {
            JS_AddObjectRoot(self.ptr, ptr::to_unsafe_ptr(&jsobj.ptr));
        }
        jsobj
    }

    pub fn set_default_options_and_version(@self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    #[fixed_stack_segment]
    pub fn set_options(@self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    #[fixed_stack_segment]
    pub fn set_version(@self, v: i32) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    #[fixed_stack_segment]
    pub fn set_logging_error_reporter(@self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportError);
        }
    }

    #[fixed_stack_segment]
    pub fn set_error_reporter(@self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportfn);
        }
    }

    #[fixed_stack_segment]
    pub fn new_compartment(@self,
                       globclsfn: &fn(@mut NamePool) -> JSClass)
                    -> Result<@mut Compartment,()> {
        unsafe {
            let np = NamePool();
            let globcls = @globclsfn(np);
            let globobj = JS_NewGlobalObject(self.ptr, ptr::to_unsafe_ptr(&*globcls), null());
            result(JS_InitStandardClasses(self.ptr, globobj)).chain(|_ok| {
                let compartment = @mut Compartment {
                    cx: self,
                    name_pool: np,
                    global_funcs: ~[],
                    global_props: ~[],
                    global_class: globcls,
                    global_obj: self.rooted_obj(globobj),
                    global_protos: @mut HashMap::new()
                };
                self.set_cx_private(ptr::to_unsafe_ptr(&*compartment) as *());
                Ok(compartment)
            })
        }
    }

    #[fixed_stack_segment]
    pub fn new_compartment_with_global(@self, global: *JSObject) -> Result<@mut Compartment,()> {
        let np = NamePool();
        let compartment = @mut Compartment {
            cx: self,
            name_pool: np,
            global_funcs: ~[],
            global_props: ~[],
            global_class: @global_class(np),
            global_obj: self.rooted_obj(global),
            global_protos: @mut HashMap::new()
        };
        unsafe {
            self.set_cx_private(ptr::to_unsafe_ptr(&*compartment) as *());
        }
        Ok(compartment)
    }

    #[fixed_stack_segment]
    pub fn evaluate_script(@self, glob: jsobj, bytes: ~[u8], filename: ~str, line_num: uint)
                    -> Result<(),()> {
        do bytes.as_imm_buf |bytes_ptr, bytes_len| {
            do filename.to_c_str().with_ref |filename_cstr| {
                let bytes_ptr = bytes_ptr as *c_char;
                let rval: JSVal = JSVAL_NULL;
                debug!("Evaluating script from %s with bytes %?", filename, bytes);
                unsafe {
                    if JS_EvaluateScript(self.ptr, glob.ptr,
                                         bytes_ptr, bytes_len as c_uint,
                                         filename_cstr, line_num as c_uint,
                                         ptr::to_unsafe_ptr(&rval)) == ERR {
                        debug!("...err!");
                        Err(())
                    } else {
                        // we could return the script result but then we'd have
                        // to root it and so forth and, really, who cares?
                        debug!("...ok!");
                        Ok(())
                    }
                }
            }
        }
    }

    pub fn lookup_class_name(@self, s: ~str) ->  @JSClass {
        // FIXME: expect should really take a lambda...
        let error_msg = fmt!("class %s not found in class table", s);
        let name = self.classes.find(&s);
        *(name.expect(error_msg))
    }

    #[fixed_stack_segment]
    pub unsafe fn get_cx_private(@self) -> *() {
        cast::transmute(JS_GetContextPrivate(self.ptr))
    }

    #[fixed_stack_segment]
    pub unsafe fn set_cx_private(@self, data: *()) {
        JS_SetContextPrivate(self.ptr, cast::transmute(data));
    }

    #[fixed_stack_segment]
    pub unsafe fn get_obj_private(@self, obj: *JSObject) -> *() {
        cast::transmute(JS_GetPrivate(obj))
    }

    #[fixed_stack_segment]
    pub unsafe fn set_obj_private(@self, obj: *JSObject, data: *()) {
        JS_SetPrivate(obj, cast::transmute(data));
    }
}

pub extern fn reportError(_cx: *JSContext, msg: *c_char, report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {~"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at %s:%?: %s\n", fname, lineno, msg);
    }
}

// ___________________________________________________________________________
// compartment

pub struct Compartment {
    cx: @Cx,
    name_pool: @mut NamePool,
    global_funcs: ~[@~[JSFunctionSpec]],
    global_props: ~[@~[JSPropertySpec]],
    global_class: @JSClass,
    global_obj: jsobj,
    global_protos: @mut HashMap<~str, jsobj>
}

impl Compartment {
    #[fixed_stack_segment]
    pub fn define_functions(@mut self,
                        specfn: &fn(@mut NamePool) -> ~[JSFunctionSpec])
                     -> Result<(),()> {
        let specvec = @specfn(self.name_pool);
        self.global_funcs.push(specvec);
        do specvec.as_imm_buf |specs, _len| {
            unsafe {
                result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specs))
            }
        }
    }
    #[fixed_stack_segment]
    pub fn define_properties(@mut self, specfn: &fn() -> ~[JSPropertySpec]) -> Result<(),()> {
        let specvec = @specfn();
        self.global_props.push(specvec);
        do specvec.as_imm_buf |specs, _len| {
            unsafe {
                result(JS_DefineProperties(self.cx.ptr, self.global_obj.ptr, specs))
            }
        }
    }
    #[fixed_stack_segment]
    pub fn define_property(@mut self,
                       name: ~str,
                       value: JSVal,
                       getter: JSPropertyOp, setter: JSStrictPropertyOp,
                       attrs: c_uint)
                    -> Result<(),()> {
        unsafe {
            result(JS_DefineProperty(self.cx.ptr,
                                     self.global_obj.ptr,
                                     self.add_name(name),
                                     value,
                                     Some(getter),
                                     Some(setter),
                                     attrs))
        }
    }
    #[fixed_stack_segment]
    pub fn new_object(@mut self, class_name: ~str, proto: *JSObject, parent: *JSObject)
               -> Result<jsobj, ()> {
        unsafe {
            let classptr = self.cx.lookup_class_name(class_name);
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, &*classptr, proto, parent));
            result_obj(obj)
        }
    }
    #[fixed_stack_segment]
    pub fn new_object_with_proto(@mut self, class_name: ~str, proto_name: ~str, parent: *JSObject)
                          -> Result<jsobj, ()> {
        let classptr = self.cx.lookup_class_name(class_name);
        let proto = self.global_protos.find(&proto_name.clone()).expect(
            fmt!("new_object_with_proto: expected to find %s in the proto \
                  table", proto_name));
        unsafe {
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, ptr::to_unsafe_ptr(&*classptr),
                                                      proto.ptr, parent));
            result_obj(obj)
        }
    }
    pub fn get_global_proto(@mut self, name: ~str) -> jsobj {
        let proto = self.global_protos.get(&name);
        *proto
    }
    pub fn stash_global_proto(@mut self, name: ~str, proto: jsobj) {
        let global_protos = self.global_protos;
        if !global_protos.insert(name, proto) {
            fail!(~"Duplicate global prototype registered; you're gonna have a bad time.")
        }
    }
    pub fn register_class(@mut self, class_fn: &fn(x: @mut Compartment) -> JSClass) {
        let classptr = @class_fn(self);
        if !self.cx.classes.insert(
            unsafe { from_c_str(classptr.name) },
            classptr) {
            fail!(~"Duplicate JSClass registered; you're gonna have a bad time.")
        }
    }
    pub fn add_name(@mut self, name: ~str) -> *c_char {
        self.name_pool.add(name.clone())
    }
}

// ___________________________________________________________________________
// objects

pub type jsobj = @jsobj_rsrc;

pub struct jsobj_rsrc {
    cx: @Cx,
    cxptr: *JSContext,
    ptr: *JSObject,
}

#[unsafe_destructor]
impl Drop for jsobj_rsrc {
    #[fixed_stack_segment]
    fn drop(&self) {
        unsafe {
            JS_RemoveObjectRoot(self.cxptr, ptr::to_unsafe_ptr(&self.ptr));
        }
    }
}

impl jsobj_rsrc {
    fn new_object(&self, cx: @Cx, cxptr: *JSContext, ptr: *JSObject) -> jsobj {
        return @jsobj_rsrc {
            cx: cx,
            cxptr: cxptr,
            ptr: ptr
        }
    }
}

// ___________________________________________________________________________
// random utilities

pub trait to_jsstr {
    fn to_jsstr(self, cx: @Cx) -> *JSString;
}

impl to_jsstr for ~str {
    #[fixed_stack_segment]
    fn to_jsstr(self, cx: @Cx) -> *JSString {
        do self.as_imm_buf |buf, len| {
            unsafe {
                let cbuf = cast::transmute(buf);
                JS_NewStringCopyN(cx.ptr, cbuf, len as size_t)
            }
        }
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::super::global;
    use super::super::jsapi::{JS_GC, JS_GetRuntime};

    #[test]
    #[fixed_stack_segment]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.set_default_options_and_version();
        cx.set_logging_error_reporter();
        cx.new_compartment(global::global_class).chain(|comp| {
            unsafe { JS_GC(JS_GetRuntime(comp.cx.ptr)); }

            comp.define_functions(global::debug_fns);

            let s = ~"debug(22);";
            let bytes = s.as_bytes().to_owned();
            cx.evaluate_script(comp.global_obj, bytes, ~"test", 1u)
        });
    }

}
<|endoftext|>


<commit_before>//! Internal `#[repr(simd)]` types

#![rustfmt::skip]
#![allow(non_camel_case_types)]

macro_rules! simd_ty {
    ($id:ident [$ety:ident]: $($elem_ty:ident),* | $($elem_name:ident),*) => {
        #[repr(simd)]
        #[derive(Copy, Clone, Debug, PartialEq)]
        pub(crate) struct $id($(pub $elem_ty),*);

        #[allow(clippy::use_self)]
        impl $id {
            #[inline]
            pub(crate) const fn new($($elem_name: $elem_ty),*) -> Self {
                $id($($elem_name),*)
            }

            #[inline]
            pub(crate) const fn splat(value: $ety) -> Self {
                $id($({
                    #[allow(non_camel_case_types, dead_code)]
                    struct $elem_name;
                    value
                }),*)
            }

            #[inline]
            pub(crate) fn extract(self, index: usize) -> $ety {
                unsafe {
                    crate::core_arch::simd_llvm::simd_extract(self, index as u32)
                }
            }
        }
    }
}

macro_rules! simd_m_ty {
    ($id:ident [$ety:ident]: $($elem_ty:ident),* | $($elem_name:ident),*) => {
        #[repr(simd)]
        #[derive(Copy, Clone, Debug, PartialEq)]
        pub(crate) struct $id($(pub $elem_ty),*);

        #[allow(clippy::use_self)]
        impl $id {
            #[inline]
            const fn bool_to_internal(x: bool) -> $ety {
                [0 as $ety, !(0 as $ety)][x as usize]
            }

            #[inline]
            pub(crate) const fn new($($elem_name: bool),*) -> Self {
                $id($(Self::bool_to_internal($elem_name)),*)
            }

            #[inline]
            pub(crate) const fn splat(value: bool) -> Self {
                $id($({
                    #[allow(non_camel_case_types, dead_code)]
                    struct $elem_name;
                    Self::bool_to_internal(value)
                }),*)
            }

            #[inline]
            pub(crate) fn extract(self, index: usize) -> bool {
                let r: $ety = unsafe {
                    crate::core_arch::simd_llvm::simd_extract(self, index as u32)
                };
                r != 0
            }
        }
    }
}

// 16-bit wide types:

simd_ty!(u8x2[u8]: u8, u8 | x0, x1);
simd_ty!(i8x2[i8]: i8, i8 | x0, x1);

// 32-bit wide types:

simd_ty!(u8x4[u8]: u8, u8, u8, u8 | x0, x1, x2, x3);
simd_ty!(u16x2[u16]: u16, u16 | x0, x1);

simd_ty!(i8x4[i8]: i8, i8, i8, i8 | x0, x1, x2, x3);
simd_ty!(i16x2[i16]: i16, i16 | x0, x1);

// 64-bit wide types:

simd_ty!(u8x8[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u16x4[u16]: u16, u16, u16, u16 | x0, x1, x2, x3);
simd_ty!(u32x2[u32]: u32, u32 | x0, x1);
simd_ty!(u64x1[u64]: u64 | x1);

simd_ty!(i8x8[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i16x4[i16]: i16, i16, i16, i16 | x0, x1, x2, x3);
simd_ty!(i32x2[i32]: i32, i32 | x0, x1);
simd_ty!(i64x1[i64]: i64 | x1);

simd_ty!(f32x2[f32]: f32, f32 | x0, x1);

// 128-bit wide types:

simd_ty!(u8x16[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(u16x8[u16]:
         u16, u16, u16, u16, u16, u16, u16, u16
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u32x4[u32]: u32, u32, u32, u32 | x0, x1, x2, x3);
simd_ty!(u64x2[u64]: u64, u64 | x0, x1);

simd_ty!(i8x16[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(i16x8[i16]:
         i16, i16, i16, i16, i16, i16, i16, i16
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i32x4[i32]: i32, i32, i32, i32 | x0, x1, x2, x3);
simd_ty!(i64x2[i64]: i64, i64 | x0, x1);

simd_ty!(f32x4[f32]: f32, f32, f32, f32 | x0, x1, x2, x3);
simd_ty!(f64x2[f64]: f64, f64 | x0, x1);

simd_m_ty!(m8x16[i8]:
           i8, i8, i8, i8, i8, i8, i8, i8,
           i8, i8, i8, i8, i8, i8, i8, i8
           | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_m_ty!(m16x8[i16]:
           i16, i16, i16, i16, i16, i16, i16, i16
           | x0, x1, x2, x3, x4, x5, x6, x7);
simd_m_ty!(m32x4[i32]: i32, i32, i32, i32 | x0, x1, x2, x3);
simd_m_ty!(m64x2[i64]: i64, i64 | x0, x1);

// 256-bit wide types:

simd_ty!(u8x32[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15,
         x16, x17, x18, x19, x20, x21, x22, x23,
         x24, x25, x26, x27, x28, x29, x30, x31
);
simd_ty!(u16x16[u16]:
         u16, u16, u16, u16, u16, u16, u16, u16,
         u16, u16, u16, u16, u16, u16, u16, u16
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(u32x8[u32]:
         u32, u32, u32, u32, u32, u32, u32, u32
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u64x4[u64]: u64, u64, u64, u64 | x0, x1, x2, x3);

simd_ty!(i8x32[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15,
         x16, x17, x18, x19, x20, x21, x22, x23,
         x24, x25, x26, x27, x28, x29, x30, x31
);
simd_ty!(i16x16[i16]:
         i16, i16, i16, i16, i16, i16, i16, i16,
         i16, i16, i16, i16, i16, i16, i16, i16
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(i32x8[i32]:
         i32, i32, i32, i32, i32, i32, i32, i32
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i64x4[i64]: i64, i64, i64, i64 | x0, x1, x2, x3);

simd_ty!(f32x8[f32]:
         f32, f32, f32, f32, f32, f32, f32, f32 |
         x0, x1, x2, x3, x4, x5, x6, x7);

// 512-bit wide types:

simd_ty!(i32x16[i32]:
         i32, i32, i32, i32, i32, i32, i32, i32,
         i32, i32, i32, i32, i32, i32, i32, i32
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15);

simd_ty!(i64x8[i64]:
         i64, i64, i64, i64, i64, i64, i64, i64
         | x0, x1, x2, x3, x4, x5, x6, x7);
<commit_msg>Always inline splat and extract<commit_after>//! Internal `#[repr(simd)]` types

#![rustfmt::skip]
#![allow(non_camel_case_types)]

macro_rules! simd_ty {
    ($id:ident [$ety:ident]: $($elem_ty:ident),* | $($elem_name:ident),*) => {
        #[repr(simd)]
        #[derive(Copy, Clone, Debug, PartialEq)]
        pub(crate) struct $id($(pub $elem_ty),*);

        #[allow(clippy::use_self)]
        impl $id {
            #[inline]
            pub(crate) const fn new($($elem_name: $elem_ty),*) -> Self {
                $id($($elem_name),*)
            }
            // FIXME: Workaround rust@60637
            #[inline(always)]
            pub(crate) const fn splat(value: $ety) -> Self {
                $id($({
                    #[allow(non_camel_case_types, dead_code)]
                    struct $elem_name;
                    value
                }),*)
            }

            // FIXME: Workaround rust@60637
            #[inline(always)]
            pub(crate) fn extract(self, index: usize) -> $ety {
                unsafe {
                    crate::core_arch::simd_llvm::simd_extract(self, index as u32)
                }
            }
        }
    }
}

macro_rules! simd_m_ty {
    ($id:ident [$ety:ident]: $($elem_ty:ident),* | $($elem_name:ident),*) => {
        #[repr(simd)]
        #[derive(Copy, Clone, Debug, PartialEq)]
        pub(crate) struct $id($(pub $elem_ty),*);

        #[allow(clippy::use_self)]
        impl $id {
            #[inline]
            const fn bool_to_internal(x: bool) -> $ety {
                [0 as $ety, !(0 as $ety)][x as usize]
            }

            #[inline]
            pub(crate) const fn new($($elem_name: bool),*) -> Self {
                $id($(Self::bool_to_internal($elem_name)),*)
            }

            // FIXME: Workaround rust@60637
            #[inline(always)]
            pub(crate) const fn splat(value: bool) -> Self {
                $id($({
                    #[allow(non_camel_case_types, dead_code)]
                    struct $elem_name;
                    Self::bool_to_internal(value)
                }),*)
            }

            // FIXME: Workaround rust@60637
            #[inline(always)]
            pub(crate) fn extract(self, index: usize) -> bool {
                let r: $ety = unsafe {
                    crate::core_arch::simd_llvm::simd_extract(self, index as u32)
                };
                r != 0
            }
        }
    }
}

// 16-bit wide types:

simd_ty!(u8x2[u8]: u8, u8 | x0, x1);
simd_ty!(i8x2[i8]: i8, i8 | x0, x1);

// 32-bit wide types:

simd_ty!(u8x4[u8]: u8, u8, u8, u8 | x0, x1, x2, x3);
simd_ty!(u16x2[u16]: u16, u16 | x0, x1);

simd_ty!(i8x4[i8]: i8, i8, i8, i8 | x0, x1, x2, x3);
simd_ty!(i16x2[i16]: i16, i16 | x0, x1);

// 64-bit wide types:

simd_ty!(u8x8[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u16x4[u16]: u16, u16, u16, u16 | x0, x1, x2, x3);
simd_ty!(u32x2[u32]: u32, u32 | x0, x1);
simd_ty!(u64x1[u64]: u64 | x1);

simd_ty!(i8x8[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i16x4[i16]: i16, i16, i16, i16 | x0, x1, x2, x3);
simd_ty!(i32x2[i32]: i32, i32 | x0, x1);
simd_ty!(i64x1[i64]: i64 | x1);

simd_ty!(f32x2[f32]: f32, f32 | x0, x1);

// 128-bit wide types:

simd_ty!(u8x16[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(u16x8[u16]:
         u16, u16, u16, u16, u16, u16, u16, u16
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u32x4[u32]: u32, u32, u32, u32 | x0, x1, x2, x3);
simd_ty!(u64x2[u64]: u64, u64 | x0, x1);

simd_ty!(i8x16[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(i16x8[i16]:
         i16, i16, i16, i16, i16, i16, i16, i16
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i32x4[i32]: i32, i32, i32, i32 | x0, x1, x2, x3);
simd_ty!(i64x2[i64]: i64, i64 | x0, x1);

simd_ty!(f32x4[f32]: f32, f32, f32, f32 | x0, x1, x2, x3);
simd_ty!(f64x2[f64]: f64, f64 | x0, x1);

simd_m_ty!(m8x16[i8]:
           i8, i8, i8, i8, i8, i8, i8, i8,
           i8, i8, i8, i8, i8, i8, i8, i8
           | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_m_ty!(m16x8[i16]:
           i16, i16, i16, i16, i16, i16, i16, i16
           | x0, x1, x2, x3, x4, x5, x6, x7);
simd_m_ty!(m32x4[i32]: i32, i32, i32, i32 | x0, x1, x2, x3);
simd_m_ty!(m64x2[i64]: i64, i64 | x0, x1);

// 256-bit wide types:

simd_ty!(u8x32[u8]:
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8,
         u8, u8, u8, u8, u8, u8, u8, u8
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15,
         x16, x17, x18, x19, x20, x21, x22, x23,
         x24, x25, x26, x27, x28, x29, x30, x31
);
simd_ty!(u16x16[u16]:
         u16, u16, u16, u16, u16, u16, u16, u16,
         u16, u16, u16, u16, u16, u16, u16, u16
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(u32x8[u32]:
         u32, u32, u32, u32, u32, u32, u32, u32
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(u64x4[u64]: u64, u64, u64, u64 | x0, x1, x2, x3);

simd_ty!(i8x32[i8]:
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8,
         i8, i8, i8, i8, i8, i8, i8, i8
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15,
         x16, x17, x18, x19, x20, x21, x22, x23,
         x24, x25, x26, x27, x28, x29, x30, x31
);
simd_ty!(i16x16[i16]:
         i16, i16, i16, i16, i16, i16, i16, i16,
         i16, i16, i16, i16, i16, i16, i16, i16
         | x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15
);
simd_ty!(i32x8[i32]:
         i32, i32, i32, i32, i32, i32, i32, i32
         | x0, x1, x2, x3, x4, x5, x6, x7);
simd_ty!(i64x4[i64]: i64, i64, i64, i64 | x0, x1, x2, x3);

simd_ty!(f32x8[f32]:
         f32, f32, f32, f32, f32, f32, f32, f32 |
         x0, x1, x2, x3, x4, x5, x6, x7);

// 512-bit wide types:

simd_ty!(i32x16[i32]:
         i32, i32, i32, i32, i32, i32, i32, i32,
         i32, i32, i32, i32, i32, i32, i32, i32
         | x0, x1, x2, x3, x4, x5, x6, x7,
         x8, x9, x10, x11, x12, x13, x14, x15);

simd_ty!(i64x8[i64]:
         i64, i64, i64, i64, i64, i64, i64, i64
         | x0, x1, x2, x3, x4, x5, x6, x7);
<|endoftext|>


<commit_before>use std::fmt;

/// A UTF-16 encoded, growable string.
///
/// # Examples
///
/// let mut string16 = String16::from("Übung");
/// string16.push('ä');
#[derive(Clone, Default, PartialEq)]
pub struct String16 {
    utf16: Vec<u16>,
}

impl String16 {
    /// Creates a new empty `String16`.
    pub fn new() -> Self {
        String16 { utf16: vec![] }
    }

    /// Returns the length of this `String16`, in bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// let a = String16::from("Übung");
    ///
    /// assert_eq!(a.len(), 5);
    #[inline]
    pub fn len(&self) -> usize {
        self.utf16.len()
    }

    /// /// Returns a slice of [`u16`]s bytes that were attempted to convert to a `String`.
    pub fn as_bytes(&self) -> &[u16] {
        &self.utf16
    }

    /// Returns a mutable slice of [`u16`]s bytes that were attempted to convert to a `String`.
    pub fn as_bytes_mut(&mut self) -> &mut [u16] {
        &mut self.utf16
    }

    /// Inserts a string slice into this `String16` at a byte position.
    pub fn insert_str(&mut self, idx: usize, string: &str) {
        let mut counter = idx;
        for u in string.encode_utf16() {
            self.utf16.insert(counter, u);
            counter += 1;
        }
    }

    /// Appends a given string slice onto the end of this `String16`.
    pub fn push(&mut self, ch: char) {
        self.utf16.push(ch as u16)
    }

    /// Removes a [`char`] from this `String16` at a byte position and returns it.
    pub fn remove(&mut self, idx: usize) {
        self.utf16.remove(idx);
    }

    /// Returns `true` if this `String16` has a length of zero, and `false` otherwise.
    pub fn is_empty(&self) -> bool {
        self.utf16.is_empty()
    }

    // Returns `true` if this `String16` ends with the given string slice, and `false` otherwise.
    pub fn ends_with(&self, pat: &str) -> bool {
        self.as_string().ends_with(pat)
    }

    /// Truncates this `String16`, removing all contents.
    pub fn clear(&mut self) {
        self.utf16.clear()
    }

    /// Returns a string part begins with the `start`and ends with the `end` index.
    pub fn get_string(&self, start: usize, end: usize) -> Option<String> {
        self.utf16.get(start..end).map(String::from_utf16_lossy)
    }

    /// Converts the `String16` value to a String.
    pub fn as_string(&self) -> String {
        String::from_utf16_lossy(&self.utf16)
    }
}

impl From<&str> for String16 {
    fn from(s: &str) -> Self {
        String16 {
            utf16: s.encode_utf16().collect(),
        }
    }
}

impl From<String> for String16 {
    fn from(string: String) -> Self {
        String16 {
            utf16: string.encode_utf16().collect(),
        }
    }
}

impl fmt::Debug for String16 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "String16 {}", self.as_string())
    }
}

impl fmt::Display for String16 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn from_string() {
        let string16 = String16::from(String::from("Übung"));
        assert_eq!(string16.len(), 5);

        let string16 = String16::from(String::from("World"));
        assert_eq!(string16.len(), 5);
    }

    #[test]
    fn from_str() {
        let string16 = String16::from("Übung");
        assert_eq!(string16.len(), 5);

        let string16 = String16::from("World");
        assert_eq!(string16.len(), 5);
    }
}
<commit_msg>Support non-BMP in String16::push<commit_after>use std::fmt;

/// A UTF-16 encoded, growable string.
///
/// # Examples
///
/// let mut string16 = String16::from("Übung");
/// string16.push('ä');
#[derive(Clone, Default, PartialEq)]
pub struct String16 {
    utf16: Vec<u16>,
}

impl String16 {
    /// Creates a new empty `String16`.
    pub fn new() -> Self {
        String16 { utf16: vec![] }
    }

    /// Returns the length of this `String16`, in bytes.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// let a = String16::from("Übung");
    ///
    /// assert_eq!(a.len(), 5);
    #[inline]
    pub fn len(&self) -> usize {
        self.utf16.len()
    }

    /// /// Returns a slice of [`u16`]s bytes that were attempted to convert to a `String`.
    pub fn as_bytes(&self) -> &[u16] {
        &self.utf16
    }

    /// Returns a mutable slice of [`u16`]s bytes that were attempted to convert to a `String`.
    pub fn as_bytes_mut(&mut self) -> &mut [u16] {
        &mut self.utf16
    }

    /// Inserts a string slice into this `String16` at a byte position.
    pub fn insert_str(&mut self, idx: usize, string: &str) {
        let mut counter = idx;
        for u in string.encode_utf16() {
            self.utf16.insert(counter, u);
            counter += 1;
        }
    }

    /// Appends a given char onto the end of this `String16`.
    pub fn push(&mut self, ch: char) {
        let mut buf = [0; 2];

        for part in ch.encode_utf16(&mut buf) {
            self.utf16.push(*part)
        }
    }

    /// Removes a [`char`] from this `String16` at a byte position and returns it.
    pub fn remove(&mut self, idx: usize) {
        self.utf16.remove(idx);
    }

    /// Returns `true` if this `String16` has a length of zero, and `false` otherwise.
    pub fn is_empty(&self) -> bool {
        self.utf16.is_empty()
    }

    // Returns `true` if this `String16` ends with the given string slice, and `false` otherwise.
    pub fn ends_with(&self, pat: &str) -> bool {
        self.as_string().ends_with(pat)
    }

    /// Truncates this `String16`, removing all contents.
    pub fn clear(&mut self) {
        self.utf16.clear()
    }

    /// Returns a string part begins with the `start`and ends with the `end` index.
    pub fn get_string(&self, start: usize, end: usize) -> Option<String> {
        self.utf16.get(start..end).map(String::from_utf16_lossy)
    }

    /// Converts the `String16` value to a String.
    pub fn as_string(&self) -> String {
        String::from_utf16_lossy(&self.utf16)
    }
}

impl From<&str> for String16 {
    fn from(s: &str) -> Self {
        String16 {
            utf16: s.encode_utf16().collect(),
        }
    }
}

impl From<String> for String16 {
    fn from(string: String) -> Self {
        String16 {
            utf16: string.encode_utf16().collect(),
        }
    }
}

impl fmt::Debug for String16 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "String16 {}", self.as_string())
    }
}

impl fmt::Display for String16 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn from_string() {
        let string16 = String16::from(String::from("Übung"));
        assert_eq!(string16.len(), 5);

        let string16 = String16::from(String::from("World"));
        assert_eq!(string16.len(), 5);
    }

    #[test]
    fn from_str() {
        let string16 = String16::from("Übung");
        assert_eq!(string16.len(), 5);

        let string16 = String16::from("World");
        assert_eq!(string16.len(), 5);
    }

    #[test]
    fn push() {
        // Single-u16 encoded char
        let mut string16 = String16::from("Fo");
        string16.push('o');
        assert_eq!(string16, String16::from("Foo"));

        // Two-u16 encoded char
        let mut string16 = String16::from("Bar");
        string16.push('𝕊');
        assert_eq!(string16, String16::from("Bar𝕊"));
    }
}
<|endoftext|>


<commit_before>#![feature(fs_walk)]

use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::path::Path;

// A simple implementation of `% cat path`
fn cat(path: &Path) -> io::Result<String> {
    let mut f = try!(File::open(path));
    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

// A simple implementation of `% echo s > path`
fn echo(s: &str, path: &Path) -> io::Result<()> {
    let mut f = try!(File::create(path));

    f.write_all(s.as_bytes())
}

// A simple implementation of `% touch path` (ignores existing files)
fn touch(path: &Path) -> io::Result<()> {
    match OpenOptions::new().create(true).open(path) {
        Ok(_) => Ok(()),
        Err(e) => Err(e),
    }
}

fn main() {
    println!("`mkdir a`");
    // Create a directory, returns `io::Result<()>`
    match fs::create_dir(&Path::new("a")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(_) => {},
    }

    println!("`echo hello > a/b.txt`");
    // The previous match can be simplified using the `unwrap_or_else` method
    echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`mkdir -p a/c/d`");
    // Recursively create a directory, returns `io::Result<()>`
    fs::create_dir_all(&Path::new("a/c/d")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`touch a/c/e.txt`");
    touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`ln -s ../b.txt a/c/b.txt`");
    // Create a symbolic link, returns `io::Result<()>`
    fs::soft_link(&Path::new("../b.txt"),
                &Path::new("a/c/b.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`cat a/c/b.txt`");
    match cat(&Path::new("a/c/b.txt")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(s) => println!("> {}", s),
    }

    println!("`ls a`");
    // Read the contents of a directory, returns `io::Result<Vec<Path>>`
    match fs::read_dir(&Path::new("a")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(paths) => for path in paths {
            println!("> {:?}", path.unwrap().path());
        },
    }

    println!("`walk a`");
    // Recursively walk over the contents of a directory, returns
    // `Directories`, which implements the `Iterator<Path> trait
    match fs::walk_dir(&Path::new("a")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(paths) => for path in paths {
            println!("> {:?}", path.unwrap().path());
        },
    }

    println!("`rm a/c/e.txt`");
    // Remove a file, returns `io::Result<()>`
    fs::remove_file(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`rmdir a/c/d`");
    // Remove an empty directory, returns `io::Result<()>`
    fs::remove_dir(&Path::new("a/c/d")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });
}
<commit_msg>Fix warning soft_link warning. Remove unnecessary Paths<commit_after>#![feature(fs_walk)]

use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::os::unix;
use std::path::Path;

// A simple implementation of `% cat path`
fn cat(path: &Path) -> io::Result<String> {
    let mut f = try!(File::open(path));
    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

// A simple implementation of `% echo s > path`
fn echo(s: &str, path: &Path) -> io::Result<()> {
    let mut f = try!(File::create(path));

    f.write_all(s.as_bytes())
}

// A simple implementation of `% touch path` (ignores existing files)
fn touch(path: &Path) -> io::Result<()> {
    match OpenOptions::new().create(true).open(path) {
        Ok(_) => Ok(()),
        Err(e) => Err(e),
    }
}

fn main() {
    println!("`mkdir a`");
    // Create a directory, returns `io::Result<()>`
    match fs::create_dir("a") {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(_) => {},
    }

    println!("`echo hello > a/b.txt`");
    // The previous match can be simplified using the `unwrap_or_else` method
    echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`mkdir -p a/c/d`");
    // Recursively create a directory, returns `io::Result<()>`
    fs::create_dir_all("a/c/d").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`touch a/c/e.txt`");
    touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`ln -s ../b.txt a/c/b.txt`");
    // Create a symbolic link, returns `io::Result<()>`
    if cfg!(target_family = "unix") {
        unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
        });
    }

    println!("`cat a/c/b.txt`");
    match cat(&Path::new("a/c/b.txt")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(s) => println!("> {}", s),
    }

    println!("`ls a`");
    // Read the contents of a directory, returns `io::Result<Vec<Path>>`
    match fs::read_dir("a") {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(paths) => for path in paths {
            println!("> {:?}", path.unwrap().path());
        },
    }

    println!("`walk a`");
    // Recursively walk over the contents of a directory, returns
    // `Directories`, which implements the `Iterator<Path> trait
    match fs::walk_dir("a") {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(paths) => for path in paths {
            println!("> {:?}", path.unwrap().path());
        },
    }

    println!("`rm a/c/e.txt`");
    // Remove a file, returns `io::Result<()>`
    fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`rmdir a/c/d`");
    // Remove an empty directory, returns `io::Result<()>`
    fs::remove_dir("a/c/d").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });
}
<|endoftext|>


<commit_before>#[macro_export]
#[doc(hidden)]
macro_rules! seq_parser_impl {
    (; $name: ident $($tt: tt)*) => {
        $name { $($tt)* }
    };
    (_ : $first_parser: expr; $name: ident $($tt: tt)*) => {
        $name { $($tt)* }
    };
    ($first_field: ident : $first_parser: expr; $name: ident $($tt: tt)*) => {
        seq_parser_impl!(; $name $($tt)* $first_field : $first_field,)
    };
    (_ : $first_parser: expr, $($field: ident : $parser: expr),+; $name: ident $($tt: tt)*) => {
        seq_parser_impl!( $($field : $parser),+; $name $($tt)* )
    };
    ($first_field: ident : $first_parser: expr, $($field: ident : $parser: expr),+; $name: ident $($tt: tt)*) => {
        seq_parser_impl!( $($field : $parser),+; $name $($tt)* $first_field: $first_field, )
    };
}

#[macro_export]
macro_rules! seq_parser {
    ($name: ident { $($field: ident : $parser: expr),* }) => {
        ( $($parser),* )
            .map(|( $($field),* )|
                seq_parser_impl!($($field : $parser),*; $name )
            )
    }
}
struct Test {
    a: i32,
    b: i32,
}
fn main() {
    seq_parser!(Test { a: 1, b: 2 });
}<commit_msg>Delete spurious test.rs file<commit_after><|endoftext|>


<commit_before>//!RGB types, spaces and standards.

use float::Float;
use core::any::Any;

use {Component, Yxy};
use white_point::WhitePoint;

use encoding::{Linear, TransferFn};

pub use self::rgb::{Rgb, Rgba};

//mod linear;
mod rgb;

///Nonlinear sRGB.
pub type Srgb<T = f32> = Rgb<::encoding::Srgb, T>;
///Nonlinear sRGB with an alpha component.
pub type Srgba<T = f32> = Rgba<::encoding::Srgb, T>;

///Linear sRGB.
pub type LinSrgb<T = f32> = Rgb<Linear<::encoding::Srgb>, T>;
///Linear sRGB with an alpha component.
pub type LinSrgba<T = f32> = Rgba<Linear<::encoding::Srgb>, T>;

/// Gamma 2.2 encoded sRGB.
pub type GammaSrgb<T = f32> = Rgb<::encoding::Gamma<::encoding::Srgb>, T>;
/// Gamma 2.2 encoded sRGB with an alpha component.
pub type GammaSrgba<T = f32> = Rgba<::encoding::Gamma<::encoding::Srgb>, T>;

///An RGB space and a transfer function.
pub trait RgbStandard {
    ///The RGB color space.
    type Space: RgbSpace;

    ///The transfer function for the color components.
    type TransferFn: TransferFn;
}

impl<S: RgbSpace, T: TransferFn> RgbStandard for (S, T) {
    type Space = S;
    type TransferFn = T;
}

impl<P: Primaries, W: WhitePoint, T: TransferFn> RgbStandard for (P, W, T) {
    type Space = (P, W);
    type TransferFn = T;
}

///A set of primaries and a white point.
pub trait RgbSpace {
    ///The primaries of the RGB color space.
    type Primaries: Primaries;

    ///The white point of the RGB color space.
    type WhitePoint: WhitePoint;
}

impl<P: Primaries, W: WhitePoint> RgbSpace for (P, W) {
    type Primaries = P;
    type WhitePoint = W;
}

///Represents the red, green and blue primaries of an RGB space.
pub trait Primaries: Any {
    ///Primary red.
    fn red<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary green.
    fn green<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary blue.
    fn blue<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
}
<commit_msg>Add some missing `From` impls between Srgb and LinSrgb types<commit_after>//!RGB types, spaces and standards.

use alpha::Alpha;
use float::Float;
use core::any::Any;

use {Component, Yxy};
use white_point::WhitePoint;

use encoding::{Linear, TransferFn};

pub use self::rgb::{Rgb, Rgba};

//mod linear;
mod rgb;

///Nonlinear sRGB.
pub type Srgb<T = f32> = Rgb<::encoding::Srgb, T>;
///Nonlinear sRGB with an alpha component.
pub type Srgba<T = f32> = Rgba<::encoding::Srgb, T>;

///Linear sRGB.
pub type LinSrgb<T = f32> = Rgb<Linear<::encoding::Srgb>, T>;
///Linear sRGB with an alpha component.
pub type LinSrgba<T = f32> = Rgba<Linear<::encoding::Srgb>, T>;

/// Gamma 2.2 encoded sRGB.
pub type GammaSrgb<T = f32> = Rgb<::encoding::Gamma<::encoding::Srgb>, T>;
/// Gamma 2.2 encoded sRGB with an alpha component.
pub type GammaSrgba<T = f32> = Rgba<::encoding::Gamma<::encoding::Srgb>, T>;

///An RGB space and a transfer function.
pub trait RgbStandard {
    ///The RGB color space.
    type Space: RgbSpace;

    ///The transfer function for the color components.
    type TransferFn: TransferFn;
}

impl<S: RgbSpace, T: TransferFn> RgbStandard for (S, T) {
    type Space = S;
    type TransferFn = T;
}

impl<P: Primaries, W: WhitePoint, T: TransferFn> RgbStandard for (P, W, T) {
    type Space = (P, W);
    type TransferFn = T;
}

///A set of primaries and a white point.
pub trait RgbSpace {
    ///The primaries of the RGB color space.
    type Primaries: Primaries;

    ///The white point of the RGB color space.
    type WhitePoint: WhitePoint;
}

impl<P: Primaries, W: WhitePoint> RgbSpace for (P, W) {
    type Primaries = P;
    type WhitePoint = W;
}

///Represents the red, green and blue primaries of an RGB space.
pub trait Primaries: Any {
    ///Primary red.
    fn red<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary green.
    fn green<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary blue.
    fn blue<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
}

impl<T, U> From<LinSrgb<T>> for Srgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear()
            .into_format()
    }
}

impl<T, U> From<LinSrgb<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let color = lin_srgb.into();
        let alpha = U::max_intensity();
        Alpha { color, alpha }
    }
}

impl<T, U> From<LinSrgba<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgba: LinSrgba<T>) -> Self {
        let (r, g, b, a) = lin_srgba.into();
        let color = LinSrgb::new(r, g, b).into();
        let alpha = a.convert();
        Alpha { color, alpha }
    }
}

impl<T, U> From<Srgb<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        let color = srgb.into();
        let alpha = U::max_intensity();
        Alpha { color, alpha }
    }
}

impl<T, U> From<Srgba<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgba: Srgba<T>) -> Self {
        let (r, g, b, a) = srgba.into();
        let color = Srgb::new(r, g, b).into();
        let alpha = a.convert();
        Alpha { color, alpha }
    }
}
<|endoftext|>