<commit_before>pub fn recursive(u: &str, v: &str) -> u32 {
    if u.is_empty() { return v.len() as u32 }
    if v.is_empty() { return u.len() as u32 }

    let uc = u[(u.len() - 1) .. u.len()].chars().next();
    let vc = v[(v.len() - 1) .. v.len()].chars().next();
    let edit_cost = if uc == vc {0} else {1};

    let u_accent = &u[0..(u.len() - 1)];
    let v_accent = &v[0..(v.len() - 1)];

    minimum(
        recursive(&u_accent, &v) + 1,
        recursive(&u, &v_accent) + 1,
        recursive(&u_accent, &v_accent) + edit_cost
    )
}

fn minimum(a: u32, b: u32, c: u32) -> u32 {
    if a < b {
        if a < c {
            a
        } else {
            c
        }
    } else {
        if b < c {
            b
        } else {
            c
        }
    }
}

pub fn matrix(u : &str, v: &str) -> u32 {
    let m = u.len() + 1;
    let n = v.len() + 1;
    let mut matrix: Vec<Vec<u32>> = vec![vec![0; m]; n];

    for column in 0..m {
        matrix[0][column] = column as u32;
    }

    for row in 1..n {
        matrix[row][0] = row as u32;
        for column in 1..m {
            let uc = u[(column - 1) .. column].chars().next();
            let vc = v[(row - 1) .. row].chars().next();
            let edit_cost = if uc == vc {0} else {1};

            matrix[row][column] = minimum(
                matrix[row - 1][column    ] + 1,
                matrix[row    ][column - 1] + 1,
                matrix[row - 1][column - 1] + edit_cost
            );
        }
    }

    matrix[n - 1][m - 1]
}

#[cfg(test)]
mod tests {
    mod recursive {
        use super::super::*;

        #[test]
        fn levenshtein_of_empty_strings_is_zero() {
            assert_eq!(0, recursive("", ""));
        }

        #[test]
        fn levenshtein_of_empty_strings_and_non_empty_string_is_length_of_non_empty_string() {
            let string: &str = "Hello";

            assert_eq!(string.len() as u32, recursive(string, ""));
            assert_eq!(string.len() as u32, recursive("", string));
        }

        #[test]
        fn levenshtein_distace_of_one_is_correctly_calculated() {
            assert_eq!(1, recursive("a", "ab"));
            assert_eq!(1, recursive("ba", "b"));
            assert_eq!(1, recursive("a", "b"));
        }

        #[test]
        fn levenshtein_distance_of_kangaroo_koala() {
            assert_eq!(6, recursive("kangaroo", "koala"));
        }
    }

    mod matrix {
        use super::super::*;

        #[test]
        fn levenshtein_of_empty_strings_is_zero() {
            assert_eq!(0, matrix("", ""));
        }

        #[test]
        fn levenshtein_of_empty_strings_and_non_empty_string_is_length_of_non_empty_string() {
            let string: &str = "Hello";

            assert_eq!(string.len() as u32, matrix(string, ""));
            assert_eq!(string.len() as u32, matrix("", string));
        }

        #[test]
        fn levenshtein_distace_of_one_is_correctly_calculated() {
            assert_eq!(1, matrix("a", "ab"));
            assert_eq!(1, matrix("ba", "b"));
            assert_eq!(1, matrix("a", "b"));
        }

        #[test]
        fn levenshtein_distance_of_kangaroo_koala() {
            assert_eq!(6, matrix("kangaroo", "koala"));
        }
    }
}
<commit_msg>Implements rows variant of Levenshtein distance<commit_after>pub fn recursive(u: &str, v: &str) -> u32 {
    if u.is_empty() { return v.len() as u32 }
    if v.is_empty() { return u.len() as u32 }

    let uc = u[(u.len() - 1) .. u.len()].chars().next();
    let vc = v[(v.len() - 1) .. v.len()].chars().next();
    let edit_cost = if uc == vc {0} else {1};

    let u_accent = &u[0..(u.len() - 1)];
    let v_accent = &v[0..(v.len() - 1)];

    minimum(
        recursive(&u_accent, &v) + 1,
        recursive(&u, &v_accent) + 1,
        recursive(&u_accent, &v_accent) + edit_cost
    )
}

fn minimum(a: u32, b: u32, c: u32) -> u32 {
    if a < b {
        if a < c {
            a
        } else {
            c
        }
    } else {
        if b < c {
            b
        } else {
            c
        }
    }
}

pub fn matrix(u: &str, v: &str) -> u32 {
    let m = u.len() + 1;
    let n = v.len() + 1;
    let mut matrix: Vec<Vec<u32>> = vec![vec![0; m]; n];

    for column in 0..m {
        matrix[0][column] = column as u32;
    }

    for row in 1..n {
        matrix[row][0] = row as u32;
        for column in 1..m {
            let uc = u[(column - 1) .. column].chars().next();
            let vc = v[(row - 1) .. row].chars().next();
            let edit_cost = if uc == vc {0} else {1};

            matrix[row][column] = minimum(
                matrix[row - 1][column    ] + 1,
                matrix[row    ][column - 1] + 1,
                matrix[row - 1][column - 1] + edit_cost
            );
        }
    }

    matrix[n - 1][m - 1]
}

pub fn rows(u : &str, v: &str) -> u32 {
    let m = u.len() + 1;
    let n = v.len() + 1;
    let mut a: Vec<u32> = vec![0; m];
    let mut b: Vec<u32> = vec![0; m];

    for column in 0..m {
        a[column] = column as u32;
    }

    for row in 1..n {
        b[0] = row as u32;
        for column in 1..m {
            let uc = u[(column - 1) .. column].chars().next();
            let vc = v[(row - 1) .. row].chars().next();
            let edit_cost = if uc == vc {0} else {1};

            b[column] = minimum(
                a[column    ] + 1,
                b[column - 1] + 1,
                a[column - 1] + edit_cost
            );
        }

        a = b;
        b = vec![0; m];
    }

    a[m-1]
}

#[cfg(test)]
mod tests {
    mod recursive {
        use super::super::*;

        #[test]
        fn levenshtein_of_empty_strings_is_zero() {
            assert_eq!(0, recursive("", ""));
        }

        #[test]
        fn levenshtein_of_empty_strings_and_non_empty_string_is_length_of_non_empty_string() {
            let string: &str = "Hello";

            assert_eq!(string.len() as u32, recursive(string, ""));
            assert_eq!(string.len() as u32, recursive("", string));
        }

        #[test]
        fn levenshtein_distace_of_one_is_correctly_calculated() {
            assert_eq!(1, recursive("a", "ab"));
            assert_eq!(1, recursive("ba", "b"));
            assert_eq!(1, recursive("a", "b"));
        }

        #[test]
        fn levenshtein_distance_of_kangaroo_koala() {
            assert_eq!(6, recursive("kangaroo", "koala"));
        }
    }

    mod matrix {
        use super::super::*;

        #[test]
        fn levenshtein_of_empty_strings_is_zero() {
            assert_eq!(0, matrix("", ""));
        }

        #[test]
        fn levenshtein_of_empty_strings_and_non_empty_string_is_length_of_non_empty_string() {
            let string: &str = "Hello";

            assert_eq!(string.len() as u32, matrix(string, ""));
            assert_eq!(string.len() as u32, matrix("", string));
        }

        #[test]
        fn levenshtein_distace_of_one_is_correctly_calculated() {
            assert_eq!(1, matrix("a", "ab"));
            assert_eq!(1, matrix("ba", "b"));
            assert_eq!(1, matrix("a", "b"));
        }

        #[test]
        fn levenshtein_distance_of_kangaroo_koala() {
            assert_eq!(6, matrix("kangaroo", "koala"));
        }
    }

    mod rows {
        use super::super::*;

        #[test]
        fn levenshtein_of_empty_strings_is_zero() {
            assert_eq!(0, rows("", ""));
        }

        #[test]
        fn levenshtein_of_empty_strings_and_non_empty_string_is_length_of_non_empty_string() {
            let string: &str = "Hello";

            assert_eq!(string.len() as u32, rows(string, ""));
            assert_eq!(string.len() as u32, rows("", string));
        }

        #[test]
        fn levenshtein_distace_of_one_is_correctly_calculated() {
            assert_eq!(1, rows("a", "ab"));
            assert_eq!(1, rows("ba", "b"));
            assert_eq!(1, rows("a", "b"));
        }

        #[test]
        fn levenshtein_distance_of_kangaroo_koala() {
            assert_eq!(6, rows("kangaroo", "koala"));
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

// run-pass
// Test for issue #18804, #[linkage] does not propagate through generic
// functions. Failure results in a linker error.

// ignore-asmjs no weak symbol support
// ignore-emscripten no weak symbol support
// ignore-windows no extern_weak linkage
// ignore-macos no extern_weak linkage

// aux-build:lib.rs

// rust-lang/rust#56772: nikic says we need this to be proper test.
// compile-flags: -C no-prepopulate-passes

extern crate lib;

fn main() {
    lib::foo::<i32>();
}
<commit_msg>Address LLVM assertion failure by prepopulating with *just* name-anon-globals.<commit_after>// Copyright 2018 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.

// run-pass
// Test for issue #18804, #[linkage] does not propagate through generic
// functions. Failure results in a linker error.

// ignore-asmjs no weak symbol support
// ignore-emscripten no weak symbol support
// ignore-windows no extern_weak linkage
// ignore-macos no extern_weak linkage

// aux-build:lib.rs

// rust-lang/rust#56772: nikic says we need this to be proper test.
// compile-flags: -C no-prepopulate-passes -C passes=name-anon-globals

extern crate lib;

fn main() {
    lib::foo::<i32>();
}
<|endoftext|>


<commit_before>#[cfg(not(feature = "dhcpv4"))]
include!(concat!(env!("OUT_DIR"), "/constants.rs"));

use std::collections::BTreeMap;
#[cfg(not(feature = "dhcpv4"))]
use std::net::Ipv4Addr;
use std::slice;

#[cfg(feature = "dhcpv4")]
use smoltcp::dhcp::Dhcpv4Client;
use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache, Routes};
#[cfg(feature = "trace")]
use smoltcp::phy::EthernetTracer;
use smoltcp::phy::{self, Device, DeviceCapabilities};
use smoltcp::socket::SocketSet;
#[cfg(feature = "dhcpv4")]
use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer};
use smoltcp::time::Instant;
#[cfg(not(feature = "dhcpv4"))]
use smoltcp::wire::IpAddress;
#[cfg(feature = "dhcpv4")]
use smoltcp::wire::Ipv4Cidr;
use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address};

use crate::net::waker::WakerRegistration;
use crate::net::{NetworkInterface, NetworkState};

