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

use super::MaybeOwned;

macro_rules! impl_op {
    ($([$OP:ident : $op:ident, $OP_ASSIGN:ident : $op_assign: ident]),*) => ($(
        impl<'min, L, R, OUT: 'min> $OP<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
            where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
                &'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
        {
            type Output = OUT;

            fn $op(self, rhs: MaybeOwned<'min, R>) -> Self::Output {
                use self::MaybeOwned::*;
                match (self, rhs) {
                    (Owned(l), Owned(r)) => l.$op(r),
                    (Owned(l), Borrowed(r)) => l.$op(r),
                    (Borrowed(l), Owned(r)) => l.$op(r),
                    (Borrowed(l), Borrowed(r)) => l.$op(r)
                }
            }
        }

        impl<'min, L, R> $OP_ASSIGN<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
            where L: Clone + $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
        {

            fn $op_assign(&mut self, rhs: MaybeOwned<'min, R>) {
                use self::MaybeOwned::*;
                match rhs {
                    Owned(r) => self.to_mut().$op_assign(r),
                    Borrowed(r) => self.to_mut().$op_assign(r)
                }
            }
        }
    )*);
}

impl_op! {
    [Add: add, AddAssign: add_assign],
    [Sub: sub, SubAssign: sub_assign],
    [Mul: mul, MulAssign: mul_assign],
    [Div: div, DivAssign: div_assign],
    [Shl: shl, ShlAssign: shl_assign],
    [Shr: shr, ShrAssign: shr_assign],
    [BitAnd: bitand, BitAndAssign: bitand_assign],
    [BitOr:  bitor,  BitOrAssign:  bitor_assign ],
    [BitXor: bitxor, BitXorAssign: bitxor_assign]
}

impl<'l, V, OUT> Neg for MaybeOwned<'l, V>
    where V: Neg<Output=OUT>, &'l V: Neg<Output=OUT>
{
    type Output = OUT;

    fn neg(self) -> Self::Output {
        use self::MaybeOwned::*;

        match self {
            Owned(s) => s.neg(),
            Borrowed(s) => s.neg()
        }
    }
}

