<commit_before>use std::io::Write;
use std::io::Result as IoResult;
use std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::ops::RangeFrom;
use std::collections::HashMap;

use bincode::{serialize, deserialize_from, Infinite, Bounded};

use state::{WorldState, Player, Unit, UnitId};
use network::{Message, Command};

/// A `Server` instance holds global server state.
pub struct Server {
    socket_addr: SocketAddr,
    world: Arc<Mutex<WorldState>>,
    /// Generator that returns sequential unit IDs
    unit_id_generator: Arc<Mutex<RangeFrom<u32>>>,
    /// Generator that returns sequential client IDs
    client_id_generator: Arc<Mutex<RangeFrom<u32>>>,

    /// Map with active unit move commands
    unit_targets: Arc<Mutex<HashMap<UnitId, [f64; 2]>>>,
}

impl Server {
    pub fn new<T: ToSocketAddrs>(addr: T,
                                world_size: (u64, u64))
                                -> IoResult<Server> {
        let addr = try!(addr.to_socket_addrs()).next().unwrap();
        let world = Arc::new(Mutex::new(WorldState::new(world_size.0, world_size.1)));
        Ok(Server {
            socket_addr: addr,
            world: world,
            client_id_generator: Arc::new(Mutex::new(0..)),
            unit_id_generator: Arc::new(Mutex::new(0..)),
            unit_targets: Arc::new(Mutex::new(HashMap::new())),
        })
    }

    pub fn serve(&self) {
        let tcp_listener = TcpListener::bind(self.socket_addr).unwrap();
        println!("Start server: {:?}", tcp_listener);

        let world_clone = self.world.clone();
        let unit_targets_clone = self.unit_targets.clone();
        thread::spawn(move || {
            update_world(world_clone, unit_targets_clone);
        });

        for stream in tcp_listener.incoming() {
            match stream {
                Ok(stream) => {
                    let world_clone = self.world.clone();
                    let client_id_generator_clone = self.client_id_generator.clone();
                    let unit_id_generator_clone = self.unit_id_generator.clone();
                    let unit_targets = self.unit_targets.clone();
                    println!("Spawning thread...");
                    thread::spawn(move || {
                        handle_client(stream, world_clone,
                                      client_id_generator_clone, unit_id_generator_clone, unit_targets);
                    });
                }
                Err(e) => {
                    println!("{:?}", e);
                }
            }
        }
    }
}

pub type SafeWorldState = Arc<Mutex<WorldState>>;
pub type SafeUnitTargets = Arc<Mutex<HashMap<UnitId, [f64; 2]>>>;

pub fn handle_client(mut stream: TcpStream,
                     world: SafeWorldState,
                     client_id_generator: Arc<Mutex<RangeFrom<u32>>>,
                     unit_id_generator: Arc<Mutex<RangeFrom<u32>>>,
                     unit_targets: SafeUnitTargets) {

    // handle client hello
    let client_message = deserialize_from(&mut stream, Bounded(128));
    match client_message {
        Ok(message) => {
            match message {
                Message::ClientHello => {
                    // Get exclusive world access
                    let mut world_lock = world.lock().unwrap();

                    // Create new player for the newly connected client
                    let client_id = client_id_generator
                        .lock().expect("Could not lock client_id_generator mutex")
                        .next().expect("No more client IDs available!");
                    let mut player = Player::new(client_id);

                    // Create four initial units for the player
                    let coords = [
                        [50.0f64, 50.0f64], [50.0f64, 100.0f64], [100.0f64, 50.0f64], [100.0f64, 100.0f64],
                    ];
                    for coord in coords.iter() {
                        let unit_id = unit_id_generator
                            .lock().expect("Could not lock unit_id_generator mutex")
                            .next().expect("No more unit IDs available!");
                        player.units.push(Unit::new(unit_id, *coord));
                    }

                    // Add player to the world
                    let player_id = player.id;
                    world_lock.game.players.push(player);

                    // Send ServerHello message
                    let encoded: Vec<u8> = serialize(
                        &Message::ServerHello(player_id, world_lock.clone()),
                        Infinite
                    ).unwrap();
                    stream.write(&encoded).unwrap();
                },
                Message::ClientReconnect(id) => {
                    // Get exclusive world access
                    let world_lock = world.lock().unwrap();

                    // Find player with specified id
                    match world_lock.game.players.iter().find(|player| player.id == id) {
                        Some(_) => {
                            println!("Found you :)");

                            // Send ServerHello message
                            let encoded: Vec<u8> = serialize(
                                &Message::ServerHello(id, world_lock.clone()),
                                Infinite
                            ).unwrap();
                            stream.write(&encoded).unwrap();
                        },
                        None => {
                            println!("Reconnect to id {} not possible", id);

                            // Send Error message
                            let encoded: Vec<u8> = serialize(
                                &Message::Error,
                                Infinite).unwrap();
                            stream.write(&encoded).unwrap();
                            return  // Don't enter game loop
                        }
                    }
                },
                _ => {
                    println!("Did not receive ClientHello: {:?}", message);
                    let encoded: Vec<u8> = serialize(&Message::Error, Infinite).unwrap();
                    stream.write(&encoded).unwrap();
                    return  // Don't enter game loop
                }
            }
        }
        Err(e) => {
            println!("Error: {:?}", e);
            return  // Don't enter game loop
        }
    }

    let mut command_stream = stream.try_clone().unwrap();
    let world_clone = world.clone();
    let unit_targets_clone = unit_targets.clone();
    // Command receiver loop
    thread::spawn(move || {
        loop {
            let client_message = deserialize_from(&mut command_stream, Bounded(128));
            match client_message {
                Ok(message) => {
                    match message {
                        Message::Command(command) => {
                            let mut world_lock = world_clone.lock().unwrap();
                            let mut unit_targets_lock = unit_targets_clone.lock().unwrap();
                            handle_command(&mut world_lock, &mut unit_targets_lock, &command);
                        },
                        _ => {
                            println!("Did receive unexpected message: {:?}", message);
                            let encoded: Vec<u8> = serialize(&Message::Error, Infinite).unwrap();
                            command_stream.write(&encoded).unwrap();
                            return
                        },
                    }
                },
                Err(e) => {
                    println!("Error: {:?}", e);
                    return;
                }
            };
        }
    });

    // GameState loop
    loop {
        let encoded: Vec<u8> = {
            let world_lock = world.lock().unwrap();
            serialize(&world_lock.game, Infinite).unwrap()
        };
        match stream.write(&encoded) {
            Err(e) => {
                println!("Error: {:?}", e);
                return;
            }
            _ => thread::sleep(Duration::from_millis(10)),
        };
    }
}