extern "Rust" {
	fn sys_get_mac_address() -> Result<[u8; 6], ()>;
	fn sys_get_mtu() -> Result<u16, ()>;
	fn sys_get_tx_buffer(len: usize) -> Result<(*mut u8, usize), ()>;
	fn sys_send_tx_buffer(handle: usize, len: usize) -> Result<(), ()>;
	fn sys_receive_rx_buffer() -> Result<(&'static mut [u8], usize), ()>;
	fn sys_rx_buffer_consumed(handle: usize) -> Result<(), ()>;
	fn sys_free_tx_buffer(handle: usize);
}

/// Data type to determine the mac address
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub(crate) struct HermitNet {
	pub mtu: u16,
}

impl HermitNet {
	pub(crate) const fn new(mtu: u16) -> Self {
		Self { mtu }
	}
}

impl NetworkInterface<HermitNet> {
	#[cfg(feature = "dhcpv4")]
	pub(crate) fn new() -> NetworkState {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
		let routes = Routes::new(BTreeMap::new());

		info!("MAC address {}", ethernet_addr);
		info!("MTU: {} bytes", mtu);

		let mut sockets = SocketSet::new(vec![]);
		let dhcp_rx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 900]);
		let dhcp_tx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 600]);
		let dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, Instant::now());
		let prev_cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		NetworkState::Initialized(Self {
			iface,
			sockets,
			dhcp,
			prev_cidr,
			waker: WakerRegistration::new(),
		})
	}

	#[cfg(not(feature = "dhcpv4"))]
	pub(crate) fn new() -> NetworkState {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let myip: Ipv4Addr = std::env::var("HERMIT_IP")
			.unwrap_or(HERMIT_IP.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let myip = myip.octets();
		let mygw: Ipv4Addr = std::env::var("HERMIT_GATEWAY")
			.unwrap_or(HERMIT_GATEWAY.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let mygw = mygw.octets();
		let mymask: Ipv4Addr = std::env::var("HERMIT_MASK")
			.unwrap_or(HERMIT_MASK.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let mymask = mymask.octets();

		// calculate the netmask length
		// => count the number of contiguous 1 bits,
		// starting at the most significant bit in the first octet
		let mut prefix_len = (!mymask[0]).trailing_zeros();
		if prefix_len == 8 {
			prefix_len += (!mymask[1]).trailing_zeros();
		}
		if prefix_len == 16 {
			prefix_len += (!mymask[2]).trailing_zeros();
		}
		if prefix_len == 24 {
			prefix_len += (!mymask[3]).trailing_zeros();
		}

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(
			IpAddress::v4(myip[0], myip[1], myip[2], myip[3]),
			prefix_len.try_into().unwrap(),
		)];
		let default_v4_gw = Ipv4Address::new(mygw[0], mygw[1], mygw[2], mygw[3]);
		let mut routes = Routes::new(BTreeMap::new());
		routes.add_default_ipv4_route(default_v4_gw).unwrap();

		info!("MAC address {}", ethernet_addr);
		info!("Configure network interface with address {}", ip_addrs[0]);
		info!("Configure gateway with address {}", default_v4_gw);
		info!("MTU: {} bytes", mtu);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		NetworkState::Initialized(Self {
			iface,
			sockets: SocketSet::new(vec![]),
			waker: WakerRegistration::new(),
		})
	}
}

impl<'a> Device<'a> for HermitNet {
	type RxToken = RxToken;
	type TxToken = TxToken;

	fn capabilities(&self) -> DeviceCapabilities {
		let mut cap = DeviceCapabilities::default();
		cap.max_transmission_unit = self.mtu.into();
		cap
	}

	fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
		match unsafe { sys_receive_rx_buffer() } {
			Ok((buffer, handle)) => Some((RxToken::new(buffer, handle), TxToken::new())),
			_ => None,
		}
	}

	fn transmit(&'a mut self) -> Option<Self::TxToken> {
		trace!("create TxToken to transfer data");
		Some(TxToken::new())
	}
}

#[doc(hidden)]
pub(crate) struct RxToken {
	buffer: &'static mut [u8],
	handle: usize,
}

impl RxToken {
	pub(crate) fn new(buffer: &'static mut [u8], handle: usize) -> Self {
		Self { buffer, handle }
	}
}

impl phy::RxToken for RxToken {
	#[allow(unused_mut)]
	fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let result = f(self.buffer);
		if unsafe { sys_rx_buffer_consumed(self.handle).is_ok() } {
			result
		} else {
			Err(smoltcp::Error::Exhausted)
		}
	}
}

#[doc(hidden)]
pub(crate) struct TxToken;

impl TxToken {
	pub(crate) fn new() -> Self {
		Self {}
	}
}

impl phy::TxToken for TxToken {
	fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let (tx_buffer, handle) =
			unsafe { sys_get_tx_buffer(len).map_err(|_| smoltcp::Error::Exhausted)? };
		let tx_slice: &'static mut [u8] = unsafe { slice::from_raw_parts_mut(tx_buffer, len) };
		match f(tx_slice) {
			Ok(result) => {
				if unsafe { sys_send_tx_buffer(handle, len).is_ok() } {
					Ok(result)
				} else {
					Err(smoltcp::Error::Exhausted)
				}
			}
			Err(e) => {
				unsafe { sys_free_tx_buffer(handle) };
				Err(e)
			}
		}
	}
}
<commit_msg>address clippy error<commit_after>#[cfg(not(feature = "dhcpv4"))]
include!(concat!(env!("OUT_DIR"), "/constants.rs"));

use std::collections::BTreeMap;
#[cfg(not(feature = "dhcpv4"))]
use std::net::Ipv4Addr;
use std::slice;

#[cfg(feature = "dhcpv4")]
use smoltcp::dhcp::Dhcpv4Client;
use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache, Routes};
#[cfg(feature = "trace")]
use smoltcp::phy::EthernetTracer;
use smoltcp::phy::{self, Device, DeviceCapabilities};
use smoltcp::socket::SocketSet;
#[cfg(feature = "dhcpv4")]
use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer};
use smoltcp::time::Instant;
#[cfg(not(feature = "dhcpv4"))]
use smoltcp::wire::IpAddress;
#[cfg(feature = "dhcpv4")]
use smoltcp::wire::Ipv4Cidr;
use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address};

use crate::net::waker::WakerRegistration;
use crate::net::{NetworkInterface, NetworkState};

extern "Rust" {
	fn sys_get_mac_address() -> Result<[u8; 6], ()>;
	fn sys_get_mtu() -> Result<u16, ()>;
	fn sys_get_tx_buffer(len: usize) -> Result<(*mut u8, usize), ()>;
	fn sys_send_tx_buffer(handle: usize, len: usize) -> Result<(), ()>;
	fn sys_receive_rx_buffer() -> Result<(&'static mut [u8], usize), ()>;
	fn sys_rx_buffer_consumed(handle: usize) -> Result<(), ()>;
	fn sys_free_tx_buffer(handle: usize);
}

/// Data type to determine the mac address
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub(crate) struct HermitNet {
	pub mtu: u16,
}

impl HermitNet {
	pub(crate) const fn new(mtu: u16) -> Self {
		Self { mtu }
	}
}

impl NetworkInterface<HermitNet> {
	#[cfg(feature = "dhcpv4")]
	pub(crate) fn new() -> NetworkState {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
		let routes = Routes::new(BTreeMap::new());

		info!("MAC address {}", ethernet_addr);
		info!("MTU: {} bytes", mtu);

		let mut sockets = SocketSet::new(vec![]);
		let dhcp_rx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 900]);
		let dhcp_tx_buffer = RawSocketBuffer::new([RawPacketMetadata::EMPTY; 1], vec![0; 600]);
		let dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, Instant::now());
		let prev_cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		NetworkState::Initialized(Self {
			iface,
			sockets,
			dhcp,
			prev_cidr,
			waker: WakerRegistration::new(),
		})
	}

	#[cfg(not(feature = "dhcpv4"))]
	pub(crate) fn new() -> NetworkState {
		let mtu = match unsafe { sys_get_mtu() } {
			Ok(mtu) => mtu,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let device = HermitNet::new(mtu);
		#[cfg(feature = "trace")]
		let device = EthernetTracer::new(device, |_timestamp, printer| {
			trace!("{}", printer);
		});

		let mac: [u8; 6] = match unsafe { sys_get_mac_address() } {
			Ok(mac) => mac,
			Err(_) => {
				return NetworkState::InitializationFailed;
			}
		};
		let myip: Ipv4Addr = std::env::var("HERMIT_IP")
			.unwrap_or_else(|_| HERMIT_IP.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let myip = myip.octets();
		let mygw: Ipv4Addr = std::env::var("HERMIT_GATEWAY")
			.unwrap_or_else(|_| HERMIT_GATEWAY.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let mygw = mygw.octets();
		let mymask: Ipv4Addr = std::env::var("HERMIT_MASK")
			.unwrap_or_else(|_| HERMIT_MASK.to_string())
			.parse()
			.expect("Unable to parse IPv4 address");
		let mymask = mymask.octets();

		// calculate the netmask length
		// => count the number of contiguous 1 bits,
		// starting at the most significant bit in the first octet
		let mut prefix_len = (!mymask[0]).trailing_zeros();
		if prefix_len == 8 {
			prefix_len += (!mymask[1]).trailing_zeros();
		}
		if prefix_len == 16 {
			prefix_len += (!mymask[2]).trailing_zeros();
		}
		if prefix_len == 24 {
			prefix_len += (!mymask[3]).trailing_zeros();
		}

		let neighbor_cache = NeighborCache::new(BTreeMap::new());
		let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
		let ip_addrs = [IpCidr::new(
			IpAddress::v4(myip[0], myip[1], myip[2], myip[3]),
			prefix_len.try_into().unwrap(),
		)];
		let default_v4_gw = Ipv4Address::new(mygw[0], mygw[1], mygw[2], mygw[3]);
		let mut routes = Routes::new(BTreeMap::new());
		routes.add_default_ipv4_route(default_v4_gw).unwrap();

		info!("MAC address {}", ethernet_addr);
		info!("Configure network interface with address {}", ip_addrs[0]);
		info!("Configure gateway with address {}", default_v4_gw);
		info!("MTU: {} bytes", mtu);

		let iface = EthernetInterfaceBuilder::new(device)
			.ethernet_addr(ethernet_addr)
			.neighbor_cache(neighbor_cache)
			.ip_addrs(ip_addrs)
			.routes(routes)
			.finalize();

		NetworkState::Initialized(Self {
			iface,
			sockets: SocketSet::new(vec![]),
			waker: WakerRegistration::new(),
		})
	}
}

impl<'a> Device<'a> for HermitNet {
	type RxToken = RxToken;
	type TxToken = TxToken;

	fn capabilities(&self) -> DeviceCapabilities {
		let mut cap = DeviceCapabilities::default();
		cap.max_transmission_unit = self.mtu.into();
		cap
	}

	fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
		match unsafe { sys_receive_rx_buffer() } {
			Ok((buffer, handle)) => Some((RxToken::new(buffer, handle), TxToken::new())),
			_ => None,
		}
	}

	fn transmit(&'a mut self) -> Option<Self::TxToken> {
		trace!("create TxToken to transfer data");
		Some(TxToken::new())
	}
}

#[doc(hidden)]
pub(crate) struct RxToken {
	buffer: &'static mut [u8],
	handle: usize,
}

impl RxToken {
	pub(crate) fn new(buffer: &'static mut [u8], handle: usize) -> Self {
		Self { buffer, handle }
	}
}

impl phy::RxToken for RxToken {
	#[allow(unused_mut)]
	fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let result = f(self.buffer);
		if unsafe { sys_rx_buffer_consumed(self.handle).is_ok() } {
			result
		} else {
			Err(smoltcp::Error::Exhausted)
		}
	}
}