impl<'l, V, OUT> Not for MaybeOwned<'l, V>
    where V: Not<Output=OUT>, &'l V: Not<Output=OUT>
{
    type Output = V::Output;

    fn not(self) -> Self::Output {
        use self::MaybeOwned::*;

        match self {
            Owned(s) => s.not(),
            Borrowed(s) => s.not()
        }
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Add, AddAssign, Not, Neg};
    use super::*;

    #[derive(Clone, PartialEq)]
    struct Think { x: u8 }

    impl Add<Think> for Think {
        type Output = u8;

        fn add(self, rhs: Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl AddAssign<Think> for Think {
        fn add_assign(&mut self, rhs: Think) {
            self.x += rhs.x
        }
    }
    impl<'a> Add<&'a Think> for Think {
        type Output = u8;

        fn add(self, rhs: &'a Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl<'a> AddAssign<&'a Think> for Think {
        fn add_assign(&mut self, rhs: &'a Think) {
            self.x += rhs.x
        }
    }
    impl<'a> Add<Think> for &'a Think {
        type Output = u8;

        fn add(self, rhs: Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl<'a, 'b> Add<&'a Think> for &'b Think {
        type Output = u8;

        fn add(self, rhs: &'a Think) -> Self::Output {
            self.x + rhs.x
        }
    }

    impl Not for Think {
        type Output = bool;

        fn not(self) -> Self::Output {
            self.x != 0
        }
    }

    impl<'a> Not for &'a Think {
        type Output = bool;

        fn not(self) -> Self::Output {
            self.x != 0
        }
    }

    impl Neg for Think {
        type Output = i8;

        fn neg(self) -> Self::Output {
            -(self.x as i8)
        }
    }

    impl<'a> Neg for &'a Think {
        type Output = i8;

        fn neg(self) -> Self::Output {
            -(self.x as i8)
        }
    }

    #[test]
    fn op_impls_exist() {
        let a = MaybeOwned::from(Think { x: 12 });
        let b = MaybeOwned::from(Think { x: 13 });
        assert_eq!(a + b, 25u8);

        let c = Think { x: 42 };
        let c1: MaybeOwned<Think> = (&c).into();
        let c2: MaybeOwned<Think> = (&c).into();

        assert_eq!(c1 + c2, 84);
    }

    #[test]
    fn op_assign_impls_exist() {
        let mut a = MaybeOwned::from(Think { x: 2 });
        a += MaybeOwned::from(Think { x: 3 });
        assert_eq!(a.x, 5);

        let a = Think { x: 2 };
        let mut a: MaybeOwned<Think> = (&a).into();
        assert!(!a.is_owned());
        a += MaybeOwned::from(Think { x: 5 });
        assert!(a.is_owned());
        assert_eq!(a.as_ref().x, 7);
    }

    #[test]
    fn not_and_neg_are_impl() {
        let a = Think { x: 5 };
        let b = Think { x: 0 };
        let a1: MaybeOwned<Think> = (&a).into();
        let a2: MaybeOwned<Think> = (&a).into();

        assert_eq!(!a1, true);
        assert_eq!(!b, false);
        assert_eq!(-a2, -5i8);
    }

}<commit_msg>Added transitive op implementations for MaybeOwnedMut. (#11)<commit_after>use std::ops::*;

use super::{MaybeOwned, MaybeOwnedMut};

macro_rules! impl_op {
    ($([$OP:ident : $op:ident, $OP_ASSIGN:ident : $op_assign: ident]),*) => ($(
        impl<'min, L, R, OUT: 'min> $OP<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
            where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
                &'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
        {
            type Output = OUT;

            fn $op(self, rhs: MaybeOwned<'min, R>) -> Self::Output {
                use self::MaybeOwned::*;
                match (self, rhs) {
                    (Owned(l), Owned(r)) => l.$op(r),
                    (Owned(l), Borrowed(r)) => l.$op(r),
                    (Borrowed(l), Owned(r)) => l.$op(r),
                    (Borrowed(l), Borrowed(r)) => l.$op(r)
                }
            }
        }

        // Note: With an additional macro level we could fold this with the
        //       previous $OP implementation. But the additional read complexity
        //       isn't really worth it.
        impl<'min, L, R, OUT: 'min> $OP<MaybeOwnedMut<'min, R>> for MaybeOwnedMut<'min, L>
            where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
                &'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
        {
            type Output = OUT;

            fn $op(self, rhs: MaybeOwnedMut<'min, R>) -> Self::Output {
                use self::MaybeOwnedMut::*;
                match (self, rhs) {
                    (Owned(l), Owned(r)) => l.$op(r),
                    (Owned(l), Borrowed(r)) => l.$op(&*r),
                    (Borrowed(l), Owned(r)) => (&*l).$op(r),
                    (Borrowed(l), Borrowed(r)) => (&*l).$op(&*r)
                }
            }
        }

        impl<'min, L, R> $OP_ASSIGN<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
            where L: Clone + $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
        {

            fn $op_assign(&mut self, rhs: MaybeOwned<'min, R>) {
                use self::MaybeOwned::*;
                match rhs {
                    Owned(r) => self.to_mut().$op_assign(r),
                    Borrowed(r) => self.to_mut().$op_assign(r)
                }
            }
        }

        impl<'min, L, R> $OP_ASSIGN<MaybeOwnedMut<'min, R>> for MaybeOwnedMut<'min, L>
            where L: $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
        {

            fn $op_assign(&mut self, rhs: MaybeOwnedMut<'min, R>) {
                use self::MaybeOwnedMut::*;
                match rhs {
                    Owned(r) => self.as_mut().$op_assign(r),
                    Borrowed(r) => self.as_mut().$op_assign(&*r)
                }
            }
        }
    )*);
}

impl_op! {
    [Add: add, AddAssign: add_assign],
    [Sub: sub, SubAssign: sub_assign],
    [Mul: mul, MulAssign: mul_assign],
    [Div: div, DivAssign: div_assign],
    [Shl: shl, ShlAssign: shl_assign],
    [Shr: shr, ShrAssign: shr_assign],
    [BitAnd: bitand, BitAndAssign: bitand_assign],
    [BitOr:  bitor,  BitOrAssign:  bitor_assign ],
    [BitXor: bitxor, BitXorAssign: bitxor_assign]
}

impl<'l, V, OUT> Neg for MaybeOwned<'l, V>
    where V: Neg<Output=OUT>, &'l V: Neg<Output=OUT>
{
    type Output = OUT;

    fn neg(self) -> Self::Output {
        use self::MaybeOwned::*;

        match self {
            Owned(s) => s.neg(),
            Borrowed(s) => s.neg()
        }
    }
}

impl<'l, V, OUT> Neg for MaybeOwnedMut<'l, V>
    where V: Neg<Output=OUT>, &'l V: Neg<Output=OUT>
{
    type Output = OUT;

    fn neg(self) -> Self::Output {
        use self::MaybeOwnedMut::*;

        match self {
            Owned(s) => s.neg(),
            Borrowed(s) => (&*s).neg()
        }
    }
}

impl<'l, V, OUT> Not for MaybeOwned<'l, V>
    where V: Not<Output=OUT>, &'l V: Not<Output=OUT>
{
    type Output = V::Output;

    fn not(self) -> Self::Output {
        use self::MaybeOwned::*;

        match self {
            Owned(s) => s.not(),
            Borrowed(s) => s.not()
        }
    }
}

impl<'l, V, OUT> Not for MaybeOwnedMut<'l, V>
    where V: Not<Output=OUT>, &'l V: Not<Output=OUT>
{
    type Output = V::Output;

    fn not(self) -> Self::Output {
        use self::MaybeOwnedMut::*;

        match self {
            Owned(s) => s.not(),
            Borrowed(s) => (&*s).not()
        }
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Add, AddAssign, Not, Neg};
    use super::*;

    //FIXME the test might need some cleanup.

    #[derive(Clone, PartialEq)]
    struct Think { x: u8 }

    impl Add<Think> for Think {
        type Output = u8;

        fn add(self, rhs: Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl AddAssign<Think> for Think {
        fn add_assign(&mut self, rhs: Think) {
            self.x += rhs.x
        }
    }
    impl<'a> Add<&'a Think> for Think {
        type Output = u8;

        fn add(self, rhs: &'a Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl<'a> AddAssign<&'a Think> for Think {
        fn add_assign(&mut self, rhs: &'a Think) {
            self.x += rhs.x
        }
    }
    impl<'a> Add<Think> for &'a Think {
        type Output = u8;

        fn add(self, rhs: Think) -> Self::Output {
            self.x + rhs.x
        }
    }
    impl<'a, 'b> Add<&'a Think> for &'b Think {
        type Output = u8;

        fn add(self, rhs: &'a Think) -> Self::Output {
            self.x + rhs.x
        }
    }

    impl Not for Think {
        type Output = bool;

        fn not(self) -> Self::Output {
            self.x != 0
        }
    }

    impl<'a> Not for &'a Think {
        type Output = bool;

        fn not(self) -> Self::Output {
            self.x != 0
        }
    }

    impl Neg for Think {
        type Output = i8;

        fn neg(self) -> Self::Output {
            -(self.x as i8)
        }
    }

    impl<'a> Neg for &'a Think {
        type Output = i8;

        fn neg(self) -> Self::Output {
            -(self.x as i8)
        }
    }

    #[test]
    fn op_impls_exist() {
        let a = MaybeOwned::from(Think { x: 12 });
        let b = MaybeOwned::from(Think { x: 13 });
        assert_eq!(a + b, 25u8);

        let c = Think { x: 42 };
        let c1: MaybeOwned<Think> = (&c).into();
        let c2: MaybeOwned<Think> = (&c).into();

        assert_eq!(c1 + c2, 84);
    }

    #[test]
    fn op_impls_exist_for_mut() {
        let a: MaybeOwnedMut<Think> = Think { x: 12 }.into();
        let b: MaybeOwnedMut<Think> = Think { x: 13 }.into();
        assert_eq!(a + b, 25u8);

        let mut c0a = Think { x: 42 };
        let mut c0b = Think { x: 8 };
        let c1: MaybeOwnedMut<Think> = (&mut c0a).into();
        let c2: MaybeOwnedMut<Think> = (&mut c0b).into();
        assert_eq!(c1 + c2, 50);
    }

    #[test]
    fn op_assign_impls_exist() {
        let mut a = MaybeOwned::from(Think { x: 2 });
        a += MaybeOwned::from(Think { x: 3 });
        assert_eq!(a.x, 5);

        let a = Think { x: 2 };
        let mut a: MaybeOwned<Think> = (&a).into();
        assert!(!a.is_owned());
        a += MaybeOwned::from(Think { x: 5 });
        assert!(a.is_owned());
        assert_eq!(a.as_ref().x, 7);
    }

    #[test]
    fn op_assign_impls_exist_mut() {
        let mut a: MaybeOwnedMut<Think> = Think { x: 2 }.into();
        a += MaybeOwnedMut::from(Think { x: 3 });
        assert_eq!(a.x, 5);

        let mut a = Think { x: 2 };
        let mut a: MaybeOwnedMut<Think> = (&mut a).into();
        assert!(!a.is_owned());
        a += MaybeOwnedMut::from(Think { x: 5 });
        assert!(!a.is_owned());
        assert_eq!(a.as_ref().x, 7);
    }

    #[test]
    fn not_and_neg_work_for_think_test_type()  {
        assert_eq!(!Think { x: 0 }, false);
        assert_eq!(!Think { x: 1 }, true);
        assert_eq!(!&Think { x: 0 }, false);
        assert_eq!(!&Think { x: 1 }, true);
    }

    #[test]
    fn not_and_neg_are_impl() {
        let a = Think { x: 5 };
        let a1: MaybeOwned<Think> = (&a).into();
        let a2: MaybeOwned<Think> = (&a).into();
        assert_eq!(!a1, true);
        assert_eq!(-a2, -5i8);
    }

    #[test]
    fn not_and_neg_are_impl_mut() {
        let mut a = Think { x: 5 };
        let mut b = Think { x: 0 };
        let a1: MaybeOwnedMut<Think> = (&mut a).into();
        let b1: MaybeOwnedMut<Think> = (&mut b).into();

        assert_eq!(!a1, true);
        assert_eq!(!b1, false);

        let a2: MaybeOwnedMut<Think> = (&mut a).into();
        assert_eq!(-a2, -5i8);
    }
}<|endoftext|>


<commit_before>use core::cmp::min;
use core::mem::size_of;
use core::ptr;

use common::scheduler::*;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4 * 1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4 * 1024; // Of 4 K chunks

#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

struct Memory {
    address: usize,
}

impl Memory {
    pub fn new(size: usize) -> Option<Self> {
        unsafe {
            let alloc = alloc(size);
            if alloc > 0 {
                Some(Memory { address: alloc })
            }
            else { None }
        }
    }

    pub fn renew(&self, size: usize) -> Option<Self> {
        unsafe {
            let realloc = realloc(self.address, size);
            if realloc > 0 {
                Some(Memory { address: realloc })
            }
            else { None }
        }
    }
}

impl Drop for Memory {
        fn drop(&mut self) {
            unsafe {
                unalloc(self.address)
            }
        }
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize,
                   address);
    }
}

pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number * CLUSTER_SIZE
}

pub unsafe fn cluster_init() {
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && cluster_to_address(i) % align == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}
<commit_msg>Another Fix<commit_after>use core::cmp::min;
use core::mem::size_of;
use core::ptr;

use common::scheduler::*;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4 * 1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4 * 1024; // Of 4 K chunks

#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

struct Memory {
    address: usize,
}

impl Memory {
    pub fn new(size: usize) -> Option<Self> {
        let alloc = unsafe { alloc(size) };
        if alloc > 0 {
            Some(Memory { address: alloc })
        }
        else { None }
    }

    pub fn renew(&self, size: usize) -> Option<Self> {
        let realloc = unsafe { realloc(self.address, size) };
        if realloc > 0 {
            Some(Memory { address: realloc })
        }
        else { None }
    }
}

impl Drop for Memory {
    fn drop(&mut self) {
        unsafe { unalloc(self.address) }
    }
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize,
                   address);
    }
}

pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number * CLUSTER_SIZE
}

pub unsafe fn cluster_init() {
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && cluster_to_address(i) % align == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    //Memory allocation must be atomic
    end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    //Memory allocation must be atomic
    let reenable = start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        //Memory allocation must be atomic
        let reenable = start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        //Memory allocation must be atomic
        end_no_ints(reenable);
    }
    ret
}
<|endoftext|>


<commit_before>import lib.llvm.llvm;
import lib.llvm.llvm.ModuleRef;
import std._str;
import std._vec;
import std.os.target_os;
import util.common.istr;

const int wordsz = 4;

fn wstr(int i) -> str {
    ret istr(i * wordsz);
}

fn save_callee_saves() -> vec[str] {
    ret vec("pushl %ebp",
            "pushl %edi",
            "pushl %esi",
            "pushl %ebx");
}

fn restore_callee_saves() -> vec[str] {
    ret vec("popl  %ebx",
            "popl  %esi",
            "popl  %edi",
            "popl  %ebp");
}

fn load_esp_from_rust_sp() -> vec[str] {
    ret vec("movl  " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp");
}

fn load_esp_from_runtime_sp() -> vec[str] {
    ret vec("movl  " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp");
}

fn store_esp_to_rust_sp() -> vec[str] {
    ret vec("movl  %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)");
}

fn store_esp_to_runtime_sp() -> vec[str] {
    ret vec("movl  %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
}

fn rust_activate_glue() -> vec[str] {
    ret vec("movl  4(%esp), %ecx    # ecx = rust_task")
        + save_callee_saves()
        + store_esp_to_runtime_sp()
        + load_esp_from_rust_sp()

        // This 'add' instruction is a bit surprising.
        // See lengthy comment in boot/be/x86.ml activate_glue.
        + vec("addl  $20, " + wstr(abi.task_field_rust_sp) + "(%edx)")

        + restore_callee_saves()
        + vec("ret");
}

fn rust_yield_glue() -> vec[str] {
    ret vec("movl  0(%esp), %ecx    # ecx = rust_task")
        + load_esp_from_rust_sp()
        + save_callee_saves()
        + store_esp_to_rust_sp()
        + load_esp_from_runtime_sp()
        + restore_callee_saves()
        + vec("ret");
}

fn upcall_glue(int n_args) -> vec[str] {

    /*
     * 0, 4, 8, 12 are callee-saves
     * 16 is retpc
     * 20 .. (5+i) * 4 are args
     *
     * ecx is taskptr
     * edx is callee
     *
     */

    fn copy_arg(uint i) -> str {
        auto src_off = wstr(5 + (i as int));
        auto dst_off = wstr(1 + (i as int));
        auto m = vec("movl  " + src_off + "(%ebp),%eax",
                     "movl  %eax," + dst_off + "(%esp)");
        ret _str.connect(m, "\n\t");
    }

    auto carg = copy_arg;

    ret
        save_callee_saves()

        + vec("movl  %esp, %ebp     # ebp = rust_sp")

        + store_esp_to_rust_sp()
        + load_esp_from_runtime_sp()

        + vec("subl  $" + wstr(n_args + 1) + ", %esp   # esp -= args",
              "andl  $~0xf, %esp    # align esp down",
              "movl  %ecx, (%esp)   # arg[0] = rust_task ")

        + _vec.init_fn[str](carg, n_args as uint)

        +  vec("movl  %ecx, %edi     # save task from ecx to edi",
               "call  *%edx          # call *%edx",
               "movl  %edi, %ecx     # restore edi-saved task to ecx")

        + load_esp_from_rust_sp()
        + restore_callee_saves()
        + vec("ret");

}

fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
    auto sym = prefix + name;
    ret "\t.globl " + sym + "\n" +
        "\t.balign " + istr(align) + "\n" +
        sym + ":\n" +
        "\t" + _str.connect(insns, "\n\t");
}

fn decl_upcall_glue(int align, str prefix, uint n) -> str {
    let int i = n as int;
    ret decl_glue(align, prefix,
                  abi.upcall_glue_name(i),
                  upcall_glue(i));
}

fn get_symbol_prefix() -> str {
    if (_str.eq(target_os(), "macos") ||
        _str.eq(target_os(), "win32")) {
        ret "_";
    } else {
        ret "";
    }
}

fn get_module_asm() -> str {
    auto align = 4;

    auto prefix = get_symbol_prefix();

    auto glues =
        vec(decl_glue(align, prefix,
                      abi.activate_glue_name(),
                      rust_activate_glue()),

            decl_glue(align, prefix,
                      abi.yield_glue_name(),
                      rust_yield_glue()))

        + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
                            abi.n_upcall_glues as uint);

    ret _str.connect(glues, "\n\n");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Fix typo in x86 backend glue that was, by luck, only crashing on OSX.<commit_after>import lib.llvm.llvm;
import lib.llvm.llvm.ModuleRef;
import std._str;
import std._vec;
import std.os.target_os;
import util.common.istr;

const int wordsz = 4;

fn wstr(int i) -> str {
    ret istr(i * wordsz);
}

fn save_callee_saves() -> vec[str] {
    ret vec("pushl %ebp",
            "pushl %edi",
            "pushl %esi",
            "pushl %ebx");
}

fn restore_callee_saves() -> vec[str] {
    ret vec("popl  %ebx",
            "popl  %esi",
            "popl  %edi",
            "popl  %ebp");
}

fn load_esp_from_rust_sp() -> vec[str] {
    ret vec("movl  " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp");
}

fn load_esp_from_runtime_sp() -> vec[str] {
    ret vec("movl  " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp");
}

fn store_esp_to_rust_sp() -> vec[str] {
    ret vec("movl  %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)");
}

fn store_esp_to_runtime_sp() -> vec[str] {
    ret vec("movl  %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
}

fn rust_activate_glue() -> vec[str] {
    ret vec("movl  4(%esp), %ecx    # ecx = rust_task")
        + save_callee_saves()
        + store_esp_to_runtime_sp()
        + load_esp_from_rust_sp()

        // This 'add' instruction is a bit surprising.
        // See lengthy comment in boot/be/x86.ml activate_glue.
        + vec("addl  $20, " + wstr(abi.task_field_rust_sp) + "(%ecx)")

        + restore_callee_saves()
        + vec("ret");
}

fn rust_yield_glue() -> vec[str] {
    ret vec("movl  0(%esp), %ecx    # ecx = rust_task")
        + load_esp_from_rust_sp()
        + save_callee_saves()
        + store_esp_to_rust_sp()
        + load_esp_from_runtime_sp()
        + restore_callee_saves()
        + vec("ret");
}

fn upcall_glue(int n_args) -> vec[str] {

    /*
     * 0, 4, 8, 12 are callee-saves
     * 16 is retpc
     * 20 .. (5+i) * 4 are args
     *
     * ecx is taskptr
     * edx is callee
     *
     */

    fn copy_arg(uint i) -> str {
        auto src_off = wstr(5 + (i as int));
        auto dst_off = wstr(1 + (i as int));
        auto m = vec("movl  " + src_off + "(%ebp),%eax",
                     "movl  %eax," + dst_off + "(%esp)");
        ret _str.connect(m, "\n\t");
    }

    auto carg = copy_arg;

    ret
        save_callee_saves()

        + vec("movl  %esp, %ebp     # ebp = rust_sp")

        + store_esp_to_rust_sp()
        + load_esp_from_runtime_sp()

        + vec("subl  $" + wstr(n_args + 1) + ", %esp   # esp -= args",
              "andl  $~0xf, %esp    # align esp down",
              "movl  %ecx, (%esp)   # arg[0] = rust_task ")

        + _vec.init_fn[str](carg, n_args as uint)

        +  vec("movl  %ecx, %edi     # save task from ecx to edi",
               "call  *%edx          # call *%edx",
               "movl  %edi, %ecx     # restore edi-saved task to ecx")

        + load_esp_from_rust_sp()
        + restore_callee_saves()
        + vec("ret");

}

fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
    auto sym = prefix + name;
    ret "\t.globl " + sym + "\n" +
        "\t.balign " + istr(align) + "\n" +
        sym + ":\n" +
        "\t" + _str.connect(insns, "\n\t");
}

fn decl_upcall_glue(int align, str prefix, uint n) -> str {
    let int i = n as int;
    ret decl_glue(align, prefix,
                  abi.upcall_glue_name(i),
                  upcall_glue(i));
}

fn get_symbol_prefix() -> str {
    if (_str.eq(target_os(), "macos") ||
        _str.eq(target_os(), "win32")) {
        ret "_";
    } else {
        ret "";
    }
}

fn get_module_asm() -> str {
    auto align = 4;

    auto prefix = get_symbol_prefix();

    auto glues =
        vec(decl_glue(align, prefix,
                      abi.activate_glue_name(),
                      rust_activate_glue()),

            decl_glue(align, prefix,
                      abi.yield_glue_name(),
                      rust_yield_glue()))

        + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
                            abi.n_upcall_glues as uint);

    ret _str.connect(glues, "\n\n");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>use buffer::{Content, Buffer, BufferAny, BufferType, BufferMode, BufferCreationError};
use buffer::{BufferSlice, BufferMutSlice};
use uniforms::{AsUniformValue, UniformBlock, UniformValue, LayoutMismatchError};
use program;

use gl;
use GlObject;

use std::ops::{Deref, DerefMut};

use backend::Facade;

/// Buffer that contains a uniform block.
///
/// For example, to use a `UniformBuffer<[u32; 8]`, you must declare it as
///
///     uniform MyBlock {
///         uint array[8];
///     };
///
/// and pass it to `uniform!` like this:
///
///     uniform! {
///         MyBlock: &buffer,
///     }
#[derive(Debug)]
pub struct UniformBuffer<T: ?Sized> where T: Content {
    buffer: Buffer<T>,
}

/// Same as `UniformBuffer` but doesn't contain any information about the type.
#[derive(Debug)]
pub struct TypelessUniformBuffer {
    buffer: BufferAny,
}

impl<T: ?Sized + Content> GlObject for UniformBuffer<T> {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl<T> UniformBuffer<T> where T: Copy {
    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn new<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Default)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn dynamic<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                      where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Dynamic)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn persistent<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Persistent)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn immutable<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                        where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Immutable)
    }

    #[inline]
    fn new_impl<F: ?Sized>(facade: &F, data: T, mode: BufferMode)
                   -> Result<UniformBuffer<T>, BufferCreationError>
                   where F: Facade
    {
        let buffer = try!(Buffer::new(facade, &data, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError> where F: Facade {
        UniformBuffer::empty_impl(facade, BufferMode::Default)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_dynamic<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_persistent<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                               where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_immutable<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                              where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Immutable)
    }

    #[inline]
    fn empty_impl<F: ?Sized>(facade: &F, mode: BufferMode) -> Result<UniformBuffer<T>, BufferCreationError>
                     where F: Facade
    {
        let buffer = try!(Buffer::empty(facade, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> UniformBuffer<T> where T: Content {
    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized<F: ?Sized>(facade: &F, size: usize)
                            -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Default)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_dynamic<F: ?Sized>(facade: &F, size: usize)
                                    -> Result<UniformBuffer<T>, BufferCreationError>
                                    where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_persistent<F: ?Sized>(facade: &F, size: usize)
                                       -> Result<UniformBuffer<T>, BufferCreationError>
                                       where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_immutable<F: ?Sized>(facade: &F, size: usize)
                                      -> Result<UniformBuffer<T>, BufferCreationError>
                                      where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Immutable)
    }

    #[inline]
    fn empty_unsized_impl<F: ?Sized>(facade: &F, size: usize, mode: BufferMode)
                             -> Result<UniformBuffer<T>, BufferCreationError>
                             where F: Facade
    {
        let buffer = try!(Buffer::empty_unsized(facade, BufferType::UniformBuffer, size, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> Deref for UniformBuffer<T> where T: Content {
    type Target = Buffer<T>;

    #[inline]
    fn deref(&self) -> &Buffer<T> {
        &self.buffer
    }
}

impl<T: ?Sized> DerefMut for UniformBuffer<T> where T: Content {
    #[inline]
    fn deref_mut(&mut self) -> &mut Buffer<T> {
        &mut self.buffer
    }
}

impl<'a, T: ?Sized> From<&'a UniformBuffer<T>> for BufferSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a UniformBuffer<T>) -> BufferSlice<'a, T> {
        b.buffer.as_slice()
    }
}

impl<'a, T: ?Sized> From<&'a mut UniformBuffer<T>> for BufferMutSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a mut UniformBuffer<T>) -> BufferMutSlice<'a, T> {
        b.buffer.as_mut_slice()
    }
}

impl<'a, T: ?Sized> AsUniformValue for &'a UniformBuffer<T> where T: UniformBlock + Content {
    #[inline]
    fn as_uniform_value(&self) -> UniformValue {
        #[inline]
        fn f<T: ?Sized>(block: &program::UniformBlock)
                        -> Result<(), LayoutMismatchError> where T: UniformBlock + Content
        {
            // TODO: more checks?
            T::matches(&block.layout, 0)
        }

        UniformValue::Block(self.buffer.as_slice_any(), f::<T>)
    }
}
<commit_msg>Fix typo in #876406e.<commit_after>use buffer::{Content, Buffer, BufferAny, BufferType, BufferMode, BufferCreationError};
use buffer::{BufferSlice, BufferMutSlice};
use uniforms::{AsUniformValue, UniformBlock, UniformValue, LayoutMismatchError};
use program;

use gl;
use GlObject;

use std::ops::{Deref, DerefMut};

use backend::Facade;

/// Buffer that contains a uniform block.
///
/// For example, to use a `UniformBuffer<[u32; 8]>`, you must declare it as
///
///     uniform MyBlock {
///         uint array[8];
///     };
///
/// and pass it to `uniform!` like this:
///
///     uniform! {
///         MyBlock: &buffer,
///     }
#[derive(Debug)]
pub struct UniformBuffer<T: ?Sized> where T: Content {
    buffer: Buffer<T>,
}

/// Same as `UniformBuffer` but doesn't contain any information about the type.
#[derive(Debug)]
pub struct TypelessUniformBuffer {
    buffer: BufferAny,
}

impl<T: ?Sized + Content> GlObject for UniformBuffer<T> {
    type Id = gl::types::GLuint;

    #[inline]
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl<T> UniformBuffer<T> where T: Copy {
    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn new<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Default)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn dynamic<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                      where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Dynamic)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn persistent<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                  where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Persistent)
    }

    /// Uploads data in the uniforms buffer.
    #[inline]
    pub fn immutable<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
                        where F: Facade
    {
        UniformBuffer::new_impl(facade, data, BufferMode::Immutable)
    }

    #[inline]
    fn new_impl<F: ?Sized>(facade: &F, data: T, mode: BufferMode)
                   -> Result<UniformBuffer<T>, BufferCreationError>
                   where F: Facade
    {
        let buffer = try!(Buffer::new(facade, &data, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError> where F: Facade {
        UniformBuffer::empty_impl(facade, BufferMode::Default)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_dynamic<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_persistent<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                               where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    #[inline]
    pub fn empty_immutable<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
                              where F: Facade
    {
        UniformBuffer::empty_impl(facade, BufferMode::Immutable)
    }

    #[inline]
    fn empty_impl<F: ?Sized>(facade: &F, mode: BufferMode) -> Result<UniformBuffer<T>, BufferCreationError>
                     where F: Facade
    {
        let buffer = try!(Buffer::empty(facade, BufferType::UniformBuffer, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> UniformBuffer<T> where T: Content {
    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized<F: ?Sized>(facade: &F, size: usize)
                            -> Result<UniformBuffer<T>, BufferCreationError>
                            where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Default)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_dynamic<F: ?Sized>(facade: &F, size: usize)
                                    -> Result<UniformBuffer<T>, BufferCreationError>
                                    where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Dynamic)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_persistent<F: ?Sized>(facade: &F, size: usize)
                                       -> Result<UniformBuffer<T>, BufferCreationError>
                                       where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Persistent)
    }

    /// Creates an empty buffer.
    ///
    /// # Panic
    ///
    /// Panicks if the size passed as parameter is not suitable for the type of data.
    ///
    #[inline]
    pub fn empty_unsized_immutable<F: ?Sized>(facade: &F, size: usize)
                                      -> Result<UniformBuffer<T>, BufferCreationError>
                                      where F: Facade
    {
        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Immutable)
    }

    #[inline]
    fn empty_unsized_impl<F: ?Sized>(facade: &F, size: usize, mode: BufferMode)
                             -> Result<UniformBuffer<T>, BufferCreationError>
                             where F: Facade
    {
        let buffer = try!(Buffer::empty_unsized(facade, BufferType::UniformBuffer, size, mode));

        Ok(UniformBuffer {
            buffer: buffer,
        })
    }
}

impl<T: ?Sized> Deref for UniformBuffer<T> where T: Content {
    type Target = Buffer<T>;

    #[inline]
    fn deref(&self) -> &Buffer<T> {
        &self.buffer
    }
}

impl<T: ?Sized> DerefMut for UniformBuffer<T> where T: Content {
    #[inline]
    fn deref_mut(&mut self) -> &mut Buffer<T> {
        &mut self.buffer
    }
}

impl<'a, T: ?Sized> From<&'a UniformBuffer<T>> for BufferSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a UniformBuffer<T>) -> BufferSlice<'a, T> {
        b.buffer.as_slice()
    }
}