pub fn handle_command(world: &mut WorldState, unit_targets: &mut HashMap<UnitId, [f64; 2]>, command: &Command) {
    println!("Did receive command {:?}", command);
    match command {
        &Command::Move(id, target) => {
            for player in world.game.players.iter_mut() {
                for unit in player.units.iter_mut() {
                    if unit.id == id {
                        println!("Found it :)");
                        unit_targets.insert(id, target);
                    }
                }
            }
            println!("Move {} to {:?}!", id, target);
        }
    }
}

pub fn update_world(world: SafeWorldState, unit_targets: SafeUnitTargets) {
    loop {
        {
            let mut world_lock = world.lock().unwrap();
            let unit_targets = unit_targets.lock().unwrap();
            for player in world_lock.game.players.iter_mut() {
                for unit in player.units.iter_mut() {
                    if let Some(target) = unit_targets.get(&unit.id) {
                        let speed = 0.0001;
                        unit.speed_vector = [(target[0]-unit.position[0])*speed, (target[1]-unit.position[1])*speed];
                    } else {
                        unit.speed_vector = [0.0,0.0];
                    }
                    unit.update(5);
                }
                //println!("{:?}", player);
            }
        }
        thread::sleep(Duration::from_millis(5));
    }
}
<commit_msg>server: Update angle on move command<commit_after>use std::io::Write;
use std::io::Result as IoResult;
use std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::ops::RangeFrom;
use std::collections::HashMap;
use std::f64::consts::PI;

use bincode::{serialize, deserialize_from, Infinite, Bounded};

use state::{WorldState, Player, Unit, UnitId};
use network::{Message, Command};

/// A `Server` instance holds global server state.
pub struct Server {
    socket_addr: SocketAddr,
    world: Arc<Mutex<WorldState>>,
    /// Generator that returns sequential unit IDs
    unit_id_generator: Arc<Mutex<RangeFrom<u32>>>,
    /// Generator that returns sequential client IDs
    client_id_generator: Arc<Mutex<RangeFrom<u32>>>,

    /// Map with active unit move commands
    unit_targets: Arc<Mutex<HashMap<UnitId, [f64; 2]>>>,
}

impl Server {
    pub fn new<T: ToSocketAddrs>(addr: T,
                                world_size: (u64, u64))
                                -> IoResult<Server> {
        let addr = try!(addr.to_socket_addrs()).next().unwrap();
        let world = Arc::new(Mutex::new(WorldState::new(world_size.0, world_size.1)));
        Ok(Server {
            socket_addr: addr,
            world: world, client_id_generator: Arc::new(Mutex::new(0..)),
            unit_id_generator: Arc::new(Mutex::new(0..)),
            unit_targets: Arc::new(Mutex::new(HashMap::new())),
        })
    }

    pub fn serve(&self) {
        let tcp_listener = TcpListener::bind(self.socket_addr).unwrap();
        println!("Start server: {:?}", tcp_listener);

        let world_clone = self.world.clone();
        let unit_targets_clone = self.unit_targets.clone();
        thread::spawn(move || {
            update_world(world_clone, unit_targets_clone);
        });

        for stream in tcp_listener.incoming() {
            match stream {
                Ok(stream) => {
                    let world_clone = self.world.clone();
                    let client_id_generator_clone = self.client_id_generator.clone();
                    let unit_id_generator_clone = self.unit_id_generator.clone();
                    let unit_targets = self.unit_targets.clone();
                    println!("Spawning thread...");
                    thread::spawn(move || {
                        handle_client(stream, world_clone,
                                      client_id_generator_clone, unit_id_generator_clone, unit_targets);
                    });
                }
                Err(e) => {
                    println!("{:?}", e);
                }
            }
        }
    }
}

pub type SafeWorldState = Arc<Mutex<WorldState>>;
pub type SafeUnitTargets = Arc<Mutex<HashMap<UnitId, [f64; 2]>>>;

pub fn handle_client(mut stream: TcpStream,
                     world: SafeWorldState,
                     client_id_generator: Arc<Mutex<RangeFrom<u32>>>,
                     unit_id_generator: Arc<Mutex<RangeFrom<u32>>>,
                     unit_targets: SafeUnitTargets) {

    // handle client hello
    let client_message = deserialize_from(&mut stream, Bounded(128));
    match client_message {
        Ok(message) => {
            match message {
                Message::ClientHello => {
                    // Get exclusive world access
                    let mut world_lock = world.lock().unwrap();

                    // Create new player for the newly connected client
                    let client_id = client_id_generator
                        .lock().expect("Could not lock client_id_generator mutex")
                        .next().expect("No more client IDs available!");
                    let mut player = Player::new(client_id);

                    // Create four initial units for the player
                    let coords = [
                        [50.0f64, 50.0f64], [50.0f64, 100.0f64], [100.0f64, 50.0f64], [100.0f64, 100.0f64],
                    ];
                    for coord in coords.iter() {
                        let unit_id = unit_id_generator
                            .lock().expect("Could not lock unit_id_generator mutex")
                            .next().expect("No more unit IDs available!");
                        player.units.push(Unit::new(unit_id, *coord));
                    }

                    // Add player to the world
                    let player_id = player.id;
                    world_lock.game.players.push(player);

                    // Send ServerHello message
                    let encoded: Vec<u8> = serialize(
                        &Message::ServerHello(player_id, world_lock.clone()),
                        Infinite
                    ).unwrap();
                    stream.write(&encoded).unwrap();
                },
                Message::ClientReconnect(id) => {
                    // Get exclusive world access
                    let world_lock = world.lock().unwrap();

                    // Find player with specified id
                    match world_lock.game.players.iter().find(|player| player.id == id) {
                        Some(_) => {
                            println!("Found you :)");

                            // Send ServerHello message
                            let encoded: Vec<u8> = serialize(
                                &Message::ServerHello(id, world_lock.clone()),
                                Infinite
                            ).unwrap();
                            stream.write(&encoded).unwrap();
                        },
                        None => {
                            println!("Reconnect to id {} not possible", id);

                            // Send Error message
                            let encoded: Vec<u8> = serialize(
                                &Message::Error,
                                Infinite).unwrap();
                            stream.write(&encoded).unwrap();
                            return  // Don't enter game loop
                        }
                    }
                },
                _ => {
                    println!("Did not receive ClientHello: {:?}", message);
                    let encoded: Vec<u8> = serialize(&Message::Error, Infinite).unwrap();
                    stream.write(&encoded).unwrap();
                    return  // Don't enter game loop
                }
            }
        }
        Err(e) => {
            println!("Error: {:?}", e);
            return  // Don't enter game loop
        }
    }

    let mut command_stream = stream.try_clone().unwrap();
    let world_clone = world.clone();
    let unit_targets_clone = unit_targets.clone();
    // Command receiver loop
    thread::spawn(move || {
        loop {
            let client_message = deserialize_from(&mut command_stream, Bounded(128));
            match client_message {
                Ok(message) => {
                    match message {
                        Message::Command(command) => {
                            let mut world_lock = world_clone.lock().unwrap();
                            let mut unit_targets_lock = unit_targets_clone.lock().unwrap();
                            handle_command(&mut world_lock, &mut unit_targets_lock, &command);
                        },
                        _ => {
                            println!("Did receive unexpected message: {:?}", message);
                            let encoded: Vec<u8> = serialize(&Message::Error, Infinite).unwrap();
                            command_stream.write(&encoded).unwrap();
                            return
                        },
                    }
                },
                Err(e) => {
                    println!("Error: {:?}", e);
                    return;
                }
            };
        }
    });

    // GameState loop
    loop {
        let encoded: Vec<u8> = {
            let world_lock = world.lock().unwrap();
            serialize(&world_lock.game, Infinite).unwrap()
        };
        match stream.write(&encoded) {
            Err(e) => {
                println!("Error: {:?}", e);
                return;
            }
            _ => thread::sleep(Duration::from_millis(10)),
        };
    }
}