#[doc(hidden)]
pub(crate) struct TxToken;

impl TxToken {
	pub(crate) fn new() -> Self {
		Self {}
	}
}

impl phy::TxToken for TxToken {
	fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result<R>
	where
		F: FnOnce(&mut [u8]) -> smoltcp::Result<R>,
	{
		let (tx_buffer, handle) =
			unsafe { sys_get_tx_buffer(len).map_err(|_| smoltcp::Error::Exhausted)? };
		let tx_slice: &'static mut [u8] = unsafe { slice::from_raw_parts_mut(tx_buffer, len) };
		match f(tx_slice) {
			Ok(result) => {
				if unsafe { sys_send_tx_buffer(handle, len).is_ok() } {
					Ok(result)
				} else {
					Err(smoltcp::Error::Exhausted)
				}
			}
			Err(e) => {
				unsafe { sys_free_tx_buffer(handle) };
				Err(e)
			}
		}
	}
}
<|endoftext|>


<commit_before>use neb::ram::types::{Id, Value};
use neb::ram::cell::Cell;
use neb::client::transaction::{Transaction, TxnError};
use std::sync::Arc;

use super::{TEdge, EdgeType, EdgeError, EdgeAttributes};
use super::super::vertex::{Vertex};
use super::super::id_list::IdList;
use server::schema::{SchemaContainer, SchemaType};

pub trait BilateralEdge : TEdge {

    fn vertex_a_field() -> u64;
    fn vertex_b_field() -> u64;

    fn vertex_a(&self) -> &Id;
    fn vertex_b(&self) -> &Id;

    fn edge_a_field() -> u64;
    fn edge_b_field() -> u64;

    fn build_edge(a_field: Id, b_field: Id, schema_id: u32, cell: Option<Cell>) -> Self::Edge;
    fn edge_cell(&self) -> &Option<Cell>;
    fn schema_id(&self) -> u32;

    fn from_id_(
        vertex_id: &Id, vertex_field: u64,
        schema_id: u32, schemas: &Arc<SchemaContainer>, txn: &mut Transaction, id: &Id
    ) -> Result<Self::Edge, EdgeError> {
        let trace_cell = match txn.read(id) {
            Ok(Some(cell)) => cell,
            Ok(None) => return Err(EdgeError::CellNotFound),
            Err(e) => return Err(EdgeError::TransactionError(e))
        };
        let cell_schema_type = match schemas.schema_type(trace_cell.header.schema) {
            Some(t) => t, None => return Err(EdgeError::CannotFindSchema)
        };
        let mut a_id = Id::unit_id();
        let mut b_id = Id::unit_id();
        let edge_cell = match cell_schema_type {
            SchemaType::Vertex => {
                if vertex_field == Self::vertex_a_field() {
                    a_id = *vertex_id;
                    b_id = *id;
                } else if vertex_field == Self::vertex_b_field() {
                    b_id = *vertex_id;
                    a_id = *id;
                } else {
                    return Err(EdgeError::WrongVertexField);
                }
                None
            },
            SchemaType::Edge(edge_attrs) => {
                if edge_attrs.edge_type == Self::edge_type() {
                    if let (
                        &Value::Id(e_a_id),
                        &Value::Id(e_b_id)
                    ) = (
                        &trace_cell.data[Self::edge_a_field()],
                        &trace_cell.data[Self::edge_b_field()]
                    ) {
                        a_id = e_a_id;
                        b_id = e_b_id;
                    }
                    Some(trace_cell)
                } else {
                    return Err(EdgeError::WrongEdgeType)
                }
            },
            _ => return Err(EdgeError::WrongSchema)
        };
        Ok(Self::build_edge(a_id, b_id, schema_id, edge_cell))
    }
    fn link_(
        vertex_a_id: &Id, vertex_b_id: &Id, body: Option<Cell>,
        txn: &mut Transaction,
        schema_id: u32, schemas: &Arc<SchemaContainer>
    ) -> Result<Self::Edge, EdgeError> {
        let mut vertex_a_pointer = Id::unit_id();
        let mut vertex_b_pointer = Id::unit_id();
        let edge_cell = {
            if let Some(SchemaType::Edge(ea)) = schemas.schema_type(schema_id) {
                if ea.edge_type != Self::edge_type() { return Err(EdgeError::WrongSchema); }
                if ea.has_body {
                    if let Some(mut body_cell) = body {
                        body_cell.header.set_id(&Id::rand());
                        body_cell.data[Self::edge_a_field()] = Value::Id(*vertex_a_id);
                        body_cell.data[Self::edge_b_field()] = Value::Id(*vertex_b_id);
                        txn.write(&body_cell).map_err(EdgeError::TransactionError)?;
                        vertex_a_pointer = body_cell.id();
                        vertex_b_pointer = body_cell.id();
                        Some(body_cell)
                    } else {
                        return Err(EdgeError::NormalEdgeShouldHaveBody);
                    }
                } else {
                    if body.is_none() {
                        vertex_a_pointer = *vertex_b_id;
                        vertex_b_pointer = *vertex_a_id;
                        None
                    } else {
                        return Err(EdgeError::SimpleEdgeShouldHaveNoBody);
                    }
                }
            } else { return Err(EdgeError::WrongSchema) }
        };
        IdList::from_txn_and_container(txn, vertex_a_id, Self::vertex_a_field(), schema_id)
            .add(&vertex_a_pointer).map_err(EdgeError::IdListError)?;
        IdList::from_txn_and_container(txn, vertex_b_id, Self::vertex_b_field(), schema_id)
            .add(&vertex_b_pointer).map_err(EdgeError::IdListError)?;
        Ok(Self::build_edge(*vertex_a_id, *vertex_b_id, schema_id, edge_cell))
    }
    fn delete_edge_(&mut self, txn: &mut Transaction) -> Result<(), EdgeError> {
        let (v_a_removal, v_b_removal) = match self.edge_cell() {
            &Some(ref cell) => {
                txn.remove(&cell.id()).map_err(EdgeError::TransactionError)?;
                (cell.id(), cell.id())
            },
            &None => {
                (*self.vertex_b(), *self.vertex_a())
            }
        };
        let schema_id = self.schema_id();
        IdList::from_txn_and_container(txn, self.vertex_a(), Self::vertex_a_field(), self.schema_id())
            .remove(&v_a_removal, false).map_err(EdgeError::IdListError)?;
        IdList::from_txn_and_container(txn, self.vertex_b(), Self::vertex_b_field(), self.schema_id())
            .remove(&v_b_removal, false).map_err(EdgeError::IdListError)?;
        Ok(())
    }
}<commit_msg>refactor for more meanful result<commit_after>use neb::ram::types::{Id, Value};
use neb::ram::cell::Cell;
use neb::client::transaction::{Transaction, TxnError};
use neb::utils::rand;
use std::sync::Arc;

use super::{TEdge, EdgeType, EdgeError, EdgeAttributes};
use super::super::vertex::{Vertex};
use super::super::id_list::IdList;
use server::schema::{SchemaContainer, SchemaType};

pub trait BilateralEdge : TEdge {

    fn vertex_a_field() -> u64;
    fn vertex_b_field() -> u64;

    fn vertex_a(&self) -> &Id;
    fn vertex_b(&self) -> &Id;

    fn edge_a_field() -> u64;
    fn edge_b_field() -> u64;

    fn build_edge(a_field: Id, b_field: Id, schema_id: u32, cell: Option<Cell>) -> Self::Edge;
    fn edge_cell(&self) -> &Option<Cell>;
    fn schema_id(&self) -> u32;

    fn from_id_(
        vertex_id: &Id, vertex_field: u64,
        schema_id: u32, schemas: &Arc<SchemaContainer>, txn: &mut Transaction, id: &Id
    ) -> Result<Self::Edge, EdgeError> {
        let trace_cell = match txn.read(id) {
            Ok(Some(cell)) => cell,
            Ok(None) => return Err(EdgeError::CellNotFound),
            Err(e) => return Err(EdgeError::TransactionError(e))
        };
        let cell_schema_type = match schemas.schema_type(trace_cell.header.schema) {
            Some(t) => t, None => return Err(EdgeError::CannotFindSchema)
        };
        let mut a_id = Id::unit_id();
        let mut b_id = Id::unit_id();
        let edge_cell = match cell_schema_type {
            SchemaType::Vertex => {
                if vertex_field == Self::vertex_a_field() {
                    a_id = *vertex_id;
                    b_id = *id;
                } else if vertex_field == Self::vertex_b_field() {
                    b_id = *vertex_id;
                    a_id = *id;
                } else {
                    return Err(EdgeError::WrongVertexField);
                }
                None
            },
            SchemaType::Edge(edge_attrs) => {
                if edge_attrs.edge_type == Self::edge_type() {
                    if let (
                        &Value::Id(e_a_id),
                        &Value::Id(e_b_id)
                    ) = (
                        &trace_cell.data[Self::edge_a_field()],
                        &trace_cell.data[Self::edge_b_field()]
                    ) {
                        a_id = e_a_id;
                        b_id = e_b_id;
                    }
                    Some(trace_cell)
                } else {
                    return Err(EdgeError::WrongEdgeType)
                }
            },
            _ => return Err(EdgeError::WrongSchema)
        };
        Ok(Self::build_edge(a_id, b_id, schema_id, edge_cell))
    }
    fn link_(
        vertex_a_id: &Id, vertex_b_id: &Id, body: Option<Cell>,
        txn: &mut Transaction,
        schema_id: u32, schemas: &Arc<SchemaContainer>
    ) -> Result<Self::Edge, EdgeError> {
        let mut vertex_a_pointer = Id::unit_id();
        let mut vertex_b_pointer = Id::unit_id();
        let edge_cell = {
            match schemas.schema_type(schema_id) {
                Some(SchemaType::Edge(ea)) => {
                    if ea.edge_type != Self::edge_type() { return Err(EdgeError::WrongEdgeType); }
                    if ea.has_body {
                        if let Some(mut body_cell) = body {
                            body_cell.header.set_id(&Id::new(vertex_a_id.higher, rand::next()));
                            body_cell.header.schema = schema_id;
                            body_cell.data[Self::edge_a_field()] = Value::Id(*vertex_a_id);
                            body_cell.data[Self::edge_b_field()] = Value::Id(*vertex_b_id);
                            txn.write(&body_cell).map_err(EdgeError::TransactionError)?;
                            vertex_a_pointer = body_cell.id();
                            vertex_b_pointer = body_cell.id();
                            Some(body_cell)
                        } else {
                            return Err(EdgeError::NormalEdgeShouldHaveBody);
                        }
                    } else {
                        if body.is_none() {
                            vertex_a_pointer = *vertex_b_id;
                            vertex_b_pointer = *vertex_a_id;
                            None
                        } else {
                            return Err(EdgeError::SimpleEdgeShouldHaveNoBody);
                        }
                    }
                },
                Some(_) => return Err(EdgeError::WrongSchema),
                None => return Err(EdgeError::CannotFindSchema)
            }
        };
        IdList::from_txn_and_container(txn, vertex_a_id, Self::vertex_a_field(), schema_id)
            .add(&vertex_a_pointer).map_err(EdgeError::IdListError)?;
        IdList::from_txn_and_container(txn, vertex_b_id, Self::vertex_b_field(), schema_id)
            .add(&vertex_b_pointer).map_err(EdgeError::IdListError)?;
        Ok(Self::build_edge(*vertex_a_id, *vertex_b_id, schema_id, edge_cell))
    }
    fn delete_edge_(&mut self, txn: &mut Transaction) -> Result<(), EdgeError> {
        let (v_a_removal, v_b_removal) = match self.edge_cell() {
            &Some(ref cell) => {
                txn.remove(&cell.id()).map_err(EdgeError::TransactionError)?;
                (cell.id(), cell.id())
            },
            &None => {
                (*self.vertex_b(), *self.vertex_a())
            }
        };
        let schema_id = self.schema_id();
        IdList::from_txn_and_container(txn, self.vertex_a(), Self::vertex_a_field(), self.schema_id())
            .remove(&v_a_removal, false).map_err(EdgeError::IdListError)?;
        IdList::from_txn_and_container(txn, self.vertex_b(), Self::vertex_b_field(), self.schema_id())
            .remove(&v_b_removal, false).map_err(EdgeError::IdListError)?;
        Ok(())
    }
}<|endoftext|>