impl<'a, T: ?Sized> From<&'a mut UniformBuffer<T>> for BufferMutSlice<'a, T> where T: Content {
    #[inline]
    fn from(b: &'a mut UniformBuffer<T>) -> BufferMutSlice<'a, T> {
        b.buffer.as_mut_slice()
    }
}

impl<'a, T: ?Sized> AsUniformValue for &'a UniformBuffer<T> where T: UniformBlock + Content {
    #[inline]
    fn as_uniform_value(&self) -> UniformValue {
        #[inline]
        fn f<T: ?Sized>(block: &program::UniformBlock)
                        -> Result<(), LayoutMismatchError> where T: UniformBlock + Content
        {
            // TODO: more checks?
            T::matches(&block.layout, 0)
        }

        UniformValue::Block(self.buffer.as_slice_any(), f::<T>)
    }
}
<|endoftext|>


<commit_before>// spell-checker:ignore (ToDO) dylib libstdbuf deps liblibstdbuf

use std::env;
use std::fs;
use std::path::Path;

#[cfg(not(any(target_vendor = "apple", target_os = "windows")))]
mod platform {
    pub const DYLIB_EXT: &str = ".so";
}

#[cfg(any(target_vendor = "apple"))]
mod platform {
    pub const DYLIB_EXT: &str = ".dylib";
}