pub fn handle_command(world: &mut WorldState, unit_targets: &mut HashMap<UnitId, [f64; 2]>, command: &Command) {
    println!("Did receive command {:?}", command);
    match command {
        &Command::Move(id, target) => {
            for player in world.game.players.iter_mut() {
                for unit in player.units.iter_mut() {
                    if unit.id == id {
                        println!("Found it :)");
                        let dx = target[0] - unit.position[0];
                        let dy = target[1] - unit.position[1];
                        if dx.is_sign_negative() {
                            unit.angle = (dy / dx).atan() + PI;
                        } else {
                            unit.angle = (dy / dx).atan();
                        }
                        unit_targets.insert(id, target);
                    }
                }
            }
            println!("Move {} to {:?}!", id, target);
        }
    }
}

pub fn update_world(world: SafeWorldState, unit_targets: SafeUnitTargets) {
    loop {
        {
            let mut world_lock = world.lock().unwrap();
            let unit_targets = unit_targets.lock().unwrap();
            for player in world_lock.game.players.iter_mut() {
                for unit in player.units.iter_mut() {
                    if let Some(target) = unit_targets.get(&unit.id) {
                        let speed = 0.0001;
                        unit.speed_vector = [(target[0]-unit.position[0])*speed, (target[1]-unit.position[1])*speed];
                    } else {
                        unit.speed_vector = [0.0,0.0];
                    }
                    unit.update(5);
                }
                //println!("{:?}", player);
            }
        }
        thread::sleep(Duration::from_millis(5));
    }
}
<|endoftext|>


<commit_before>const STEP_TABLE: [u32; 89] = [
    7,     8,     9,     10,    11,    12,     13,    14,    16,
    17,    19,    21,    23,    25,    28,     31,    34,    37,
    41,    45,    50,    55,    60,    66,     73,    80,    88,
    97,    107,   118,   130,   143,   157,    173,   190,   209,
    230,   253,   279,   307,   337,   371,    408,   449,   494,
    544,   598,   658,   724,   796,   876,    963,   1060,  1166,
    1282,  1411,  1552,  1707,  1878,  2066,   2272,  2499,  2749,
    3024,  3327,  3660,  4026,  4428,  4871,   5358,  5894,  6484,
    7132,  7845,  8630,  9493,  10442, 11487,  12635, 13899, 15289,
    16818, 18500, 20350, 22385, 24623, 27086,  29794, 32767
];

const INDEX_ADJUSTMENT: [i32; 8] = [
    -1, -1, -1, -1, 2, 4, 6, 8
];

/// Decompress samples of a _single_ audio channel.
///
/// First call to this function should pass in 0 for `index` and 0 for `sample`.
/// Subsequent calls should maintain `index` and `sample` for a single channel.
pub fn decompress(input: &[u8], index: &mut i32, sample: &mut i32) -> Box<[u16]> {
    let mut buffer = Vec::with_capacity(input.len() * 2);

    for i in 0..input.len() {
        for c in [input[i] & 0b0000_1111, input[i] & 0b1111_0000].iter() {
            let mut code = *c;

            let sb = if code & 0x8 != 0 { 1 } else { 0 };
            code = code & 0x7;
            let mut delta = ((STEP_TABLE[*index as usize]*code as u32) / 4 + STEP_TABLE[*index as usize] / 8) as i32;
            if sb == 1 { delta = -delta; }

            *sample = *sample + delta;
            if *sample > 32767 { *sample = 32767; }
            else if *sample < -32768 { *sample = -32768; }

            buffer.push(*sample as u16);

            *index = *index + INDEX_ADJUSTMENT[code as usize];
            if *index < 0 { *index = 0; }
            else if *index > 88 { *index = 88; }
        }
    }

    buffer.into_boxed_slice()
}<commit_msg>add CodecState struct<commit_after>const STEP_TABLE: [u32; 89] = [
    7,     8,     9,     10,    11,    12,     13,    14,    16,
    17,    19,    21,    23,    25,    28,     31,    34,    37,
    41,    45,    50,    55,    60,    66,     73,    80,    88,
    97,    107,   118,   130,   143,   157,    173,   190,   209,
    230,   253,   279,   307,   337,   371,    408,   449,   494,
    544,   598,   658,   724,   796,   876,    963,   1060,  1166,
    1282,  1411,  1552,  1707,  1878,  2066,   2272,  2499,  2749,
    3024,  3327,  3660,  4026,  4428,  4871,   5358,  5894,  6484,
    7132,  7845,  8630,  9493,  10442, 11487,  12635, 13899, 15289,
    16818, 18500, 20350, 22385, 24623, 27086,  29794, 32767
];

const INDEX_ADJUSTMENT: [i32; 16] = [
    -1, -1, -1, -1, 2, 4, 6, 8,
    -1, -1, -1, -1, 2, 4, 6, 8
];

pub struct CodecState {
    sample: i32,
    index: i32
}