<commit_before>extern crate gstreamer as gst;
extern crate gstreamer_audio as gst_audio;

use std::any::Any;

use std::mem;

use std::sync::{Arc, Mutex};

use super::{AudioBuffer, AudioChannel, SampleExtractor};

const EXTRACTION_THRESHOLD: usize = 1024;

// The DoubleBuffer is reponsible for ensuring a thread safe double buffering
// mechanism that receives samples from GStreamer, prepares an extraction of
// these samples and presents the most recent extraction to an external
// mechanism (e.g. UI).
// The DoubleBuffer hosts two SampleExtractors and an AudioBuffer:
//   - The SampleExtractor trait is designed to allow the extraction of samples
//   depending on certains conditions as defined in its concrete implementation.
//   - The AudioBuffer manages the container for all the samples received.
// The DoubleBuffer prepares the extraction in the working_buffer and exposes
// the exposed_buffer during that time. When the extration is done, the buffers
// are swapped.
pub struct DoubleAudioBuffer {
    audio_buffer: AudioBuffer,
    samples_since_last_extract: usize,
    exposed_buffer_mtx: Arc<Mutex<Box<SampleExtractor>>>,
    working_buffer: Option<Box<SampleExtractor>>,
    lower_to_keep: usize,
}

impl DoubleAudioBuffer {
    // need 2 arguments for new as we can't clone buffers as they are known
    // as trait SampleExtractor
    pub fn new(
        buffer_duration: u64,
        exposed_buffer: Box<SampleExtractor>,
        working_buffer: Box<SampleExtractor>
    ) -> DoubleAudioBuffer {
        DoubleAudioBuffer {
            audio_buffer: AudioBuffer::new(buffer_duration),
            samples_since_last_extract: 0,
            exposed_buffer_mtx: Arc::new(Mutex::new(exposed_buffer)),
            working_buffer: Some(working_buffer),
            lower_to_keep: 0,
        }
    }

    // Get a reference on the exposed buffer mutex.
    pub fn get_exposed_buffer_mtx(&self) -> Arc<Mutex<Box<SampleExtractor>>> {
        Arc::clone(&self.exposed_buffer_mtx)
    }

    pub fn cleanup(&mut self) {
        self.audio_buffer.cleanup();
        self.samples_since_last_extract = 0;

        {
            let exposed_buffer = &mut self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer: couldn't lock exposed_buffer_mtx while setting audio sink");
            exposed_buffer.cleanup();
        }

        self.working_buffer.as_mut()
            .expect("DoubleAudioBuffer: couldn't get working_buffer while setting audio sink")
            .cleanup();
        self.lower_to_keep = 0;
    }

    // Initialize buffer with audio stream capabilities
    // and GStreamer element for position reference
    pub fn set_audio_caps_and_ref(&mut self,
        caps: &gst::Caps,
        audio_ref: &gst::Element
    ) {
        let audio_info = gst_audio::AudioInfo::from_caps(&caps)
            .expect("DoubleAudioBuffer::set_audio_caps_and_ref unable to get AudioInfo");

        let rate = audio_info.rate() as u64;
        let channels = audio_info.channels() as usize;
        self.audio_buffer.init(rate, channels);

        let sample_duration = 1_000_000_000 / rate;
        let duration_for_1000_samples = 1_000_000_000_000f64 / (rate as f64);

        let mut channels: Vec<AudioChannel> = Vec::with_capacity(channels);
        if let Some(positions) = audio_info.positions() {
            for position in positions {
                channels.push(AudioChannel::new(position));
            }
        };

        {
            let exposed_buffer = &mut self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer: couldn't lock exposed_buffer_mtx while setting audio sink");
            exposed_buffer.set_audio_sink(audio_ref.clone());
            exposed_buffer.set_sample_duration(sample_duration, duration_for_1000_samples);
            exposed_buffer.set_channels(&channels);
        }

        let working_buffer = self.working_buffer.as_mut()
            .expect("DoubleAudioBuffer: couldn't get working_buffer while setting audio sink");
        working_buffer.set_audio_sink(audio_ref.clone());
        working_buffer.set_sample_duration(sample_duration, duration_for_1000_samples);
        working_buffer.set_channels(&channels);
    }

    pub fn handle_eos(&mut self) {
        self.audio_buffer.handle_eos();
        // extract last samples and swap
        self.extract_samples();
        // update second buffer too
        self.extract_samples();
    }

    pub fn push_gst_sample(&mut self, sample: gst::Sample) {
        // store incoming samples
        self.samples_since_last_extract +=
            self.audio_buffer.push_gst_sample(sample, self.lower_to_keep);

        if self.samples_since_last_extract >= EXTRACTION_THRESHOLD {
            // extract new samples and swap
            self.extract_samples();
            self.samples_since_last_extract = 0;
        }
    }

    // Update the working extractor with new samples and swap.
    pub fn extract_samples(&mut self) {
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::extract_samples: failed to take working buffer");
        working_buffer.extract_samples(&self.audio_buffer);

        // swap buffers
        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer::extract_samples: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            // in order to smoothen rendering between frames
            working_buffer.update_concrete_state(exposed_buffer_box);
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }

    pub fn refresh(&mut self) {
        // refresh with current conditions
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::refresh: failed to take working buffer");

        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer:::refresh: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            working_buffer.update_concrete_state(exposed_buffer_box);

            // refresh working buffer
            working_buffer.refresh(&self.audio_buffer);

            // swap buffers
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }

    // Refresh the working buffer with the provided conditions and swap.
    // Conditions concrete type must conform to a struct expected
    // by the concrete implementation of the SampleExtractor.
    pub fn refresh_with_conditions<T: Any + Clone>(&mut self, conditions: Box<T>) {
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::refresh: failed to take working buffer");

        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer:::refresh: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            working_buffer.update_concrete_state(exposed_buffer_box);

            // refresh working buffer
            working_buffer.refresh_with_conditions(&self.audio_buffer, conditions.clone());

            // swap buffers
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        // working buffer is last exposed buffer
        // refresh with new conditions
        working_buffer.refresh_with_conditions(&self.audio_buffer, conditions);

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }
}
<commit_msg>DoubleAudioBuffer: update only one buffer at EOS (#58) The other buffer will be refreshed before being presented anyway.<commit_after>extern crate gstreamer as gst;
extern crate gstreamer_audio as gst_audio;

use std::any::Any;

use std::mem;

use std::sync::{Arc, Mutex};

use super::{AudioBuffer, AudioChannel, SampleExtractor};

const EXTRACTION_THRESHOLD: usize = 1024;

// The DoubleBuffer is reponsible for ensuring a thread safe double buffering
// mechanism that receives samples from GStreamer, prepares an extraction of
// these samples and presents the most recent extraction to an external
// mechanism (e.g. UI).
// The DoubleBuffer hosts two SampleExtractors and an AudioBuffer:
//   - The SampleExtractor trait is designed to allow the extraction of samples
//   depending on certains conditions as defined in its concrete implementation.
//   - The AudioBuffer manages the container for all the samples received.
// The DoubleBuffer prepares the extraction in the working_buffer and exposes
// the exposed_buffer during that time. When the extration is done, the buffers
// are swapped.
pub struct DoubleAudioBuffer {
    audio_buffer: AudioBuffer,
    samples_since_last_extract: usize,
    exposed_buffer_mtx: Arc<Mutex<Box<SampleExtractor>>>,
    working_buffer: Option<Box<SampleExtractor>>,
    lower_to_keep: usize,
}

impl DoubleAudioBuffer {
    // need 2 arguments for new as we can't clone buffers as they are known
    // as trait SampleExtractor
    pub fn new(
        buffer_duration: u64,
        exposed_buffer: Box<SampleExtractor>,
        working_buffer: Box<SampleExtractor>
    ) -> DoubleAudioBuffer {
        DoubleAudioBuffer {
            audio_buffer: AudioBuffer::new(buffer_duration),
            samples_since_last_extract: 0,
            exposed_buffer_mtx: Arc::new(Mutex::new(exposed_buffer)),
            working_buffer: Some(working_buffer),
            lower_to_keep: 0,
        }
    }

    // Get a reference on the exposed buffer mutex.
    pub fn get_exposed_buffer_mtx(&self) -> Arc<Mutex<Box<SampleExtractor>>> {
        Arc::clone(&self.exposed_buffer_mtx)
    }

    pub fn cleanup(&mut self) {
        self.audio_buffer.cleanup();
        self.samples_since_last_extract = 0;

        {
            let exposed_buffer = &mut self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer: couldn't lock exposed_buffer_mtx while setting audio sink");
            exposed_buffer.cleanup();
        }

        self.working_buffer.as_mut()
            .expect("DoubleAudioBuffer: couldn't get working_buffer while setting audio sink")
            .cleanup();
        self.lower_to_keep = 0;
    }

    // Initialize buffer with audio stream capabilities
    // and GStreamer element for position reference
    pub fn set_audio_caps_and_ref(&mut self,
        caps: &gst::Caps,
        audio_ref: &gst::Element
    ) {
        let audio_info = gst_audio::AudioInfo::from_caps(&caps)
            .expect("DoubleAudioBuffer::set_audio_caps_and_ref unable to get AudioInfo");

        let rate = audio_info.rate() as u64;
        let channels = audio_info.channels() as usize;
        self.audio_buffer.init(rate, channels);

        let sample_duration = 1_000_000_000 / rate;
        let duration_for_1000_samples = 1_000_000_000_000f64 / (rate as f64);

        let mut channels: Vec<AudioChannel> = Vec::with_capacity(channels);
        if let Some(positions) = audio_info.positions() {
            for position in positions {
                channels.push(AudioChannel::new(position));
            }
        };

        {
            let exposed_buffer = &mut self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer: couldn't lock exposed_buffer_mtx while setting audio sink");
            exposed_buffer.set_audio_sink(audio_ref.clone());
            exposed_buffer.set_sample_duration(sample_duration, duration_for_1000_samples);
            exposed_buffer.set_channels(&channels);
        }

        let working_buffer = self.working_buffer.as_mut()
            .expect("DoubleAudioBuffer: couldn't get working_buffer while setting audio sink");
        working_buffer.set_audio_sink(audio_ref.clone());
        working_buffer.set_sample_duration(sample_duration, duration_for_1000_samples);
        working_buffer.set_channels(&channels);
    }

    pub fn handle_eos(&mut self) {
        self.audio_buffer.handle_eos();
        // extract last samples and swap
        self.extract_samples();
    }

    pub fn push_gst_sample(&mut self, sample: gst::Sample) {
        // store incoming samples
        self.samples_since_last_extract +=
            self.audio_buffer.push_gst_sample(sample, self.lower_to_keep);

        if self.samples_since_last_extract >= EXTRACTION_THRESHOLD {
            // extract new samples and swap
            self.extract_samples();
            self.samples_since_last_extract = 0;
        }
    }

    // Update the working extractor with new samples and swap.
    pub fn extract_samples(&mut self) {
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::extract_samples: failed to take working buffer");
        working_buffer.extract_samples(&self.audio_buffer);

        // swap buffers
        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer::extract_samples: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            // in order to smoothen rendering between frames
            working_buffer.update_concrete_state(exposed_buffer_box);
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }

    pub fn refresh(&mut self) {
        // refresh with current conditions
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::refresh: failed to take working buffer");

        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer:::refresh: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            working_buffer.update_concrete_state(exposed_buffer_box);

            // refresh working buffer
            working_buffer.refresh(&self.audio_buffer);

            // swap buffers
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }

    // Refresh the working buffer with the provided conditions and swap.
    // Conditions concrete type must conform to a struct expected
    // by the concrete implementation of the SampleExtractor.
    pub fn refresh_with_conditions<T: Any + Clone>(&mut self, conditions: Box<T>) {
        let mut working_buffer = self.working_buffer.take()
            .expect("DoubleAudioBuffer::refresh: failed to take working buffer");

        {
            let exposed_buffer_box = &mut *self.exposed_buffer_mtx.lock()
                .expect("DoubleAudioBuffer:::refresh: failed to lock the exposed buffer");
            // get latest state from the previously exposed buffer
            working_buffer.update_concrete_state(exposed_buffer_box);

            // refresh working buffer
            working_buffer.refresh_with_conditions(&self.audio_buffer, conditions.clone());

            // swap buffers
            mem::swap(exposed_buffer_box, &mut working_buffer);
        }

        // working buffer is last exposed buffer
        // refresh with new conditions
        working_buffer.refresh_with_conditions(&self.audio_buffer, conditions);

        self.lower_to_keep = working_buffer.get_lower();

        self.working_buffer = Some(working_buffer);
        // self.working_buffer is now the buffer previously in
        // self.exposed_buffer_mtx
    }
}
<|endoftext|>


<commit_before>//! Conversions to different `Term` encodings

#![allow(missing_docs)]

use term::{Term, abs, app};
use term::Term::*;
use data::boolean::{fls, tru};

macro_rules! make_trait {
    ($trait_name:ident, $function_name:ident) => (
        pub trait $trait_name {
            #[doc="Performs the conversion."]
            fn $function_name(self) -> Term;
        }
    );
}

make_trait!(IntoChurch, into_church);

impl IntoChurch for usize {
    fn into_church(self) -> Term {
        let mut ret = Var(1);

        for _ in 0..self {
            ret = app(Var(2), ret);
        }

        abs!(2, ret)
    }
}

impl<T, U> IntoChurch for (T, U) where T: IntoChurch, U: IntoChurch {
    fn into_church(self) -> Term {
        abs(app!(Var(1), self.0.into_church(), self.1.into_church()))
    }
}

impl<T> IntoChurch for Vec<T> where T: IntoChurch {
    fn into_church(self) -> Term {
        let mut ret = fls();

        for term in self.into_iter().rev() {
            ret = abs(app!(Var(1), term.into_church(), ret))
        }

        ret
    }
}

impl<T> IntoChurch for Option<T> where T: IntoChurch {
    fn into_church(self) -> Term {
        match self {
            None => tru(),
            Some(value) => abs!(2, app(Var(1), value.into_church()))
        }
    }
}

make_trait!(IntoScott, into_scott);

impl IntoScott for usize {
    fn into_scott(self) -> Term {
        let mut ret = abs!(2, Var(2));

        for _ in 0..self {
            ret = abs!(2, app(Var(1), ret));
        }

        ret
    }
}

make_trait!(IntoParigot, into_parigot);

impl IntoParigot for usize {
    fn into_parigot(self) -> Term {
        let mut ret = abs!(2, Var(1));

        for _ in 0..self {
            ret = abs!(2, app!(Var(2), ret.clone(), ret.unabs().and_then(|r| r.unabs()).unwrap()));
        }

        ret
    }
}

make_trait!(IntoStumpFu, into_stumpfu);

impl IntoStumpFu for usize {
    fn into_stumpfu(self) -> Term {
        let mut ret = abs!(2, Var(1));

        for n in 1..self+1 {
            ret = abs!(2, app!(Var(2), n.into_church(), ret));
        }

        ret
    }
}
<commit_msg>generate implementations with a macro<commit_after>//! Conversions to different `Term` encodings

#![allow(missing_docs)]

use term::{Term, abs, app};
use term::Term::*;

macro_rules! make_trait {
    ($trait_name:ident, $function_name:ident) => (
        pub trait $trait_name {
            #[doc="Performs the conversion."]
            fn $function_name(self) -> Term;
        }
    );
}

make_trait!(IntoChurch, into_church);
make_trait!(IntoScott, into_scott);
make_trait!(IntoParigot, into_parigot);
make_trait!(IntoStumpFu, into_stumpfu);

impl IntoChurch for usize {
    fn into_church(self) -> Term {
        let mut ret = Var(1);

        for _ in 0..self {
            ret = app(Var(2), ret);
        }

        abs!(2, ret)
    }
}

impl IntoScott for usize {
    fn into_scott(self) -> Term {
        let mut ret = abs!(2, Var(2));

        for _ in 0..self {
            ret = abs!(2, app(Var(1), ret));
        }

        ret
    }
}

impl IntoParigot for usize {
    fn into_parigot(self) -> Term {
        let mut ret = abs!(2, Var(1));

        for _ in 0..self {
            ret = abs!(2, app!(Var(2), ret.clone(), ret.unabs().and_then(|r| r.unabs()).unwrap()));
        }

        ret
    }
}

impl IntoStumpFu for usize {
    fn into_stumpfu(self) -> Term {
        let mut ret = abs!(2, Var(1));

        for n in 1..self+1 {
            ret = abs!(2, app!(Var(2), n.into_church(), ret));
        }

        ret
    }
}

macro_rules! impl_pair {
    ($trait_name:ident, $function_name:ident) => (
        impl<T, U> $trait_name for (T, U) where T: $trait_name, U: $trait_name {
            fn $function_name(self) -> Term {
                abs(app!(Var(1), (self.0).$function_name(), (self.1).$function_name()))
            }
        }
    );
}

impl_pair!(IntoChurch, into_church);
impl_pair!(IntoScott, into_scott);
impl_pair!(IntoParigot, into_parigot);
impl_pair!(IntoStumpFu, into_stumpfu);

macro_rules! impl_list {
    ($trait_name:ident, $function_name:ident) => (
        impl<T> $trait_name for Vec<T> where T: $trait_name {
            fn $function_name(self) -> Term {
                let mut ret = abs!(2, Var(1));

                for term in self.into_iter().rev() {
                    ret = abs(app!(Var(1), term.$function_name(), ret))
                }

                ret
            }
        }
    );
}

impl_list!(IntoChurch, into_church);
impl_list!(IntoScott, into_scott);
impl_list!(IntoParigot, into_parigot);
impl_list!(IntoStumpFu, into_stumpfu);

macro_rules! impl_option {
    ($trait_name:ident, $function_name:ident) => (
        impl<T> $trait_name for Option<T> where T: $trait_name {
            fn $function_name(self) -> Term {
                match self {
                    None => abs!(2, Var(2)),
                    Some(value) => abs!(2, app(Var(1), value.$function_name()))
                }
            }
        }
    );
}

impl_option!(IntoChurch, into_church);
impl_option!(IntoScott, into_scott);
impl_option!(IntoParigot, into_parigot);
impl_option!(IntoStumpFu, into_stumpfu);
<|endoftext|>


<commit_before>use crate::shapes::{GeoKind, Shape, StateOfShape};
use crate::util::SQRT_2;
use crate::StrError;
use russell_lab::{mat_mat_mul, mat_t_mat_mul, Matrix};
use russell_tensor::LinElasticity;

/// Performs analytical integrations on a Tri3
pub struct AnalyticalTri3 {
    // Holds the b-coefficients
    pub b: [f64; 3],

    // Holds the c-coefficients
    pub c: [f64; 3],

    // Holds the area of the triangle
    pub area: f64,

    /// Holds the gradients
    pub gg: Matrix,

    /// Holds the B-matrix
    pub bb: Matrix,
}

impl AnalyticalTri3 {
    pub fn new(shape: &Shape, state: &StateOfShape) -> Self {
        assert_eq!(shape.kind, GeoKind::Tri3);

        // coefficients
        let (x0, y0) = (state.coords_transp[0][0], state.coords_transp[1][0]);
        let (x1, y1) = (state.coords_transp[0][1], state.coords_transp[1][1]);
        let (x2, y2) = (state.coords_transp[0][2], state.coords_transp[1][2]);
        let (b0, b1, b2) = (y1 - y2, y2 - y0, y0 - y1);
        let (c0, c1, c2) = (x2 - x1, x0 - x2, x1 - x0);
        let (f0, f1, f2) = (x1 * y2 - x2 * y1, x2 * y0 - x0 * y2, x0 * y1 - x1 * y0);

        // area
        let area = (f0 + f1 + f2) / 2.0;

        // gradients
        let gg = Matrix::from(&[
            [b0 / (2.0 * area), c0 / (2.0 * area)],
            [b1 / (2.0 * area), c1 / (2.0 * area)],
            [b2 / (2.0 * area), c2 / (2.0 * area)],
        ]);

        // B-matrix
        let r = 2.0 * area;
        let s = r * SQRT_2;
        #[rustfmt::skip]
        let bb = Matrix::from(&[
            [b0/r,  0.0, b1/r,  0.0, b2/r,  0.0],
            [ 0.0, c0/r,  0.0, c1/r,  0.0, c2/r],
            [ 0.0,  0.0,  0.0,  0.0,  0.0,  0.0],
            [c0/s, b0/s, c1/s, b1/s, c2/s, b2/s],
        ]);

        // results
        AnalyticalTri3 {
            b: [b0, b1, b2],
            c: [c0, c1, c2],
            area,
            gg,
            bb,
        }
    }

    /// Performs the integ_vec_c operation given constant vector function w(x) = {w₀, w₁}
    ///
    /// solution:
    /// ```text
    /// cᵐ = ½ (w₀ bₘ + w₁ cₘ)
    /// ```
    ///
    /// # Input
    ///
    /// * `(w0,w1)` -- components of a constant vector function: w(x) = {w₀, w₁}
    pub fn integ_vec_c_constant(&self, w0: f64, w1: f64) -> Vec<f64> {
        vec![
            (w0 * self.b[0] + w1 * self.c[0]) / 2.0,
            (w0 * self.b[1] + w1 * self.c[1]) / 2.0,
            (w0 * self.b[2] + w1 * self.c[2]) / 2.0,
        ]
    }

    /// Performs the integ_vec_c operation given bilinear vector function w(x) = {x, y}
    ///
    /// solution:
    /// ```text
    /// cᵐ = ⅙ bₘ (x₀+x₁+x₂) + ⅙ cₘ (y₀+y₁+y₂)
    /// ```
    ///
    /// # Input
    ///
    /// * `shape` -- the same shape used in `new` because we need the nodal coordinates here
    pub fn integ_vec_c_bilinear(&self, state: &StateOfShape) -> Vec<f64> {
        let (x0, x1, x2) = (
            state.coords_transp[0][0],
            state.coords_transp[0][1],
            state.coords_transp[0][2],
        );
        let (y0, y1, y2) = (
            state.coords_transp[1][0],
            state.coords_transp[1][1],
            state.coords_transp[1][2],
        );
        let ana = self;
        vec![
            (x0 + x1 + x2) * ana.b[0] / 6.0 + (y0 + y1 + y2) * ana.c[0] / 6.0,
            (x0 + x1 + x2) * ana.b[1] / 6.0 + (y0 + y1 + y2) * ana.c[1] / 6.0,
            (x0 + x1 + x2) * ana.b[2] / 6.0 + (y0 + y1 + y2) * ana.c[2] / 6.0,
        ]
    }

    /// Performs the integ_vec_d operation given constant tensor function σ(x) = {σ₀₀, σ₁₁, σ₂₂, σ₀₁√2}
    ///
    /// solution:
    /// ```text
    /// dᵐ₀ = ½ (σ₀₀ bₘ + σ₀₁ cₘ)
    /// dᵐ₁ = ½ (σ₁₀ bₘ + σ₁₁ cₘ)
    /// ```
    ///
    /// # Input
    ///
    /// * `s₀₀, s₁₁, s₀₁` -- components of a constant tensor function: σ(x) = {σ₀₀, σ₁₁, σ₂₂, σ₀₁√2}
    pub fn integ_vec_d_constant(&self, s00: f64, s11: f64, s01: f64) -> Vec<f64> {
        let ana = self;
        vec![
            (s00 * ana.b[0] + s01 * ana.c[0]) / 2.0,
            (s01 * ana.b[0] + s11 * ana.c[0]) / 2.0,
            (s00 * ana.b[1] + s01 * ana.c[1]) / 2.0,
            (s01 * ana.b[1] + s11 * ana.c[1]) / 2.0,
            (s00 * ana.b[2] + s01 * ana.c[2]) / 2.0,
            (s01 * ana.b[2] + s11 * ana.c[2]) / 2.0,
        ]
    }

    /// Calculates the stiffness matrix
    ///
    /// solution:
    ///
    /// ```text
    /// K = Bᵀ ⋅ D ⋅ B ⋅ th ⋅ area
    /// ```
    pub fn integ_stiffness(&self, young: f64, poisson: f64, plane_stress: bool, th: f64) -> Result<Matrix, StrError> {
        let ela = LinElasticity::new(young, poisson, true, plane_stress);
        let dd = ela.get_modulus();
        let dim_dd = 4;
        let dim_kk = 6;
        let mut bb_t_dd = Matrix::new(dim_kk, dim_dd);
        let mut kk = Matrix::new(dim_kk, dim_kk);
        mat_t_mat_mul(&mut bb_t_dd, 1.0, &self.bb, &dd.mat)?;
        mat_mat_mul(&mut kk, th * self.area, &bb_t_dd, &self.bb)?;
        Ok(kk)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::AnalyticalTri3;
    use crate::shapes::{Shape, StateOfShape};
    use crate::StrError;
    use russell_chk::{assert_approx_eq, assert_vec_approx_eq};

    #[test]
    fn new_works() -> Result<(), StrError> {
        // Tri3 # 1 from Figure 1.18, page 29 of [@bhatti]
        //
        // [@bhatti] Bhatti, M.A. (2005) Fundamental Finite Element Analysis
        //          and Applications, Wiley, 700p.
        //
        let shape = Shape::new(2, 2, 3)?;
        let mut state = StateOfShape::new(shape.geo_ndim, &[[0.0, 0.0], [0.2, 0.0], [0.1, 0.1]])?;
        let ana = AnalyticalTri3::new(&shape, &mut state);
        assert_approx_eq!(ana.area, 0.01, 1e-15);
        assert_vec_approx_eq!(ana.b, [-0.1, 0.1, 0.0], 1e-15);
        assert_vec_approx_eq!(ana.c, [-0.1, -0.1, 0.2], 1e-15);
        Ok(())
    }
}
<commit_msg>Organize code in analytical tri3<commit_after>use crate::shapes::{GeoKind, Shape, StateOfShape};
use crate::util::SQRT_2;
use crate::StrError;
use russell_lab::{mat_mat_mul, mat_t_mat_mul, Matrix};
use russell_tensor::LinElasticity;

/// Performs analytical integrations on a Tri3
pub struct AnalyticalTri3 {
    // Holds the b-coefficients
    pub b: [f64; 3],

    // Holds the c-coefficients
    pub c: [f64; 3],

    // Holds the area of the triangle
    pub area: f64,

    /// Holds the gradients
    pub gg: Matrix,

    /// Holds the B-matrix
    pub bb: Matrix,
}

impl AnalyticalTri3 {
    pub fn new(shape: &Shape, state: &StateOfShape) -> Self {
        assert_eq!(shape.kind, GeoKind::Tri3);

        // coefficients
        let (x0, y0) = (state.coords_transp[0][0], state.coords_transp[1][0]);
        let (x1, y1) = (state.coords_transp[0][1], state.coords_transp[1][1]);
        let (x2, y2) = (state.coords_transp[0][2], state.coords_transp[1][2]);
        let (b0, b1, b2) = (y1 - y2, y2 - y0, y0 - y1);
        let (c0, c1, c2) = (x2 - x1, x0 - x2, x1 - x0);
        let (f0, f1, f2) = (x1 * y2 - x2 * y1, x2 * y0 - x0 * y2, x0 * y1 - x1 * y0);

        // area
        let area = (f0 + f1 + f2) / 2.0;

        // auxiliary
        let r = 2.0 * area;
        let s = r * SQRT_2;

        // gradients
        #[rustfmt::skip]
        let gg = Matrix::from(&[
            [b0/r, c0/r],
            [b1/r, c1/r],
            [b2/r, c2/r],
        ]);

        // B-matrix
        #[rustfmt::skip]
        let bb = Matrix::from(&[
            [b0/r,  0.0, b1/r,  0.0, b2/r,  0.0],
            [ 0.0, c0/r,  0.0, c1/r,  0.0, c2/r],
            [ 0.0,  0.0,  0.0,  0.0,  0.0,  0.0],
            [c0/s, b0/s, c1/s, b1/s, c2/s, b2/s],
        ]);

        // results
        AnalyticalTri3 {
            b: [b0, b1, b2],
            c: [c0, c1, c2],
            area,
            gg,
            bb,
        }
    }

    /// Performs the integ_vec_c operation given constant vector function w(x) = {w₀, w₁}
    ///
    /// solution:
    /// ```text
    /// cᵐ = ½ (w₀ bₘ + w₁ cₘ)
    /// ```
    ///
    /// # Input
    ///
    /// * `(w0,w1)` -- components of a constant vector function: w(x) = {w₀, w₁}
    pub fn integ_vec_c_constant(&self, w0: f64, w1: f64) -> Vec<f64> {
        vec![
            (w0 * self.b[0] + w1 * self.c[0]) / 2.0,
            (w0 * self.b[1] + w1 * self.c[1]) / 2.0,
            (w0 * self.b[2] + w1 * self.c[2]) / 2.0,
        ]
    }

    /// Performs the integ_vec_c operation given bilinear vector function w(x) = {x, y}
    ///
    /// solution:
    /// ```text
    /// cᵐ = ⅙ bₘ (x₀+x₁+x₂) + ⅙ cₘ (y₀+y₁+y₂)
    /// ```
    ///
    /// # Input
    ///
    /// * `shape` -- the same shape used in `new` because we need the nodal coordinates here
    pub fn integ_vec_c_bilinear(&self, state: &StateOfShape) -> Vec<f64> {
        let (x0, x1, x2) = (
            state.coords_transp[0][0],
            state.coords_transp[0][1],
            state.coords_transp[0][2],
        );
        let (y0, y1, y2) = (
            state.coords_transp[1][0],
            state.coords_transp[1][1],
            state.coords_transp[1][2],
        );
        let ana = self;
        vec![
            (x0 + x1 + x2) * ana.b[0] / 6.0 + (y0 + y1 + y2) * ana.c[0] / 6.0,
            (x0 + x1 + x2) * ana.b[1] / 6.0 + (y0 + y1 + y2) * ana.c[1] / 6.0,
            (x0 + x1 + x2) * ana.b[2] / 6.0 + (y0 + y1 + y2) * ana.c[2] / 6.0,
        ]
    }

    /// Performs the integ_vec_d operation given constant tensor function σ(x) = {σ₀₀, σ₁₁, σ₂₂, σ₀₁√2}
    ///
    /// solution:
    /// ```text
    /// dᵐ₀ = ½ (σ₀₀ bₘ + σ₀₁ cₘ)
    /// dᵐ₁ = ½ (σ₁₀ bₘ + σ₁₁ cₘ)
    /// ```
    ///
    /// # Input
    ///
    /// * `s₀₀, s₁₁, s₀₁` -- components of a constant tensor function: σ(x) = {σ₀₀, σ₁₁, σ₂₂, σ₀₁√2}
    pub fn integ_vec_d_constant(&self, s00: f64, s11: f64, s01: f64) -> Vec<f64> {
        let ana = self;
        vec![
            (s00 * ana.b[0] + s01 * ana.c[0]) / 2.0,
            (s01 * ana.b[0] + s11 * ana.c[0]) / 2.0,
            (s00 * ana.b[1] + s01 * ana.c[1]) / 2.0,
            (s01 * ana.b[1] + s11 * ana.c[1]) / 2.0,
            (s00 * ana.b[2] + s01 * ana.c[2]) / 2.0,
            (s01 * ana.b[2] + s11 * ana.c[2]) / 2.0,
        ]
    }

    /// Calculates the stiffness matrix
    ///
    /// solution:
    ///
    /// ```text
    /// K = Bᵀ ⋅ D ⋅ B ⋅ th ⋅ area
    /// ```
    pub fn integ_stiffness(&self, young: f64, poisson: f64, plane_stress: bool, th: f64) -> Result<Matrix, StrError> {
        let ela = LinElasticity::new(young, poisson, true, plane_stress);
        let dd = ela.get_modulus();
        let dim_dd = 4;
        let dim_kk = 6;
        let mut bb_t_dd = Matrix::new(dim_kk, dim_dd);
        let mut kk = Matrix::new(dim_kk, dim_kk);
        mat_t_mat_mul(&mut bb_t_dd, 1.0, &self.bb, &dd.mat)?;
        mat_mat_mul(&mut kk, th * self.area, &bb_t_dd, &self.bb)?;
        Ok(kk)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::AnalyticalTri3;
    use crate::shapes::{Shape, StateOfShape};
    use crate::StrError;
    use russell_chk::{assert_approx_eq, assert_vec_approx_eq};

    #[test]
    fn new_works() -> Result<(), StrError> {
        // Tri3 # 1 from Figure 1.18, page 29 of [@bhatti]
        //
        // [@bhatti] Bhatti, M.A. (2005) Fundamental Finite Element Analysis
        //          and Applications, Wiley, 700p.
        //
        let shape = Shape::new(2, 2, 3)?;
        let mut state = StateOfShape::new(shape.geo_ndim, &[[0.0, 0.0], [0.2, 0.0], [0.1, 0.1]])?;
        let ana = AnalyticalTri3::new(&shape, &mut state);
        assert_approx_eq!(ana.area, 0.01, 1e-15);
        assert_vec_approx_eq!(ana.b, [-0.1, 0.1, 0.0], 1e-15);
        assert_vec_approx_eq!(ana.c, [-0.1, -0.1, 0.2], 1e-15);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use dbus::arg::{Array};
use dbus::tree::MethodErr;
use dbus::MessageItem;

use ::ipc::utils::{parse_uuid, lock_tree_dbus};
use ::ipc::{DBusFactory, DBusObjPath};
use ::render::screen_scrape::{write_screen_scrape_lock, read_screen_scrape_lock,
                              scraped_pixels_lock, sync_scrape};

pub fn setup(f: &mut DBusFactory) -> DBusObjPath {
    f.object_path("/org/way_cooler/Screen", ()).introspectable().add(
        f.interface("org.way_cooler.Screen", ())
            .add_m(
                f.method("List", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let outputs = tree.outputs().iter()
                        .map(|id|
                             MessageItem::Str(format!("{}", id.simple())))
                        .collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(outputs, "s".into())))
                    ])
                }).outarg::<Array<String, Vec<String>>, _>("success")
            )
            .add_m(
                // TODO Make this take in a:
                // * Output UUID
                // * Size (u32, u32) to scrape. For invalid ones, we throw error
                f.method("Scrape", (), |m| {
                    *write_screen_scrape_lock() = true;
                    // ensure that no other threads can try to grab the pixels.
                    let _lock = read_screen_scrape_lock();
                    sync_scrape();
                    drop(_lock);
                    *write_screen_scrape_lock() = false;
                    let scraped_pixels = scraped_pixels_lock()
                        .expect("scraped_pixels lock was poisoned!");
                    let result = scraped_pixels.iter()
                        .map(|pixel| MessageItem::Byte(*pixel)).collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(result, "y".into())))])
                }).outarg::<Array<u8, Vec<u8>>, _>("success")
            )
            .add_m(
                f.method("Resolution", (), |m| {
                    let mut args_iter = m.msg.iter_init();
                    let output_id = args_iter.read::<String>()?;
                    let tree = lock_tree_dbus()?;
                    let uuid = parse_uuid("container_id", &output_id)?
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container"))?;
                    let size = tree.output_resolution(uuid)
                        .map_err(|err| {
                            MethodErr::failed(&format!("{:?}", err))
                        })?;
                    Ok(vec![m.msg.method_return()
                            .append1((size.w, size.h))
                    ])
                })
                    .outarg::<(u32, u32), _>("success")
                    .inarg::<String, _>("output_id")
            )
    )
}
<commit_msg>Added Screen.ActiveScreen endpoint<commit_after>use dbus::arg::{Array};
use dbus::tree::MethodErr;
use dbus::MessageItem;