#[cfg(target_os = "windows")]
mod platform {
    pub const DYLIB_EXT: &str = ".dll";
}

fn main() {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("Could not find manifest dir");
    let profile = env::var("PROFILE").expect("Could not determine profile");

    let out_dir = env::var("OUT_DIR").unwrap();
    let libstdbuf = format!(
        "{}/../../../{}/{}/deps/liblibstdbuf{}",
        manifest_dir,
        env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| "target".to_string()),
        profile,
        platform::DYLIB_EXT
    );

    fs::copy(libstdbuf, Path::new(&out_dir).join("libstdbuf.so")).unwrap();
}
<commit_msg>stdbuf: fix cargo --git build (#1276)<commit_after>// spell-checker:ignore (ToDO) dylib libstdbuf deps liblibstdbuf

use std::env;
use std::fs;
use std::path::Path;

#[cfg(not(any(target_vendor = "apple", target_os = "windows")))]
mod platform {
    pub const DYLIB_EXT: &str = ".so";
}

#[cfg(any(target_vendor = "apple"))]
mod platform {
    pub const DYLIB_EXT: &str = ".dylib";
}

#[cfg(target_os = "windows")]
mod platform {
    pub const DYLIB_EXT: &str = ".dll";
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let mut target_dir = Path::new(&out_dir);

    // Depending on how this is util is built, the directory structure. This seems to work for now.
    // Here are three cases to test when changing this:
    // - cargo run
    // - cross run
    // - cargo install --git
    let mut name = target_dir.file_name().unwrap().to_string_lossy();
    while name != "target" && !name.starts_with("cargo-install") {
        target_dir = target_dir.parent().unwrap();
        name = target_dir.file_name().unwrap().to_string_lossy();
    }
    let mut libstdbuf = target_dir.to_path_buf();
    libstdbuf.push(env::var("PROFILE").unwrap());
    libstdbuf.push("deps");
    libstdbuf.push(format!("liblibstdbuf{}", platform::DYLIB_EXT));

    fs::copy(libstdbuf, Path::new(&out_dir).join("libstdbuf.so")).unwrap();
}
<|endoftext|>


<commit_before>use crate::codec::decoder::Decoder;
use crate::codec::encoder::Encoder;
use crate::codec::framed_impl::{FramedImpl, RWFrames, ReadFrame, WriteFrame};

use tokio::{
    io::{AsyncRead, AsyncWrite},
    stream::Stream,
};

use bytes::BytesMut;
use futures_sink::Sink;
use pin_project_lite::pin_project;
use std::fmt;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// A unified [`Stream`] and [`Sink`] interface to an underlying I/O object, using
    /// the `Encoder` and `Decoder` traits to encode and decode frames.
    ///
    /// You can create a `Framed` instance by using the [`Decoder::framed`] adapter, or
    /// by using the `new` function seen below.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`Decoder::framed`]: crate::codec::Decoder::framed()
    pub struct Framed<T, U> {
        #[pin]
        inner: FramedImpl<T, U, RWFrames>
    }
}