impl CodecState {
    pub fn new() -> CodecState {
        CodecState {
            sample: 0,
            index: 0
        }
    }
}

/// Decompress samples of a _single_ audio channel.
///
/// Pass in a separate `state` for each channel
pub fn decompress(state: &mut CodecState, input: &[u8]) -> Box<[u16]> {
    let mut buffer = Vec::with_capacity(input.len() * 2);
    let mut low_nibble = true;
    let mut i = 0;

    while i < input.len() {
        let mut code;
        if low_nibble {
            code = input[i] & 0xf;
        } else {
            code = (input[i] >> 4) & 0xf;
            i += 1;
        };
        low_nibble = !low_nibble;

        let sb = if code & 0x8 != 0 { 1 } else { 0 };
        code = code & 0x7;
        let mut delta = ((STEP_TABLE[state.index as usize]*code as u32) / 4 + STEP_TABLE[state.index as usize] / 8) as i32;
        if sb == 1 { delta = -delta; }

        state.sample = state.sample + delta;
        if state.sample > 32767 { state.sample = 32767; }
        else if state.sample < -32768 { state.sample = -32768; }

        buffer.push(state.sample as u16);

        state.index = state.index + INDEX_ADJUSTMENT[code as usize];
        if state.index < 0 { state.index = 0; }
        else if state.index > 88 { state.index = 88; }
    }

    buffer.into_boxed_slice()
}
<|endoftext|>


<commit_before>use approx::RelativeEq;
#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::mem;
use std::ops::{Deref, Neg};

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

use alga::general::SubsetOf;
use alga::linear::NormedSpace;

/// A wrapper that ensures the underlying algebraic entity has a unit norm.
///
/// Use `.as_ref()` or `.unwrap()` to obtain the underlying value by-reference or by-move.
#[repr(C)]
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Unit<T> {
    value: T,
}

#[cfg(feature = "serde-serialize")]
impl<T: Serialize> Serialize for Unit<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.value.serialize(serializer)
    }
}

#[cfg(feature = "serde-serialize")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        T::deserialize(deserializer).map(|x| Unit { value: x })
    }
}

#[cfg(feature = "abomonation-serialize")]
impl<T: Abomonation> Abomonation for Unit<T> {
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.value.entomb(writer)
    }

    fn extent(&self) -> usize {
        self.value.extent()
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.value.exhume(bytes)
    }
}

impl<T: NormedSpace> Unit<T> {
    /// Normalize the given value and return it wrapped on a `Unit` structure.
    #[inline]
    pub fn new_normalize(value: T) -> Self {
        Self::new_and_get(value).0
    }

    /// Attempts to normalize the given value and return it wrapped on a `Unit` structure.
    ///
    /// Returns `None` if the norm was smaller or equal to `min_norm`.
    #[inline]
    pub fn try_new(value: T, min_norm: T::Field) -> Option<Self> {
        Self::try_new_and_get(value, min_norm).map(|res| res.0)
    }

    /// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
    #[inline]
    pub fn new_and_get(mut value: T) -> (Self, T::Field) {
        let n = value.normalize_mut();

        (Unit { value: value }, n)
    }

    /// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
    ///
    /// Returns `None` if the norm was smaller or equal to `min_norm`.
    #[inline]
    pub fn try_new_and_get(mut value: T, min_norm: T::Field) -> Option<(Self, T::Field)> {
        if let Some(n) = value.try_normalize_mut(min_norm) {
            Some((Unit { value: value }, n))
        } else {
            None
        }
    }

    /// Normalizes this value again. This is useful when repeated computations
    /// might cause a drift in the norm because of float inaccuracies.
    ///
    /// Returns the norm before re-normalization (should be close to `1.0`).
    #[inline]
    pub fn renormalize(&mut self) -> T::Field {
        self.value.normalize_mut()
    }
}

impl<T> Unit<T> {
    /// Wraps the given value, assuming it is already normalized.
    ///
    /// This function is not safe because `value` is not verified to be actually normalized.
    #[inline]
    pub fn new_unchecked(value: T) -> Self {
        Unit { value: value }
    }

    /// Retrieves the underlying value.
    #[inline]
    pub fn unwrap(self) -> T {
        self.value
    }

    /// Returns a mutable reference to the underlying value. This is `_unchecked` because modifying
    /// the underlying value in such a way that it no longer has unit length may lead to unexpected
    /// results.
    #[inline]
    pub fn as_mut_unchecked(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T> AsRef<T> for Unit<T> {
    #[inline]
    fn as_ref(&self) -> &T {
        &self.value
    }
}

/*
 *
 * Conversions.
 *
 */
impl<T: NormedSpace> SubsetOf<T> for Unit<T>
where
    T::Field: RelativeEq,
{
    #[inline]
    fn to_superset(&self) -> T {
        self.clone().unwrap()
    }

    #[inline]
    fn is_in_subset(value: &T) -> bool {
        relative_eq!(value.norm_squared(), ::one())
    }

    #[inline]
    unsafe fn from_superset_unchecked(value: &T) -> Self {
        Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact.
    }
}

// impl<T: RelativeEq> RelativeEq for Unit<T> {
//     type Epsilon = T::Epsilon;
//
//     #[inline]
//     fn default_epsilon() -> Self::Epsilon {
//         T::default_epsilon()
//     }
//
//     #[inline]
//     fn default_max_relative() -> Self::Epsilon {
//         T::default_max_relative()
//     }
//
//     #[inline]
//     fn default_max_ulps() -> u32 {
//         T::default_max_ulps()
//     }
//
//     #[inline]
//     fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
//         self.value.relative_eq(&other.value, epsilon, max_relative)
//     }
//
//     #[inline]
//     fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
//         self.value.ulps_eq(&other.value, epsilon, max_ulps)
//     }
// }

// FIXME:re-enable this impl when specialization is possible.
// Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display.
/*
impl<T: fmt::Display> fmt::Display for Unit<T> {
    // XXX: will not always work correctly due to rounding errors.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.value.fmt(f)
    }
}
*/

impl<T: Neg> Neg for Unit<T> {
    type Output = Unit<T::Output>;

    #[inline]
    fn neg(self) -> Self::Output {
        Unit::new_unchecked(-self.value)
    }
}

impl<T> Deref for Unit<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        unsafe { mem::transmute(self) }
    }
}
<commit_msg>Introduce Unit::from_ref_unchecked<commit_after>use approx::RelativeEq;
#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::mem;
use std::ops::{Deref, Neg};

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

use alga::general::SubsetOf;
use alga::linear::NormedSpace;