use ::rustwlc::WlcOutput;
use ::layout::Handle;
use ::ipc::utils::{parse_uuid, lock_tree_dbus};
use ::ipc::{DBusFactory, DBusObjPath};
use ::render::screen_scrape::{write_screen_scrape_lock, read_screen_scrape_lock,
                              scraped_pixels_lock, sync_scrape};

pub fn setup(f: &mut DBusFactory) -> DBusObjPath {
    f.object_path("/org/way_cooler/Screen", ()).introspectable().add(
        f.interface("org.way_cooler.Screen", ())
            .add_m(
                f.method("List", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let outputs = tree.outputs().iter()
                        .map(|id|
                             MessageItem::Str(format!("{}", id.simple())))
                        .collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(outputs, "s".into())))
                    ])
                }).outarg::<Array<String, Vec<String>>, _>("success")
            )
            .add_m(
                f.method("ActiveScreen", (), |m| {
                    let tree = lock_tree_dbus()?;
                    let id = tree.lookup_handle(Handle::Output(WlcOutput::focused()))
                        .map_err(|err| MethodErr::failed(&format!("{:?}", err)))?.to_string();
                    Ok(vec![m.msg.method_return().append((MessageItem::Str(id)))])
                }).outarg::<String, _>("success")
            )
            .add_m(
                // TODO Make this take in a:
                // * Output UUID
                // * Size (u32, u32) to scrape. For invalid ones, we throw error
                f.method("Scrape", (), |m| {
                    *write_screen_scrape_lock() = true;
                    // ensure that no other threads can try to grab the pixels.
                    let _lock = read_screen_scrape_lock();
                    sync_scrape();
                    drop(_lock);
                    *write_screen_scrape_lock() = false;
                    let scraped_pixels = scraped_pixels_lock()
                        .expect("scraped_pixels lock was poisoned!");
                    let result = scraped_pixels.iter()
                        .map(|pixel| MessageItem::Byte(*pixel)).collect();
                    Ok(vec![m.msg.method_return()
                            .append((MessageItem::Array(result, "y".into())))])
                }).outarg::<Array<u8, Vec<u8>>, _>("success")
            )
            .add_m(
                f.method("Resolution", (), |m| {
                    let mut args_iter = m.msg.iter_init();
                    let output_id = args_iter.read::<String>()?;
                    let tree = lock_tree_dbus()?;
                    let uuid = parse_uuid("container_id", &output_id)?
                        .or_else(|| tree.active_id())
                        .ok_or(MethodErr::failed(&"No active container"))?;
                    let size = tree.output_resolution(uuid)
                        .map_err(|err| {
                            MethodErr::failed(&format!("{:?}", err))
                        })?;
                    Ok(vec![m.msg.method_return()
                            .append1((size.w, size.h))
                    ])
                })
                    .outarg::<(u32, u32), _>("success")
                    .inarg::<String, _>("output_id")
            )
    )
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters::*,
    data_cache::{RemoteCache, TransactionDataCache},
};
use libra_types::{
    access_path::AccessPath,
    contract_event::ContractEvent,
    language_storage::ModuleId,
    transaction::{TransactionOutput, TransactionStatus},
    vm_error::{StatusCode, VMStatus},
    write_set::WriteSet,
};
use vm::transaction_metadata::TransactionMetadata;
use vm::{
    errors::VMResult,
    gas_schedule::{GasAlgebra, GasCarrier, GasUnits},
};
use vm_runtime_types::{loaded_data::struct_def::StructDef, values::GlobalValue};