impl<T, U> Framed<T, U>
where
    T: AsyncRead + AsyncWrite,
{
    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the codec
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decode`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn new(inner: T, codec: U) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner,
                codec,
                state: Default::default(),
            },
        }
    }

    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data,
    /// with a specific read buffer initial capacity.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the codec
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decode`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn with_capacity(inner: T, codec: U, capacity: usize) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner,
                codec,
                state: RWFrames {
                    read: ReadFrame {
                        eof: false,
                        is_readable: false,
                        buffer: BytesMut::with_capacity(capacity),
                    },
                    write: WriteFrame::default(),
                },
            },
        }
    }
}

impl<T, U> Framed<T, U> {
    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// This objects takes a stream and a readbuffer and a writebuffer. These field
    /// can be obtained from an existing `Framed` with the [`into_parts`] method.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decoder`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`into_parts`]: crate::codec::Framed::into_parts()
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner: parts.io,
                codec: parts.codec,
                state: RWFrames {
                    read: parts.read_buf.into(),
                    write: parts.write_buf.into(),
                },
            },
        }
    }

    /// Returns a reference to the underlying I/O stream wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner
    }

    /// Returns a reference to the underlying codec wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying codec
    /// as it may corrupt the stream of frames otherwise being worked with.
    pub fn codec(&self) -> &U {
        &self.inner.codec
    }

    /// Returns a mutable reference to the underlying codec wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying codec
    /// as it may corrupt the stream of frames otherwise being worked with.
    pub fn codec_mut(&mut self) -> &mut U {
        &mut self.inner.codec
    }

    /// Returns a reference to the read buffer.
    pub fn read_buffer(&self) -> &BytesMut {
        &self.inner.state.read.buffer
    }

    /// Consumes the `Framed`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner
    }

    /// Consumes the `Framed`, returning its underlying I/O stream, the buffer
    /// with unprocessed data, and the codec.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_parts(self) -> FramedParts<T, U> {
        FramedParts {
            io: self.inner.inner,
            codec: self.inner.codec,
            read_buf: self.inner.state.read.buffer,
            write_buf: self.inner.state.write.buffer,
            _priv: (),
        }
    }
}