/// A wrapper that ensures the underlying algebraic entity has a unit norm.
///
/// Use `.as_ref()` or `.unwrap()` to obtain the underlying value by-reference or by-move.
#[repr(transparent)]
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Unit<T> {
    value: T,
}

#[cfg(feature = "serde-serialize")]
impl<T: Serialize> Serialize for Unit<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.value.serialize(serializer)
    }
}

#[cfg(feature = "serde-serialize")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        T::deserialize(deserializer).map(|x| Unit { value: x })
    }
}

#[cfg(feature = "abomonation-serialize")]
impl<T: Abomonation> Abomonation for Unit<T> {
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.value.entomb(writer)
    }

    fn extent(&self) -> usize {
        self.value.extent()
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.value.exhume(bytes)
    }
}

impl<T: NormedSpace> Unit<T> {
    /// Normalize the given value and return it wrapped on a `Unit` structure.
    #[inline]
    pub fn new_normalize(value: T) -> Self {
        Self::new_and_get(value).0
    }

    /// Attempts to normalize the given value and return it wrapped on a `Unit` structure.
    ///
    /// Returns `None` if the norm was smaller or equal to `min_norm`.
    #[inline]
    pub fn try_new(value: T, min_norm: T::Field) -> Option<Self> {
        Self::try_new_and_get(value, min_norm).map(|res| res.0)
    }

    /// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
    #[inline]
    pub fn new_and_get(mut value: T) -> (Self, T::Field) {
        let n = value.normalize_mut();

        (Unit { value: value }, n)
    }

    /// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
    ///
    /// Returns `None` if the norm was smaller or equal to `min_norm`.
    #[inline]
    pub fn try_new_and_get(mut value: T, min_norm: T::Field) -> Option<(Self, T::Field)> {
        if let Some(n) = value.try_normalize_mut(min_norm) {
            Some((Unit { value: value }, n))
        } else {
            None
        }
    }

    /// Normalizes this value again. This is useful when repeated computations
    /// might cause a drift in the norm because of float inaccuracies.
    ///
    /// Returns the norm before re-normalization (should be close to `1.0`).
    #[inline]
    pub fn renormalize(&mut self) -> T::Field {
        self.value.normalize_mut()
    }
}

impl<T> Unit<T> {
    /// Wraps the given value, assuming it is already normalized.
    #[inline]
    pub fn new_unchecked(value: T) -> Self {
        Unit { value: value }
    }