/// Trait that describes what Move bytecode runtime expects from the Libra blockchain.
pub trait ChainState {
    // Gas operations
    fn deduct_gas(&mut self, amount: GasUnits<GasCarrier>) -> VMResult<()>;
    fn remaining_gas(&self) -> GasUnits<GasCarrier>;

    // StateStore operations. Ideally the api should look like:
    // fn read_data(&self, ap: &AccessPath) -> VMResult<Vec<u8>>;
    // fn write_data(&mut self, ap: &AccessPath, data: Vec<u8>) -> VMResult<()>;
    // However this is not implementable due to the current implementation of MoveVM: data are
    // organized as a tree of GlobalRefs.
    /// Get a mutable reference to a resource stored on chain.
    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>>;

    /// Get the serialized format of a `CompiledModule` from chain given a `ModuleId`.
    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>>;

    /// Publish a module to be stored on chain.
    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()>;

    /// Publish a resource to be stored on chain.
    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()>;

    /// Check if this module exists on chain.
    // TODO: Can we get rid of this api with the loader refactor?
    fn exists_module(&self, key: &ModuleId) -> bool;

    /// Emit an event to the EventStore
    fn emit_event(&mut self, event: ContractEvent);
}

/// A TransactionExecutionContext holds the mutable data that needs to be persisted from one
/// section of the transaction flow to another. Because of this, this is the _only_ data that can
/// both be mutated, and persist between interpretation instances.
pub struct TransactionExecutionContext<'txn> {
    /// Gas metering to track cost of execution.
    gas_left: GasUnits<GasCarrier>,
    /// List of events "fired" during the course of an execution.
    event_data: Vec<ContractEvent>,
    /// Data store
    data_view: TransactionDataCache<'txn>,
}

/// The transaction
impl<'txn> TransactionExecutionContext<'txn> {
    pub fn new(gas_left: GasUnits<GasCarrier>, data_cache: &'txn dyn RemoteCache) -> Self {
        Self {
            gas_left,
            event_data: Vec::new(),
            data_view: TransactionDataCache::new(data_cache),
        }
    }

    /// Clear all the writes local to this execution.
    pub fn clear(&mut self) {
        self.data_view.clear();
        self.event_data.clear();
    }

    /// Return the list of events emitted during execution.
    pub fn events(&self) -> &[ContractEvent] {
        &self.event_data
    }

    /// Return the gas remaining
    pub fn gas_left(&self) -> GasUnits<GasCarrier> {
        self.gas_left
    }

    /// Generate a `WriteSet` as a result of an execution.
    pub fn make_write_set(&mut self) -> VMResult<WriteSet> {
        self.data_view.make_write_set()
    }

    pub fn get_transaction_output(
        &mut self,
        txn_data: &TransactionMetadata,
        status: VMStatus,
    ) -> VMResult<TransactionOutput> {
        let gas_used: u64 = txn_data
            .max_gas_amount()
            .sub(self.gas_left())
            .mul(txn_data.gas_unit_price())
            .get();
        let write_set = self.make_write_set()?;
        record_stats!(observe | TXN_TOTAL_GAS_USAGE | gas_used);
        Ok(TransactionOutput::new(
            write_set,
            self.events().to_vec(),
            gas_used,
            TransactionStatus::Keep(status),
        ))
    }
}