// This impl just defers to the underlying FramedImpl
impl<T, U> Stream for Framed<T, U>
where
    T: AsyncRead,
    U: Decoder,
{
    type Item = Result<U::Item, U::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.project().inner.poll_next(cx)
    }
}

// This impl just defers to the underlying FramedImpl
impl<T, I, U> Sink<I> for Framed<T, U>
where
    T: AsyncWrite,
    U: Encoder<I>,
    U::Error: From<io::Error>,
{
    type Error = U::Error;

    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_ready(cx)
    }

    fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> {
        self.project().inner.start_send(item)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_flush(cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_close(cx)
    }
}

impl<T, U> fmt::Debug for Framed<T, U>
where
    T: fmt::Debug,
    U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Framed")
            .field("io", self.get_ref())
            .field("codec", self.codec())
            .finish()
    }
}

/// `FramedParts` contains an export of the data of a Framed transport.
/// It can be used to construct a new [`Framed`] with a different codec.
/// It contains all current buffers and the inner transport.
///
/// [`Framed`]: crate::codec::Framed
#[derive(Debug)]
pub struct FramedParts<T, U> {
    /// The inner transport used to read bytes to and write bytes to
    pub io: T,

    /// The codec
    pub codec: U,

    /// The buffer with read but unprocessed data.
    pub read_buf: BytesMut,