    /// Wraps the given reference, assuming it is already normalized.
    #[inline]
    pub fn from_ref_unchecked<'a>(value: &'a T) -> &'a Self {
        unsafe { mem::transmute(value) }
    }

    /// Retrieves the underlying value.
    #[inline]
    pub fn unwrap(self) -> T {
        self.value
    }

    /// Returns a mutable reference to the underlying value. This is `_unchecked` because modifying
    /// the underlying value in such a way that it no longer has unit length may lead to unexpected
    /// results.
    #[inline]
    pub fn as_mut_unchecked(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T> AsRef<T> for Unit<T> {
    #[inline]
    fn as_ref(&self) -> &T {
        &self.value
    }
}

/*
 *
 * Conversions.
 *
 */
impl<T: NormedSpace> SubsetOf<T> for Unit<T>
where
    T::Field: RelativeEq,
{
    #[inline]
    fn to_superset(&self) -> T {
        self.clone().unwrap()
    }

    #[inline]
    fn is_in_subset(value: &T) -> bool {
        relative_eq!(value.norm_squared(), ::one())
    }

    #[inline]
    unsafe fn from_superset_unchecked(value: &T) -> Self {
        Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact.
    }
}

// impl<T: RelativeEq> RelativeEq for Unit<T> {
//     type Epsilon = T::Epsilon;
//
//     #[inline]
//     fn default_epsilon() -> Self::Epsilon {
//         T::default_epsilon()
//     }
//
//     #[inline]
//     fn default_max_relative() -> Self::Epsilon {
//         T::default_max_relative()
//     }
//
//     #[inline]
//     fn default_max_ulps() -> u32 {
//         T::default_max_ulps()
//     }
//
//     #[inline]
//     fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
//         self.value.relative_eq(&other.value, epsilon, max_relative)
//     }
//
//     #[inline]
//     fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
//         self.value.ulps_eq(&other.value, epsilon, max_ulps)
//     }
// }

// FIXME:re-enable this impl when specialization is possible.
// Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display.
/*
impl<T: fmt::Display> fmt::Display for Unit<T> {
    // XXX: will not always work correctly due to rounding errors.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.value.fmt(f)
    }
}
*/

impl<T: Neg> Neg for Unit<T> {
    type Output = Unit<T::Output>;

    #[inline]
    fn neg(self) -> Self::Output {
        Unit::new_unchecked(-self.value)
    }
}

impl<T> Deref for Unit<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        unsafe { mem::transmute(self) }
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::sync::Arc;

pub trait Lang: Debug + Send + Sync {
    fn eval(&self, code: &str, timeout: Option<usize>, context_key: Option<&str>) -> Result<String, String>;
}

pub fn new(cfg: &::LangCfg) -> Arc<Lang> {
    if {
        (if cfg.binary_path.is_some() { 1 } else { 0 })
        + (if cfg.network_address.is_some() { 1 } else { 0 })
        + (if cfg.socket_address.is_some() { 1 } else { 0 })
    } != 1 {
        panic!("LangCfg with more or less than one of binary_path, network_address, socket_address specified");
    }

    if cfg.binary_path.is_some() {
        Arc::new(exec::ExecLang::new(cfg.binary_path.as_ref().unwrap().to_owned(), cfg.binary_args.as_ref().unwrap().clone(), cfg.binary_timeout_arg.clone()))
    } else if cfg.network_address.is_some() {
        Arc::new(remote::network::NetworkLang::new(cfg.network_address.as_ref().unwrap().to_owned()))
    } else if cfg.socket_address.is_some() {
        Arc::new(remote::unixsocket::UnixSocketLang::new(cfg.socket_address.as_ref().unwrap().to_owned()))
    } else {
        panic!("No valid run configuration found")
    }
}

mod exec;
mod remote;
<commit_msg>Fix compile without unixsockets<commit_after>use std::fmt::Debug;
use std::sync::Arc;

pub trait Lang: Debug + Send + Sync {
    fn eval(&self, code: &str, timeout: Option<usize>, context_key: Option<&str>) -> Result<String, String>;
}

pub fn new(cfg: &::LangCfg) -> Arc<Lang> {
    if {
        (if cfg.binary_path.is_some() { 1 } else { 0 })
        + (if cfg.network_address.is_some() { 1 } else { 0 })
        + (if cfg.socket_address.is_some() { 1 } else { 0 })
    } != 1 {
        panic!("LangCfg with more or less than one of binary_path, network_address, socket_address specified");
    }

    if cfg.binary_path.is_some() {
        Arc::new(exec::ExecLang::new(cfg.binary_path.as_ref().unwrap().to_owned(), cfg.binary_args.as_ref().unwrap().clone(), cfg.binary_timeout_arg.clone()))
    } else if cfg.network_address.is_some() {
        Arc::new(remote::network::NetworkLang::new(cfg.network_address.as_ref().unwrap().to_owned()))
    } else if cfg.socket_address.is_some() {
        #[cfg(not(feature = "unixsocket"))]
        panic!("Unix socket functionality not enabled");
        #[cfg(feature = "unixsocket")]
        Arc::new(remote::unixsocket::UnixSocketLang::new(cfg.socket_address.as_ref().unwrap().to_owned()))
    } else {
        panic!("No valid run configuration found");
    }
}

mod exec;
mod remote;
<|endoftext|>


<commit_before>#![feature(slice_patterns)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

// XXX this should probably be split up. The VM has the instructions, a "Thread" has locals, stack, and arguments.
struct VM<'a> {
  instructions: Vec<&'a str>,
  labels: HashMap<&'a str, usize>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr) in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      labels: parse_labels(&instructions),
      instructions: instructions,
    }
  }

  pub fn run(&mut self) {
    let ip = self.labels.get("main").unwrap_or(&0).clone();
    self.run_call(ip, &mut Vec::new());
  }

  // TODO locals
  pub fn run_call(&mut self, start_ip: usize, stack: &mut Vec<Expr>) -> Option<Expr> {
    let mut ip = start_ip;
    let len = self.instructions.len();
    let locals: &mut HashMap<&'a str, Expr> = &mut HashMap::new();

    let mut carry = false; // comparison carry

    let mut arguments = Vec::new();

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") || instr.trim() == "" {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        &["$label", _] => (),
        &["push", "int", n] => stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        &["push", "str", n] => stack.push(Expr::Str(String::from(n))),
        &["push", "arg"] => arguments.push(stack.pop().expect("Nothing on the stack to push to the arguments")),

        &["dup"] => {
          let expr = stack.pop().expect("Nothing on the stack to pop");
          stack.push(expr.clone());
          stack.push(expr);
        },

        // how = "always" | "carry"
        &["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            self.labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        &["carry", "set", val] => carry = val == "true",
        &["carry", "invert"] => carry = !carry,

        &["call", "primitive", "say"] => if let Some(Expr::Str(arg)) = stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        &["call", "primitive", "typeof"] => match stack.pop() {
            Some(Expr::Str(_)) => stack.push(Expr::Str(String::from("str"))),
            Some(Expr::Int(_)) => stack.push(Expr::Str(String::from("int"))),
            None => panic!("VM error: no argument supplied to `typeof`"),
        },

        &["call", "primitive", "convert"] => if let
            (Some(Expr::Str(from)), Some(Expr::Str(to)))
            =
            (stack.pop(), stack.pop()) {

            match (from.as_ref(), to.as_ref()) {
                ("int", "str") => if let Some(Expr::Int(arg)) = stack.pop() {
                  stack.push(Expr::Str(arg.to_string()));
                } else {
                  panic!("VM error: cannot convert int to string");
                },
                _ => panic!("VM error: cannot convert from {} to {}", from, to),
            }
        }
        else {
            panic!("VM error: bad arguments to primitive call `convert`");
        },

        // TODO resolve name in scope, check type, apply
        &["call", name] => {
          let new_ip = self.labels.get(name).expect("VM error: no such label").clone();
          let ret = self.run_call(new_ip, &mut arguments);
          arguments = Vec::new();
          match ret {
            Some(val) => stack.push(val),
            None => (),
          };
        },

        &["ret"] => {
          return None;
        },

        &["ret", "val"] => {
          if stack.len() != 1 {
            panic!("VM error: trying to return a value but the stack size is not 1 ({})", stack.len());
          }
          return stack.pop();
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        &["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (stack.pop(), stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 - arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `math`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        &["cmp", op] => carry = match (stack.pop(), stack.pop()) {
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2))) => match op {
                "<" => arg1 < arg2,
                ">" => arg1 > arg2,
                "<=" => arg1 <= arg2,
                ">=" => arg1 >= arg2,
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for int: {}", op),
            },
            (Some(Expr::Str(arg1)), Some(Expr::Str(arg2))) => match op {
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for str: {}", op),
            },
            _ => panic!("VM error: not enough arguments to `cmp`"),
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        &["local", "load", name] => match locals.get(name) {
          Some(expr) => stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        &["local", "store", name] => if let Some(arg) = stack.pop() {
          // XXX check
          let _ = locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        &[instr, ..] => panic!("VM error: no such instruction {}", instr),
        &[..] => panic!("VM error: Unrecognized instruction!"),
      }
    }

    None
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<commit_msg>Remove 'hey' prefix in primitive say<commit_after>#![feature(slice_patterns)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

// XXX this should probably be split up. The VM has the instructions, a "Thread" has locals, stack, and arguments.
struct VM<'a> {
  instructions: Vec<&'a str>,
  labels: HashMap<&'a str, usize>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr) in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      labels: parse_labels(&instructions),
      instructions: instructions,
    }
  }

  pub fn run(&mut self) {
    let ip = self.labels.get("main").unwrap_or(&0).clone();
    self.run_call(ip, &mut Vec::new());
  }

  // TODO locals
  pub fn run_call(&mut self, start_ip: usize, stack: &mut Vec<Expr>) -> Option<Expr> {
    let mut ip = start_ip;
    let len = self.instructions.len();
    let locals: &mut HashMap<&'a str, Expr> = &mut HashMap::new();

    let mut carry = false; // comparison carry

    let mut arguments = Vec::new();

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") || instr.trim() == "" {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        &["$label", _] => (),
        &["push", "int", n] => stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        &["push", "str", n] => stack.push(Expr::Str(String::from(n))),
        &["push", "arg"] => arguments.push(stack.pop().expect("Nothing on the stack to push to the arguments")),

        &["dup"] => {
          let expr = stack.pop().expect("Nothing on the stack to pop");
          stack.push(expr.clone());
          stack.push(expr);
        },

        // how = "always" | "carry"
        &["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            self.labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        &["carry", "set", val] => carry = val == "true",
        &["carry", "invert"] => carry = !carry,

        &["call", "primitive", "say"] => if let Some(Expr::Str(arg)) = stack.pop() {
          println!("{}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        &["call", "primitive", "typeof"] => match stack.pop() {
            Some(Expr::Str(_)) => stack.push(Expr::Str(String::from("str"))),
            Some(Expr::Int(_)) => stack.push(Expr::Str(String::from("int"))),
            None => panic!("VM error: no argument supplied to `typeof`"),
        },

        &["call", "primitive", "convert"] => if let
            (Some(Expr::Str(from)), Some(Expr::Str(to)))
            =
            (stack.pop(), stack.pop()) {

            match (from.as_ref(), to.as_ref()) {
                ("int", "str") => if let Some(Expr::Int(arg)) = stack.pop() {
                  stack.push(Expr::Str(arg.to_string()));
                } else {
                  panic!("VM error: cannot convert int to string");
                },
                _ => panic!("VM error: cannot convert from {} to {}", from, to),
            }
        }
        else {
            panic!("VM error: bad arguments to primitive call `convert`");
        },

        // TODO resolve name in scope, check type, apply
        &["call", name] => {
          let new_ip = self.labels.get(name).expect("VM error: no such label").clone();
          let ret = self.run_call(new_ip, &mut arguments);
          arguments = Vec::new();
          match ret {
            Some(val) => stack.push(val),
            None => (),
          };
        },

        &["ret"] => {
          return None;
        },

        &["ret", "val"] => {
          if stack.len() != 1 {
            panic!("VM error: trying to return a value but the stack size is not 1 ({})", stack.len());
          }
          return stack.pop();
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        &["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (stack.pop(), stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 - arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `math`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        &["cmp", op] => carry = match (stack.pop(), stack.pop()) {
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2))) => match op {
                "<" => arg1 < arg2,
                ">" => arg1 > arg2,
                "<=" => arg1 <= arg2,
                ">=" => arg1 >= arg2,
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for int: {}", op),
            },
            (Some(Expr::Str(arg1)), Some(Expr::Str(arg2))) => match op {
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for str: {}", op),
            },
            _ => panic!("VM error: not enough arguments to `cmp`"),
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        &["local", "load", name] => match locals.get(name) {
          Some(expr) => stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        &["local", "store", name] => if let Some(arg) = stack.pop() {
          // XXX check
          let _ = locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        &[instr, ..] => panic!("VM error: no such instruction {}", instr),
        &[..] => panic!("VM error: Unrecognized instruction!"),
      }
    }

    None
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<|endoftext|>


<commit_before>//! Read points from .sdf full waveform files.
//!
//! Our sdf library contains some logic to do discretization of waveforms, so we just use that
//! rather than processing the waveforms ourselves.

use std::ffi::OsStr;
use std::path::Path;

use sdf;
use toml;

use Result;
use error::Error;
use point::{Intensity, Point};
use source::{FileSource, Source};

impl Source for sdf::File {
    fn source(&mut self, want: usize) -> Result<Option<Vec<Point>>> {
        let mut points = Vec::with_capacity(want);
        let ref file_info = try!(self.info());
        try!(self.reindex());
        loop {
            match self.read() {
                Ok(ref record) => {
                    points.append(&mut try!(sdf::convert::discretize(record, file_info))
                                           .into_iter()
                                           .map(|p| Point::from(p))
                                           .collect());
                    if points.len() > want {
                        break;
                    }
                }
                Err(sdf::Error::EndOfFile(_)) => {
                    break;
                }
                Err(err) => return Err(Error::from(err)),
            }
        }
        if points.is_empty() {
            Ok(None)
        } else {
            Ok(Some(points))
        }
    }
}

impl From<sdf::convert::Point> for Point {
    fn from(point: sdf::convert::Point) -> Point {
        Point {
            x: point.x as f64,
            y: point.y as f64,
            z: point.z as f64,
            intensity: Intensity::from_u16(point.peak.amplitude),
            return_number: Some(point.target as usize),
            number_of_returns: Some(point.num_target as usize),
            facet_number: Some(point.facet as u8),
            high_channel: Some(point.high_channel),
            ..Default::default()
        }
    }
}

impl FileSource for sdf::File {
    fn open_file_source<P>(path: P, options: Option<&toml::Table>) -> Result<Box<Source>>
        where P: AsRef<Path> + AsRef<OsStr>
    {
        if options.is_some() {
            return Err(Error::InvalidOption("sdf source does not suppport any options at this \
                                             time"
                                                .to_string()));
        }
        let path = OsStr::new(&path);
        Ok(Box::new(try!(sdf::File::open(path.to_str().unwrap()))))
    }
}

#[cfg(test)]
mod tests {

    use sdf;

    use source::{Source, open_file_source};

    #[test]
    fn source_them_all() {
        let mut source = sdf::File::open("data/110630_174316.sdf").unwrap();
        let points = source.source(1000).unwrap().unwrap();
        assert!(points.len() >= 1000);
        source.remove_index().unwrap();
    }

    #[test]
    fn open_file_source_test() {
        let _ = open_file_source("data/110630_174316.sdf", None).unwrap();
    }
}
<commit_msg>Include time in sdf source<commit_after>//! Read points from .sdf full waveform files.
//!
//! Our sdf library contains some logic to do discretization of waveforms, so we just use that
//! rather than processing the waveforms ourselves.

use std::ffi::OsStr;
use std::path::Path;

use sdf;
use toml;

use Result;
use error::Error;
use point::{Intensity, Point};
use source::{FileSource, Source};

impl Source for sdf::File {
    fn source(&mut self, want: usize) -> Result<Option<Vec<Point>>> {
        let mut points = Vec::with_capacity(want);
        let ref file_info = try!(self.info());
        try!(self.reindex());
        loop {
            match self.read() {
                Ok(ref record) => {
                    points.append(&mut try!(sdf::convert::discretize(record, file_info))
                                           .into_iter()
                                           .map(|p| Point::from(p))
                                           .collect());
                    if points.len() > want {
                        break;
                    }
                }
                Err(sdf::Error::EndOfFile(_)) => {
                    break;
                }
                Err(err) => return Err(Error::from(err)),
            }
        }
        if points.is_empty() {
            Ok(None)
        } else {
            Ok(Some(points))
        }
    }
}

impl From<sdf::convert::Point> for Point {
    fn from(point: sdf::convert::Point) -> Point {
        Point {
            x: point.x as f64,
            y: point.y as f64,
            z: point.z as f64,
            intensity: Intensity::from_u16(point.peak.amplitude),
            return_number: Some(point.target as usize),
            number_of_returns: Some(point.num_target as usize),
            facet_number: Some(point.facet as u8),
            high_channel: Some(point.high_channel),
            // TODO this probably isn't always gps time
            gps_time: Some(point.time),
            ..Default::default()
        }
    }
}

impl FileSource for sdf::File {
    fn open_file_source<P>(path: P, options: Option<&toml::Table>) -> Result<Box<Source>>
        where P: AsRef<Path> + AsRef<OsStr>
    {
        if options.is_some() {
            return Err(Error::InvalidOption("sdf source does not suppport any options at this \
                                             time"
                                                .to_string()));
        }
        let path = OsStr::new(&path);
        Ok(Box::new(try!(sdf::File::open(path.to_str().unwrap()))))
    }
}

#[cfg(test)]
mod tests {

    use sdf;

    use source::{Source, open_file_source};

    #[test]
    fn source_them_all() {
        let mut source = sdf::File::open("data/110630_174316.sdf").unwrap();
        let points = source.source(1000).unwrap().unwrap();
        assert!(points.len() >= 1000);
        source.remove_index().unwrap();
    }

    #[test]
    fn open_file_source_test() {
        let _ = open_file_source("data/110630_174316.sdf", None).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use] extern crate log;

use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::path::PathBuf;

use cargo::execute_main_without_stdin;
use cargo::util::{self, CliResult, lev_distance, Config, human, CargoResult, ChainError};

#[derive(RustcDecodable)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: Option<bool>,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    -v, --verbose       Use verbose output
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never

Some common cargo commands are:
    build       Compile the current project
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();
    execute_main_without_stdin(execute, true, USAGE)
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
    try!(config.configure_shell(flags.flag_verbose,
                                flags.flag_quiet,
                                &flags.flag_color));

    init_git_transports(config);
    cargo::util::job::setup();

    if flags.flag_version {
        println!("{}", cargo::version());
        return Ok(None)
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        };
        return Ok(None)
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbose(true);
            let args = &["cargo".to_string(), "-h".to_string()];
            let r = cargo::call_main_without_stdin(execute, config, USAGE, args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" ||
                  flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(),
                       "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => env::args().collect(),
    };

    macro_rules! cmd{
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbose(true);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        })
    }
    each_subcommand!(cmd);

    try!(execute_subcommand(config, &args[1], &args));
    Ok(None)
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter().map(|c| (lev_distance(&c, cmd), c))
                                  .filter(|&(d, _)| d < 4)
                                  .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_subcommand(config: &Config,
                      cmd: &str,
                      args: &[String]) -> CargoResult<()> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
                    .iter()
                    .map(|dir| dir.join(&command_exe))
                    .filter_map(|dir| fs::metadata(&dir).ok().map(|m| (dir, m)))
                    .find(|&(_, ref meta)| is_executable(meta));
    let command = match path {
        Some((command, _)) => command,
        None => {
            return Err(human(match find_closest(config, cmd) {
                Some(closest) => format!("no such subcommand\n\n\t\
                                          Did you mean `{}`?\n", closest),
                None => "no such subcommand".to_string()
            }))
        }
    };
    try!(util::process(&command).args(&args[1..]).exec().chain_error(|| {
        human(format!("third party subcommand `{}` exited unsuccessfully", command_exe))
    }));
    Ok(())
}