impl<'txn> ChainState for TransactionExecutionContext<'txn> {
    fn deduct_gas(&mut self, amount: GasUnits<GasCarrier>) -> VMResult<()> {
        if self
            .gas_left
            .app(&amount, |curr_gas, gas_amt| curr_gas >= gas_amt)
        {
            self.gas_left = self.gas_left.sub(amount);
            Ok(())
        } else {
            // Zero out the internal gas state
            self.gas_left = GasUnits::new(0);
            Err(VMStatus::new(StatusCode::OUT_OF_GAS))
        }
    }

    fn remaining_gas(&self) -> GasUnits<GasCarrier> {
        self.gas_left
    }

    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>> {
        self.data_view.load_data(ap, def)
    }

    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>> {
        self.data_view.load_module(module)
    }

    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()> {
        self.data_view.publish_module(module_id, module)
    }

    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()> {
        self.data_view.publish_resource(ap, g)
    }

    fn exists_module(&self, key: &ModuleId) -> bool {
        self.data_view.exists_module(key)
    }

    fn emit_event(&mut self, event: ContractEvent) {
        self.event_data.push(event)
    }
}

pub struct SystemExecutionContext<'txn>(TransactionExecutionContext<'txn>);

impl<'txn> SystemExecutionContext<'txn> {
    pub fn new(data_cache: &'txn dyn RemoteCache, gas_left: GasUnits<GasCarrier>) -> Self {
        SystemExecutionContext(TransactionExecutionContext::new(gas_left, data_cache))
    }

    /// Clear all the writes local to this execution.
    pub fn clear(&mut self) {
        self.0.clear()
    }

    /// Return the list of events emitted during execution.
    pub fn events(&self) -> &[ContractEvent] {
        self.0.events()
    }

    /// Generate a `WriteSet` as a result of an execution.
    pub fn make_write_set(&mut self) -> VMResult<WriteSet> {
        self.0.make_write_set()
    }

    pub fn get_transaction_output(
        &mut self,
        txn_data: &TransactionMetadata,
        status: VMStatus,
    ) -> VMResult<TransactionOutput> {
        self.0.get_transaction_output(txn_data, status)
    }
}

impl<'txn> ChainState for SystemExecutionContext<'txn> {
    fn deduct_gas(&mut self, _amount: GasUnits<GasCarrier>) -> VMResult<()> {
        Ok(())
    }

    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()> {
        self.0.publish_resource(ap, g)
    }

    fn remaining_gas(&self) -> GasUnits<GasCarrier> {
        self.0.gas_left()
    }

    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>> {
        self.0.load_data(ap, def)
    }

    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>> {
        self.0.load_module(module)
    }

    fn exists_module(&self, key: &ModuleId) -> bool {
        self.0.exists_module(key)
    }

    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()> {
        self.0.publish_module(module_id, module)
    }

    fn emit_event(&mut self, event: ContractEvent) {
        self.0.emit_event(event)
    }
}

impl<'txn> From<TransactionExecutionContext<'txn>> for SystemExecutionContext<'txn> {
    fn from(ctx: TransactionExecutionContext<'txn>) -> Self {
        Self(ctx)
    }
}
<commit_msg>[vm-runtime] make a clearer case for the current ChainState API<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters::*,
    data_cache::{RemoteCache, TransactionDataCache},
};
use libra_types::{
    access_path::AccessPath,
    contract_event::ContractEvent,
    language_storage::ModuleId,
    transaction::{TransactionOutput, TransactionStatus},
    vm_error::{StatusCode, VMStatus},
    write_set::WriteSet,
};
use vm::transaction_metadata::TransactionMetadata;
use vm::{
    errors::VMResult,
    gas_schedule::{GasAlgebra, GasCarrier, GasUnits},
};
use vm_runtime_types::{loaded_data::struct_def::StructDef, values::GlobalValue};

/// Trait that describes what Move bytecode runtime expects from the Libra blockchain.
pub trait ChainState {
    // ---
    // Gas operations
    // ---

    fn deduct_gas(&mut self, amount: GasUnits<GasCarrier>) -> VMResult<()>;
    fn remaining_gas(&self) -> GasUnits<GasCarrier>;

    // ---
    // StateStore operations
    // ---

    // An alternative for these APIs might look like:
    //
    //   fn read_data(&self, ap: &AccessPath) -> VMResult<Vec<u8>>;
    //   fn write_data(&mut self, ap: &AccessPath, data: Vec<u8>) -> VMResult<()>;
    //
    // However, this would make the Move VM responsible for deserialization -- in particular,
    // caching deserialized results leads to a big performance improvement. But this directly
    // conflicts with the goal of the Move VM to be as stateless as possible. Hence the burden of
    // deserialization (and caching) is placed on the implementer of this trait.

    /// Get a mutable reference to a resource stored on chain.
    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>>;

    /// Get the serialized format of a `CompiledModule` from chain given a `ModuleId`.
    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>>;

    /// Publish a module to be stored on chain.
    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()>;

    /// Publish a resource to be stored on chain.
    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()>;

    /// Check if this module exists on chain.
    // TODO: Can we get rid of this api with the loader refactor?
    fn exists_module(&self, key: &ModuleId) -> bool;

    // ---
    // EventStore operations
    // ---

    /// Emit an event to the EventStore
    fn emit_event(&mut self, event: ContractEvent);
}

/// A TransactionExecutionContext holds the mutable data that needs to be persisted from one
/// section of the transaction flow to another. Because of this, this is the _only_ data that can
/// both be mutated, and persist between interpretation instances.
pub struct TransactionExecutionContext<'txn> {
    /// Gas metering to track cost of execution.
    gas_left: GasUnits<GasCarrier>,
    /// List of events "fired" during the course of an execution.
    event_data: Vec<ContractEvent>,
    /// Data store
    data_view: TransactionDataCache<'txn>,
}

/// The transaction
impl<'txn> TransactionExecutionContext<'txn> {
    pub fn new(gas_left: GasUnits<GasCarrier>, data_cache: &'txn dyn RemoteCache) -> Self {
        Self {
            gas_left,
            event_data: Vec::new(),
            data_view: TransactionDataCache::new(data_cache),
        }
    }

    /// Clear all the writes local to this execution.
    pub fn clear(&mut self) {
        self.data_view.clear();
        self.event_data.clear();
    }

    /// Return the list of events emitted during execution.
    pub fn events(&self) -> &[ContractEvent] {
        &self.event_data
    }

    /// Return the gas remaining
    pub fn gas_left(&self) -> GasUnits<GasCarrier> {
        self.gas_left
    }

    /// Generate a `WriteSet` as a result of an execution.
    pub fn make_write_set(&mut self) -> VMResult<WriteSet> {
        self.data_view.make_write_set()
    }

    pub fn get_transaction_output(
        &mut self,
        txn_data: &TransactionMetadata,
        status: VMStatus,
    ) -> VMResult<TransactionOutput> {
        let gas_used: u64 = txn_data
            .max_gas_amount()
            .sub(self.gas_left())
            .mul(txn_data.gas_unit_price())
            .get();
        let write_set = self.make_write_set()?;
        record_stats!(observe | TXN_TOTAL_GAS_USAGE | gas_used);
        Ok(TransactionOutput::new(
            write_set,
            self.events().to_vec(),
            gas_used,
            TransactionStatus::Keep(status),
        ))
    }
}

impl<'txn> ChainState for TransactionExecutionContext<'txn> {
    fn deduct_gas(&mut self, amount: GasUnits<GasCarrier>) -> VMResult<()> {
        if self
            .gas_left
            .app(&amount, |curr_gas, gas_amt| curr_gas >= gas_amt)
        {
            self.gas_left = self.gas_left.sub(amount);
            Ok(())
        } else {
            // Zero out the internal gas state
            self.gas_left = GasUnits::new(0);
            Err(VMStatus::new(StatusCode::OUT_OF_GAS))
        }
    }

    fn remaining_gas(&self) -> GasUnits<GasCarrier> {
        self.gas_left
    }

    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>> {
        self.data_view.load_data(ap, def)
    }

    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>> {
        self.data_view.load_module(module)
    }

    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()> {
        self.data_view.publish_module(module_id, module)
    }

    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()> {
        self.data_view.publish_resource(ap, g)
    }

    fn exists_module(&self, key: &ModuleId) -> bool {
        self.data_view.exists_module(key)
    }

    fn emit_event(&mut self, event: ContractEvent) {
        self.event_data.push(event)
    }
}

pub struct SystemExecutionContext<'txn>(TransactionExecutionContext<'txn>);

impl<'txn> SystemExecutionContext<'txn> {
    pub fn new(data_cache: &'txn dyn RemoteCache, gas_left: GasUnits<GasCarrier>) -> Self {
        SystemExecutionContext(TransactionExecutionContext::new(gas_left, data_cache))
    }

    /// Clear all the writes local to this execution.
    pub fn clear(&mut self) {
        self.0.clear()
    }

    /// Return the list of events emitted during execution.
    pub fn events(&self) -> &[ContractEvent] {
        self.0.events()
    }

    /// Generate a `WriteSet` as a result of an execution.
    pub fn make_write_set(&mut self) -> VMResult<WriteSet> {
        self.0.make_write_set()
    }

    pub fn get_transaction_output(
        &mut self,
        txn_data: &TransactionMetadata,
        status: VMStatus,
    ) -> VMResult<TransactionOutput> {
        self.0.get_transaction_output(txn_data, status)
    }
}

impl<'txn> ChainState for SystemExecutionContext<'txn> {
    fn deduct_gas(&mut self, _amount: GasUnits<GasCarrier>) -> VMResult<()> {
        Ok(())
    }

    fn publish_resource(&mut self, ap: &AccessPath, g: (StructDef, GlobalValue)) -> VMResult<()> {
        self.0.publish_resource(ap, g)
    }

    fn remaining_gas(&self) -> GasUnits<GasCarrier> {
        self.0.gas_left()
    }

    fn load_data(
        &mut self,
        ap: &AccessPath,
        def: StructDef,
    ) -> VMResult<&mut Option<(StructDef, GlobalValue)>> {
        self.0.load_data(ap, def)
    }

    fn load_module(&self, module: &ModuleId) -> VMResult<Vec<u8>> {
        self.0.load_module(module)
    }

    fn exists_module(&self, key: &ModuleId) -> bool {
        self.0.exists_module(key)
    }

    fn publish_module(&mut self, module_id: ModuleId, module: Vec<u8>) -> VMResult<()> {
        self.0.publish_module(module_id, module)
    }

    fn emit_event(&mut self, event: ContractEvent) {
        self.0.emit_event(event)
    }
}

impl<'txn> From<TransactionExecutionContext<'txn>> for SystemExecutionContext<'txn> {
    fn from(ctx: TransactionExecutionContext<'txn>) -> Self {
        Self(ctx)
    }
}
<|endoftext|>