    /// A buffer with unprocessed data which are not written yet.
    pub write_buf: BytesMut,

    /// This private field allows us to add additional fields in the future in a
    /// backwards compatible way.
    _priv: (),
}

impl<T, U> FramedParts<T, U> {
    /// Create a new, default, `FramedParts`
    pub fn new<I>(io: T, codec: U) -> FramedParts<T, U>
    where
        U: Encoder<I>,
    {
        FramedParts {
            io,
            codec,
            read_buf: BytesMut::new(),
            write_buf: BytesMut::new(),
            _priv: (),
        }
    }
}
<commit_msg>codec: add Framed::read_buffer_mut (#2546)<commit_after>use crate::codec::decoder::Decoder;
use crate::codec::encoder::Encoder;
use crate::codec::framed_impl::{FramedImpl, RWFrames, ReadFrame, WriteFrame};

use tokio::{
    io::{AsyncRead, AsyncWrite},
    stream::Stream,
};

use bytes::BytesMut;
use futures_sink::Sink;
use pin_project_lite::pin_project;
use std::fmt;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// A unified [`Stream`] and [`Sink`] interface to an underlying I/O object, using
    /// the `Encoder` and `Decoder` traits to encode and decode frames.
    ///
    /// You can create a `Framed` instance by using the [`Decoder::framed`] adapter, or
    /// by using the `new` function seen below.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`Decoder::framed`]: crate::codec::Decoder::framed()
    pub struct Framed<T, U> {
        #[pin]
        inner: FramedImpl<T, U, RWFrames>
    }
}

impl<T, U> Framed<T, U>
where
    T: AsyncRead + AsyncWrite,
{
    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the codec
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decode`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn new(inner: T, codec: U) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner,
                codec,
                state: Default::default(),
            },
        }
    }

    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data,
    /// with a specific read buffer initial capacity.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the codec
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decode`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn with_capacity(inner: T, codec: U, capacity: usize) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner,
                codec,
                state: RWFrames {
                    read: ReadFrame {
                        eof: false,
                        is_readable: false,
                        buffer: BytesMut::with_capacity(capacity),
                    },
                    write: WriteFrame::default(),
                },
            },
        }
    }
}

impl<T, U> Framed<T, U> {
    /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this
    /// I/O object, using [`Decoder`] and [`Encoder`] to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both [`Stream`] and
    /// [`Sink`]; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// This objects takes a stream and a readbuffer and a writebuffer. These field
    /// can be obtained from an existing `Framed` with the [`into_parts`] method.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling [`split`] on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    ///
    /// [`Stream`]: tokio::stream::Stream
    /// [`Sink`]: futures_sink::Sink
    /// [`Decoder`]: crate::codec::Decoder
    /// [`Encoder`]: crate::codec::Encoder
    /// [`into_parts`]: crate::codec::Framed::into_parts()
    /// [`split`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.split
    pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
        Framed {
            inner: FramedImpl {
                inner: parts.io,
                codec: parts.codec,
                state: RWFrames {
                    read: parts.read_buf.into(),
                    write: parts.write_buf.into(),
                },
            },
        }
    }

    /// Returns a reference to the underlying I/O stream wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner
    }

    /// Returns a reference to the underlying codec wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying codec
    /// as it may corrupt the stream of frames otherwise being worked with.
    pub fn codec(&self) -> &U {
        &self.inner.codec
    }

    /// Returns a mutable reference to the underlying codec wrapped by
    /// `Framed`.
    ///
    /// Note that care should be taken to not tamper with the underlying codec
    /// as it may corrupt the stream of frames otherwise being worked with.
    pub fn codec_mut(&mut self) -> &mut U {
        &mut self.inner.codec
    }

    /// Returns a reference to the read buffer.
    pub fn read_buffer(&self) -> &BytesMut {
        &self.inner.state.read.buffer
    }

    /// Returns a mutable reference to the read buffer.
    pub fn read_buffer_mut(&mut self) -> &mut BytesMut {
        &mut self.inner.state.read.buffer
    }

    /// Consumes the `Framed`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner
    }

    /// Consumes the `Framed`, returning its underlying I/O stream, the buffer
    /// with unprocessed data, and the codec.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_parts(self) -> FramedParts<T, U> {
        FramedParts {
            io: self.inner.inner,
            codec: self.inner.codec,
            read_buf: self.inner.state.read.buffer,
            write_buf: self.inner.state.write.buffer,
            _priv: (),
        }
    }
}