/// List all runnable commands. find_command should always succeed
/// if given one of returned command.
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue
            }
            if let Ok(meta) = entry.metadata() {
                if is_executable(&meta) {
                    let end = filename.len() - suffix.len();
                    commands.insert(filename[prefix.len()..end].to_string());
                }
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable(metadata: &fs::Metadata) -> bool {
    use std::os::unix::prelude::*;
    metadata.is_file() && metadata.permissions().mode() & 0o111 != 0
}
#[cfg(windows)]
fn is_executable(metadata: &fs::Metadata) -> bool {
    metadata.is_file()
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>Use stat() instead of lstat() in cargo --list. Fixes #2591<commit_after>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate rustc_serialize;
extern crate toml;
#[macro_use] extern crate log;

use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::path::{Path,PathBuf};

use cargo::execute_main_without_stdin;
use cargo::util::{self, CliResult, lev_distance, Config, human, CargoResult, ChainError};

#[derive(RustcDecodable)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: Option<bool>,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    -v, --verbose       Use verbose output
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never

Some common cargo commands are:
    build       Compile the current project
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();
    execute_main_without_stdin(execute, true, USAGE)
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult<Option<()>> {
    try!(config.configure_shell(flags.flag_verbose,
                                flags.flag_quiet,
                                &flags.flag_color));

    init_git_transports(config);
    cargo::util::job::setup();

    if flags.flag_version {
        println!("{}", cargo::version());
        return Ok(None)
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        };
        return Ok(None)
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbose(true);
            let args = &["cargo".to_string(), "-h".to_string()];
            let r = cargo::call_main_without_stdin(execute, config, USAGE, args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" ||
                  flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(),
                       "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => env::args().collect(),
    };

    macro_rules! cmd{
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbose(true);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            cargo::process_executed(r, &mut config.shell());
            return Ok(None)
        })
    }
    each_subcommand!(cmd);

    try!(execute_subcommand(config, &args[1], &args));
    Ok(None)
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter().map(|c| (lev_distance(&c, cmd), c))
                                  .filter(|&(d, _)| d < 4)
                                  .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_subcommand(config: &Config,
                      cmd: &str,
                      args: &[String]) -> CargoResult<()> {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
                    .iter()
                    .map(|dir| dir.join(&command_exe))
                    .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            return Err(human(match find_closest(config, cmd) {
                Some(closest) => format!("no such subcommand\n\n\t\
                                          Did you mean `{}`?\n", closest),
                None => "no such subcommand".to_string()
            }))
        }
    };
    try!(util::process(&command).args(&args[1..]).exec().chain_error(|| {
        human(format!("third party subcommand `{}` exited unsuccessfully", command_exe))
    }));
    Ok(())
}

/// List all runnable commands. find_command should always succeed
/// if given one of returned command.
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(filename[prefix.len()..end].to_string());
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path).map(|metadata|
        metadata.is_file() && metadata.permissions().mode() & 0o111 != 0
    ).unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).map(|metadata| metadata.is_file()).unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>