// This impl just defers to the underlying FramedImpl
impl<T, U> Stream for Framed<T, U>
where
    T: AsyncRead,
    U: Decoder,
{
    type Item = Result<U::Item, U::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.project().inner.poll_next(cx)
    }
}

// This impl just defers to the underlying FramedImpl
impl<T, I, U> Sink<I> for Framed<T, U>
where
    T: AsyncWrite,
    U: Encoder<I>,
    U::Error: From<io::Error>,
{
    type Error = U::Error;

    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_ready(cx)
    }

    fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> {
        self.project().inner.start_send(item)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_flush(cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.project().inner.poll_close(cx)
    }
}

impl<T, U> fmt::Debug for Framed<T, U>
where
    T: fmt::Debug,
    U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Framed")
            .field("io", self.get_ref())
            .field("codec", self.codec())
            .finish()
    }
}

/// `FramedParts` contains an export of the data of a Framed transport.
/// It can be used to construct a new [`Framed`] with a different codec.
/// It contains all current buffers and the inner transport.
///
/// [`Framed`]: crate::codec::Framed
#[derive(Debug)]
pub struct FramedParts<T, U> {
    /// The inner transport used to read bytes to and write bytes to
    pub io: T,

    /// The codec
    pub codec: U,

    /// The buffer with read but unprocessed data.
    pub read_buf: BytesMut,

    /// A buffer with unprocessed data which are not written yet.
    pub write_buf: BytesMut,

    /// This private field allows us to add additional fields in the future in a
    /// backwards compatible way.
    _priv: (),
}

impl<T, U> FramedParts<T, U> {
    /// Create a new, default, `FramedParts`
    pub fn new<I>(io: T, codec: U) -> FramedParts<T, U>
    where
        U: Encoder<I>,
    {
        FramedParts {
            io,
            codec,
            read_buf: BytesMut::new(),
            write_buf: BytesMut::new(),
            _priv: (),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use serde::Serialize;
use std::{collections::BTreeMap, fs, path::Path};

#[derive(Debug)]
pub enum ProbeResponse {
    NoUpdate,
    Update(UpdatePackage, Option<Signature>),
    ExtraPoll(i64),
}

#[derive(Debug, PartialEq)]
pub struct UpdatePackage {
    pub inner: pkg_schema::UpdatePackage,
    pub raw: Vec<u8>,
}

#[derive(Debug, PartialEq)]
pub struct Signature(Vec<u8>);

#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct FirmwareMetadata<'a> {
    pub product_uid: &'a str,
    pub version: &'a str,
    pub hardware: &'a str,
    pub device_identity: MetadataValue<'a>,
    pub device_attributes: MetadataValue<'a>,
}

pub struct MetadataValue<'a>(pub &'a BTreeMap<String, Vec<String>>);

impl<'a> serde::ser::Serialize for MetadataValue<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        use serde::ser::SerializeMap;

        let mut map = serializer.serialize_map(Some(self.0.len()))?;
        for (k, v) in self.0 {
            if v.len() == 1 {
                map.serialize_entry(k, &v[0])?;
            } else {
                map.serialize_entry(k, v)?;
            }
        }
        map.end()
    }
}

impl UpdatePackage {
    pub fn parse(content: &[u8]) -> crate::Result<Self> {
        let update_package = serde_json::from_slice(content)?;
        Ok(UpdatePackage { inner: update_package, raw: content.to_vec() })
    }

    pub fn package_uid(&self) -> String {
        openssl::sha::sha256(&self.raw).iter().map(|c| format!("{:02x}", c)).collect()
    }

    pub fn version(&self) -> &str {
        &self.inner.version
    }
}

impl Signature {
    pub fn from_base64_str(bytes: &str) -> crate::Result<Self> {
        Ok(Signature(openssl::base64::decode_block(bytes)?.to_vec()))
    }

    pub fn validate(&self, key: &Path, package: &UpdatePackage) -> crate::Result<()> {
        use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa, sign::Verifier};
        let key = PKey::from_rsa(Rsa::public_key_from_pem(&fs::read(key)?)?)?;
        if Verifier::new(MessageDigest::sha256(), &key)?.verify_oneshot(&self.0, &package.raw)? {
            return Ok(());
        }
        Err(crate::Error::InvalidSignature)
    }
}
<commit_msg>cloud-sdk: Add clone to UpdatePackage<commit_after>// Copyright (C) 2020 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use serde::Serialize;
use std::{collections::BTreeMap, fs, path::Path};

#[derive(Debug)]
pub enum ProbeResponse {
    NoUpdate,
    Update(UpdatePackage, Option<Signature>),
    ExtraPoll(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub struct UpdatePackage {
    pub inner: pkg_schema::UpdatePackage,
    pub raw: Vec<u8>,
}

#[derive(Debug, PartialEq)]
pub struct Signature(Vec<u8>);

#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct FirmwareMetadata<'a> {
    pub product_uid: &'a str,
    pub version: &'a str,
    pub hardware: &'a str,
    pub device_identity: MetadataValue<'a>,
    pub device_attributes: MetadataValue<'a>,
}

pub struct MetadataValue<'a>(pub &'a BTreeMap<String, Vec<String>>);

impl<'a> serde::ser::Serialize for MetadataValue<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        use serde::ser::SerializeMap;

        let mut map = serializer.serialize_map(Some(self.0.len()))?;
        for (k, v) in self.0 {
            if v.len() == 1 {
                map.serialize_entry(k, &v[0])?;
            } else {
                map.serialize_entry(k, v)?;
            }
        }
        map.end()
    }
}

impl UpdatePackage {
    pub fn parse(content: &[u8]) -> crate::Result<Self> {
        let update_package = serde_json::from_slice(content)?;
        Ok(UpdatePackage { inner: update_package, raw: content.to_vec() })
    }

    pub fn package_uid(&self) -> String {
        openssl::sha::sha256(&self.raw).iter().map(|c| format!("{:02x}", c)).collect()
    }

    pub fn version(&self) -> &str {
        &self.inner.version
    }
}

impl Signature {
    pub fn from_base64_str(bytes: &str) -> crate::Result<Self> {
        Ok(Signature(openssl::base64::decode_block(bytes)?.to_vec()))
    }

    pub fn validate(&self, key: &Path, package: &UpdatePackage) -> crate::Result<()> {
        use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa, sign::Verifier};
        let key = PKey::from_rsa(Rsa::public_key_from_pem(&fs::read(key)?)?)?;
        if Verifier::new(MessageDigest::sha256(), &key)?.verify_oneshot(&self.0, &package.raw)? {
            return Ok(());
        }
        Err(crate::Error::InvalidSignature)
    }
}
<|endoftext|>