<commit_before>use std::cmp::PartialEq;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::hash_map;
use std::rc::Rc;

use super::effect::Effect;
use super::effect_node::{EffectNode, EffectNodeType};
use super::effect_send::EffectSend;
use super::effect_tree::EffectTree;
use super::partial::Partial;

pub enum StreamDest<'a> {
    EffectSends(Vec<EffectSend<'a>>),
    ChannelSink(u8),
}

/// Packages information on how to get the next partial in an effect's output
/// stream, where to send it, and the last retrieved partial.
/// These streams can be sorted based on pending partial's start time so that
/// partials can be handled based on how soon they must be rendered.
pub struct PartialStream<'a> {
    stream : EffectProcessIter,
    dest : StreamDest<'a>,
    pending : Partial,
}

/// Takes an EffectTree and some partials inserted at specific locations and
/// returns a stream of Partials outputted by the tree's root. These partials
/// can then be directly converted into a PCM/waveform signal by a separate
/// renderer.
pub struct EffectTreeRenderer<'a> {
    /// Reference to the tree that describes the connections of each effect
    tree : &'a EffectTree<'a>,
    /// Set of iterators that generate new partials packaged with information
    /// regarding where to send those partials.
    partial_streams : BinaryHeap<PartialStream<'a>>,
    effect_states : HashMap<Rc<EffectNode<'a>>, EffectRenderState>,
}

/// State info about each node in the effect tree
enum EffectRenderState {
    /// see effect::Effect::AmpScale
    AmpScale,
    /// see effect::Effect::StartTimeOffset
    StartTimeOffset,
    /// see effect::Effect::FreqScale
    FreqScale,
    /// All inputs sent to this effect should be sent to the tree's output at a
    /// specific channel
    ChannelSink(u8),
}

/// Each partial sent to an effect creates an iterator that describes the
/// output.
pub struct EffectProcessIter {
    p : Option<Partial>,
}

impl<'a> Ord for PartialStream<'a> {
    fn cmp(&self, other: &Self) -> Ordering {
        // we reverse the ordering so that the *soonest* Partial will always
        // appear at the tip of the heap.
        other.pending.start_time().cmp(&self.pending.start_time())
    }
}

impl<'a> PartialEq for PartialStream<'a> {
    fn eq(&self, other: &Self) -> bool {
         self.cmp(other) == Ordering::Equal
    }
}

impl<'a> Eq for PartialStream<'a> {}

impl<'a> PartialOrd for PartialStream<'a> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        return Some(self.cmp(other))
    }
}

impl<'a> PartialStream<'a> {
    pub fn new(stream : EffectProcessIter,
      dest : StreamDest<'a>, pending : Partial)
      -> PartialStream<'a> {
        PartialStream {
            stream:stream,
            dest:dest,
            pending:pending
        }
    }
}

impl<'a> EffectTreeRenderer <'a> {
    pub fn new(tree : &'a EffectTree<'a>) -> EffectTreeRenderer<'a> {
        EffectTreeRenderer{
            tree:tree,
            partial_streams:BinaryHeap::new(),
            // Create an EffectRenderState::ChannelSink for each root of the tree
            effect_states: tree.iter_roots().enumerate().map(|(ch, root)| {
                (root.clone(), EffectRenderState::new_channel_sink(root.effect(), ch as u8))
            }).collect()
        }
    }
    /// send a partial to the given `dest`
    pub fn feed(&mut self, dest : EffectSend<'a>, partial : &Partial) {
        // send the partial to the effect, which creates an iterator for the effect's output
        let new_iter;
        let new_dests;
        {
            let mut state_entry = self.effect_states.entry(dest.effect_node().clone());
            let render_state = match state_entry {
                hash_map::Entry::Vacant(entry) => {
                    entry.insert(EffectRenderState::new(dest.effect_node().effect()))
                },
                hash_map::Entry::Occupied(ref mut entry) => entry.get_mut()
            };
            new_dests = match render_state {
                &mut EffectRenderState::ChannelSink(ref channel) => {
                    StreamDest::ChannelSink(*channel)
                },
                &mut _ => {
                    StreamDest::EffectSends(dest.effect_node().sends().clone())
                }
            };
            new_iter = render_state.process(partial, dest.send_slot());
        }
        // add the new Partial Iterator into our heap
        self.check_add_stream(new_iter, new_dests);
    }
    /// if `iter` has another item, push its next item, `dest` & `iter`
    /// onto the heap of PartialStreams
    fn check_add_stream(&mut self, mut iter : EffectProcessIter,
      dest : StreamDest<'a> ) {
        iter.next().map(|partial| {
            let stream = PartialStream::new(iter, dest, partial);
            self.partial_streams.push(stream);
        });
    }
    /// Takes the front-most Partial and processes it.
    /// Returns Some(Partial) if this results in a new Partial that has exited
    /// from the root of the tree (ready to be rendered to audio), else None.
    pub fn step(&mut self) -> Option<(u8, Partial)> {
        self.partial_streams.pop().map_or(None, |stream| {
            match stream.dest {
                StreamDest::EffectSends(sends) => {
                    // send the partial to the destination effects/slots
                    for send in &sends {
                        self.feed(send.clone(), &stream.pending);
                    }
                    // since we popped the original stream, we have to re-add it as well:
                    // NOTE: popping & re-pushing IS necessary, since by advancing the iterator,
                    // we alter this stream's position in the queue.
                    self.check_add_stream(stream.stream, StreamDest::EffectSends(sends));
                    None
                }
                // destination is an audio sink; yield the partial
                StreamDest::ChannelSink(channel) => Some((channel, stream.pending))
            }
        })
    }
}

impl EffectRenderState {
    pub fn new(effect : &EffectNodeType) -> EffectRenderState {
        match effect {
            &EffectNodeType::EffectNode(Effect::AmpScale) =>
                EffectRenderState::AmpScale,
            &EffectNodeType::EffectNode(Effect::StartTimeOffset) =>
                EffectRenderState::StartTimeOffset,
            &EffectNodeType::EffectNode(Effect::FreqScale) =>
                EffectRenderState::FreqScale,
            // Don't allow arbitrary sinks; the EffectTree must explicitly specify them.
            &EffectNodeType::Sink => panic!("EffectNodeType::Sink objects \
                must be explicitly declared by EffectTree ahead-of-time"),
        }
    }
    pub fn new_channel_sink(effect : &EffectNodeType, ch : u8) -> EffectRenderState {
        match effect {
            &EffectNodeType::Sink => EffectRenderState::ChannelSink(ch),
            _ => panic!("Tried to create an EffectRenderState::ChannelSink \
                from an EffectNode whose type was not EffectNodeType::Sink"),
        }
    }
    /// Given @partial as an input to the effect through the slot at @slot_no,
    /// returns an iterator that will enerate every future output, where each
    /// generated output's start_usec value increases monotonically.
    pub fn process(&self, partial : &Partial, _slot_no : u32) -> EffectProcessIter {
        match self {
            &EffectRenderState::AmpScale => unimplemented!(),
            &EffectRenderState::StartTimeOffset => unimplemented!(),
            &EffectRenderState::FreqScale => unimplemented!(),
            &EffectRenderState::ChannelSink(ref _channel) => EffectProcessIter{ p:Some(*partial) },
        }
    }
}

impl Iterator for EffectProcessIter {
    type Item = Partial;

    fn next(&mut self) -> Option<Partial> {
        self.p.take()
    }
}
<commit_msg>Remove unneeded EffectTreeRenderer::tree attribute<commit_after>use std::cmp::PartialEq;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::hash_map;
use std::rc::Rc;

use super::effect::Effect;
use super::effect_node::{EffectNode, EffectNodeType};
use super::effect_send::EffectSend;
use super::effect_tree::EffectTree;
use super::partial::Partial;

pub enum StreamDest<'a> {
    EffectSends(Vec<EffectSend<'a>>),
    ChannelSink(u8),
}

/// Packages information on how to get the next partial in an effect's output
/// stream, where to send it, and the last retrieved partial.
/// These streams can be sorted based on pending partial's start time so that
/// partials can be handled based on how soon they must be rendered.
pub struct PartialStream<'a> {
    stream : EffectProcessIter,
    dest : StreamDest<'a>,
    pending : Partial,
}

/// Takes an EffectTree and some partials inserted at specific locations and
/// returns a stream of Partials outputted by the tree's root. These partials
/// can then be directly converted into a PCM/waveform signal by a separate
/// renderer.
pub struct EffectTreeRenderer<'a> {
    /// Set of iterators that generate new partials packaged with information
    /// regarding where to send those partials.
    partial_streams : BinaryHeap<PartialStream<'a>>,
    effect_states : HashMap<Rc<EffectNode<'a>>, EffectRenderState>,
}

/// State info about each node in the effect tree
enum EffectRenderState {
    /// see effect::Effect::AmpScale
    AmpScale,
    /// see effect::Effect::StartTimeOffset
    StartTimeOffset,
    /// see effect::Effect::FreqScale
    FreqScale,
    /// All inputs sent to this effect should be sent to the tree's output at a
    /// specific channel
    ChannelSink(u8),
}

/// Each partial sent to an effect creates an iterator that describes the
/// output.
pub struct EffectProcessIter {
    p : Option<Partial>,
}

impl<'a> Ord for PartialStream<'a> {
    fn cmp(&self, other: &Self) -> Ordering {
        // we reverse the ordering so that the *soonest* Partial will always
        // appear at the tip of the heap.
        other.pending.start_time().cmp(&self.pending.start_time())
    }
}

impl<'a> PartialEq for PartialStream<'a> {
    fn eq(&self, other: &Self) -> bool {
         self.cmp(other) == Ordering::Equal
    }
}

impl<'a> Eq for PartialStream<'a> {}

impl<'a> PartialOrd for PartialStream<'a> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        return Some(self.cmp(other))
    }
}

impl<'a> PartialStream<'a> {
    pub fn new(stream : EffectProcessIter,
      dest : StreamDest<'a>, pending : Partial)
      -> PartialStream<'a> {
        PartialStream {
            stream:stream,
            dest:dest,
            pending:pending
        }
    }
}

impl<'a> EffectTreeRenderer <'a> {
    pub fn new(tree : &'a EffectTree<'a>) -> EffectTreeRenderer<'a> {
        EffectTreeRenderer{
            partial_streams:BinaryHeap::new(),
            // Create an EffectRenderState::ChannelSink for each root of the tree
            effect_states: tree.iter_roots().enumerate().map(|(ch, root)| {
                (root.clone(), EffectRenderState::new_channel_sink(root.effect(), ch as u8))
            }).collect()
        }
    }
    /// send a partial to the given `dest`
    pub fn feed(&mut self, dest : EffectSend<'a>, partial : &Partial) {
        // send the partial to the effect, which creates an iterator for the effect's output
        let new_iter;
        let new_dests;
        {
            let mut state_entry = self.effect_states.entry(dest.effect_node().clone());
            let render_state = match state_entry {
                hash_map::Entry::Vacant(entry) => {
                    entry.insert(EffectRenderState::new(dest.effect_node().effect()))
                },
                hash_map::Entry::Occupied(ref mut entry) => entry.get_mut()
            };
            new_dests = match render_state {
                &mut EffectRenderState::ChannelSink(ref channel) => {
                    StreamDest::ChannelSink(*channel)
                },
                &mut _ => {
                    StreamDest::EffectSends(dest.effect_node().sends().clone())
                }
            };
            new_iter = render_state.process(partial, dest.send_slot());
        }
        // add the new Partial Iterator into our heap
        self.check_add_stream(new_iter, new_dests);
    }
    /// if `iter` has another item, push its next item, `dest` & `iter`
    /// onto the heap of PartialStreams
    fn check_add_stream(&mut self, mut iter : EffectProcessIter,
      dest : StreamDest<'a> ) {
        iter.next().map(|partial| {
            let stream = PartialStream::new(iter, dest, partial);
            self.partial_streams.push(stream);
        });
    }
    /// Takes the front-most Partial and processes it.
    /// Returns Some(Partial) if this results in a new Partial that has exited
    /// from the root of the tree (ready to be rendered to audio), else None.
    pub fn step(&mut self) -> Option<(u8, Partial)> {
        self.partial_streams.pop().map_or(None, |stream| {
            match stream.dest {
                StreamDest::EffectSends(sends) => {
                    // send the partial to the destination effects/slots
                    for send in &sends {
                        self.feed(send.clone(), &stream.pending);
                    }
                    // since we popped the original stream, we have to re-add it as well:
                    // NOTE: popping & re-pushing IS necessary, since by advancing the iterator,
                    // we alter this stream's position in the queue.
                    self.check_add_stream(stream.stream, StreamDest::EffectSends(sends));
                    None
                }
                // destination is an audio sink; yield the partial
                StreamDest::ChannelSink(channel) => Some((channel, stream.pending))
            }
        })
    }
}

impl EffectRenderState {
    pub fn new(effect : &EffectNodeType) -> EffectRenderState {
        match effect {
            &EffectNodeType::EffectNode(Effect::AmpScale) =>
                EffectRenderState::AmpScale,
            &EffectNodeType::EffectNode(Effect::StartTimeOffset) =>
                EffectRenderState::StartTimeOffset,
            &EffectNodeType::EffectNode(Effect::FreqScale) =>
                EffectRenderState::FreqScale,
            // Don't allow arbitrary sinks; the EffectTree must explicitly specify them.
            &EffectNodeType::Sink => panic!("EffectNodeType::Sink objects \
                must be explicitly declared by EffectTree ahead-of-time"),
        }
    }
    pub fn new_channel_sink(effect : &EffectNodeType, ch : u8) -> EffectRenderState {
        match effect {
            &EffectNodeType::Sink => EffectRenderState::ChannelSink(ch),
            _ => panic!("Tried to create an EffectRenderState::ChannelSink \
                from an EffectNode whose type was not EffectNodeType::Sink"),
        }
    }
    /// Given @partial as an input to the effect through the slot at @slot_no,
    /// returns an iterator that will enerate every future output, where each
    /// generated output's start_usec value increases monotonically.
    pub fn process(&self, partial : &Partial, _slot_no : u32) -> EffectProcessIter {
        match self {
            &EffectRenderState::AmpScale => unimplemented!(),
            &EffectRenderState::StartTimeOffset => unimplemented!(),
            &EffectRenderState::FreqScale => unimplemented!(),
            &EffectRenderState::ChannelSink(ref _channel) => EffectProcessIter{ p:Some(*partial) },
        }
    }
}

impl Iterator for EffectProcessIter {
    type Item = Partial;

    fn next(&mut self) -> Option<Partial> {
        self.p.take()
    }
}
<|endoftext|>


<commit_before>//! Retrieval of rooms in which PvP recently occurred. This is an "experimental" endpoint.

use EndpointResult;
use data;
use error::{Result, ApiError};
use std::marker::PhantomData;

/// Call parameters for requesting recent pvp
pub enum PvpArgs {
    /// Retrieves rooms where pvp has occurred recently, with a given number of game ticks.
    WithinLast {
        /// The interval of game ticks to request. It is unknown the maximum interval that may be requested.
        ticks: i64,
    },
    /// Retrieves rooms where pvp has occurred since a given game time.
    Since {
        /// The game "time" (tick number) to request PvP since. It is unknown how far back of a time may be requested.
        time: i64,
    },
}

impl PvpArgs {
    /// Creates a new PvP call parameter to request any PvP occurring since the given game tick.
    pub fn since(tick: i64) -> PvpArgs { PvpArgs::Since { time: tick } }
    /// Creates a new PvP call parameter to request any PvP occurring within the last x ticks.
    pub fn within(ticks: i64) -> PvpArgs { PvpArgs::WithinLast { ticks: ticks } }
}

/// Recent PvP raw result.
#[derive(Deserialize, Debug)]
pub struct Response {
    ok: i32,
    rooms: Vec<InnerRoom>,
    time: i64,
}

#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct InnerRoom {
    _id: String,
    lastPvpTime: i64,
}

/// Result storing recent pvp matches.
pub struct RecentPvp {
    /// A list of room names in which pvp has recently occurred, and the time at which pvp last occurred.
    pub rooms: Vec<(String, i64)>,
    /// The current game time of the server when the call was completed, the tick up to which pvp has been reported.
    pub reported_up_to: i64,
    /// Phantom data in order to allow adding any additional fields in the future.
    #[doc(hidden)]
    pub _phantom: PhantomData<()>,
}

impl EndpointResult for RecentPvp {
    type RequestResult = Response;
    type ErrorResult = data::ApiError;

    fn from_raw(raw: Response) -> Result<RecentPvp> {
        let Response { ok, rooms, time } = raw;

        if ok != 1 {
            return Err(ApiError::NotOk(ok).into());
        }

        Ok(RecentPvp {
            rooms: rooms.into_iter().map(|r| (r._id, r.lastPvpTime)).collect(),
            reported_up_to: time,
            _phantom: PhantomData,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{Response, RecentPvp};
    use EndpointResult;
    use serde_json;

    fn test_parse(json: serde_json::Value) {
        let response: Response = serde_json::from_value(json).unwrap();

        let _ = RecentPvp::from_raw(response).unwrap();
    }

    #[test]
    fn test_sample() {
        test_parse(json! ({
            "ok": 1,
            "rooms": [
                {
                    "_id": "W78S19",
                    "lastPvpTime": 17806851
                },
                {
                    "_id": "E23N77",
                    "lastPvpTime": 17806847
                },
                {
                    "_id": "E84N3",
                    "lastPvpTime": 17806844
                },
                {
                    "_id": "W87N58",
                    "lastPvpTime": 17806843
                }
            ],
            "time": 17806852
        }));
    }
}
<commit_msg>Add some more deriving on pvp result structures<commit_after>//! Retrieval of rooms in which PvP recently occurred. This is an "experimental" endpoint.

use EndpointResult;
use data;
use error::{Result, ApiError};
use std::marker::PhantomData;

/// Call parameters for requesting recent pvp
#[derive(Debug, Copy, Clone)]
pub enum PvpArgs {
    /// Retrieves rooms where pvp has occurred recently, with a given number of game ticks.
    WithinLast {
        /// The interval of game ticks to request. It is unknown the maximum interval that may be requested.
        ticks: i64,
    },
    /// Retrieves rooms where pvp has occurred since a given game time.
    Since {
        /// The game "time" (tick number) to request PvP since. It is unknown how far back of a time may be requested.
        time: i64,
    },
}

impl PvpArgs {
    /// Creates a new PvP call parameter to request any PvP occurring since the given game tick.
    pub fn since(tick: i64) -> PvpArgs { PvpArgs::Since { time: tick } }
    /// Creates a new PvP call parameter to request any PvP occurring within the last x ticks.
    pub fn within(ticks: i64) -> PvpArgs { PvpArgs::WithinLast { ticks: ticks } }
}

/// Recent PvP raw result.
#[derive(Deserialize, Debug)]
pub struct Response {
    ok: i32,
    rooms: Vec<InnerRoom>,
    time: i64,
}

#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct InnerRoom {
    _id: String,
    lastPvpTime: i64,
}

/// Result storing recent pvp matches.
#[derive(Debug, Clone)]
pub struct RecentPvp {
    /// A list of room names in which pvp has recently occurred, and the time at which pvp last occurred.
    pub rooms: Vec<(String, i64)>,
    /// The current game time of the server when the call was completed, the tick up to which pvp has been reported.
    pub reported_up_to: i64,
    /// Phantom data in order to allow adding any additional fields in the future.
    #[doc(hidden)]
    pub _phantom: PhantomData<()>,
}

impl EndpointResult for RecentPvp {
    type RequestResult = Response;
    type ErrorResult = data::ApiError;

    fn from_raw(raw: Response) -> Result<RecentPvp> {
        let Response { ok, rooms, time } = raw;

        if ok != 1 {
            return Err(ApiError::NotOk(ok).into());
        }

        Ok(RecentPvp {
            rooms: rooms.into_iter().map(|r| (r._id, r.lastPvpTime)).collect(),
            reported_up_to: time,
            _phantom: PhantomData,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{Response, RecentPvp};
    use EndpointResult;
    use serde_json;

    fn test_parse(json: serde_json::Value) {
        let response: Response = serde_json::from_value(json).unwrap();

        let _ = RecentPvp::from_raw(response).unwrap();
    }

    #[test]
    fn test_sample() {
        test_parse(json! ({
            "ok": 1,
            "rooms": [
                {
                    "_id": "W78S19",
                    "lastPvpTime": 17806851
                },
                {
                    "_id": "E23N77",
                    "lastPvpTime": 17806847
                },
                {
                    "_id": "E84N3",
                    "lastPvpTime": 17806844
                },
                {
                    "_id": "W87N58",
                    "lastPvpTime": 17806843
                }
            ],
            "time": 17806852
        }));
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::mem;
use std::sync::mpsc;
use std::sync::RwLock;

use rayon::prelude::*;
use rayon;
use anymap;

#[derive(Clone, Default, Debug)]
pub struct Component {
    data: i32,
}

// #[derive(Clone, Default)]
// pub struct VecResource<T> {
//     data: Vec<T>,
// }

#[derive(Clone, Default, Debug)]
pub struct VecResource<T>
    where T: Debug
{
    data: Vec<T>,
}

impl<T> VecResource<T>
    where T: Debug
{
    pub fn new() -> Self {
        VecResource { data: Vec::new() }
    }
}

pub struct Entity(u32);

pub type InputChannel<T> = Vec<T>;
pub type OutputChannel<T> = mpsc::Sender<T>;

pub struct EventSender<E> {
    channels: Vec<RwLock<Vec<E>>>
}

// We never clone the channel senders, so I'm not sure if this is
// really better than just having a Vec<RwLock<E>>, but...
impl<E> EventSender<E> where E: Send {
    fn new() -> Self {
        EventSender {
            channels: Vec::new(),
        }
    }

    pub fn send_to_entity(&self, entity: Entity, event: E) {
        let channel = self.channels.get(entity.0 as usize).expect("Sent message to non-existent entity!");
        let channel_write = &mut channel.write().expect("Attempted to write on poisoned RwLock, aiee!");
        channel_write.push(event);
    }

    pub fn clear(&mut self) {
        // Might as well parallelize?
        // Overhead might not make it worth it.
        // Try it later, see if it matters.
        /*
        self.channels.par_iter_mut()
            .for_each(|q| {
                let q_write = q.try_write().expect("Tried to clear event queues while in use; should never happen!");
                *q_write.clear()
            });
         */
        for q in self.channels.iter_mut() {
            let q_write = &mut q.try_write().expect("Tried to clear event queues while in use; should never happen!");
            q_write.clear()
        }
    }
}

// I feel a little ghetto making one global event type for everything,
// but we'll roll with it for now.
pub struct World<E> where E: Send {
    entities: Vec<Entity>,
    current_components: anymap::AnyMap,
    next_components: anymap::AnyMap,
    current_events: EventSender<E>,
    next_events: EventSender<E>,
}

impl<E> World<E> where E: Send + Sync {
    pub fn new() -> Self {
        World {
            entities: Vec::new(),
            current_components: anymap::AnyMap::new(),
            next_components: anymap::AnyMap::new(),
            current_events: EventSender::new(),
            next_events: EventSender::new(),
        }
    }

    fn register<T>(&mut self)
        where T: Default + 'static
    {
        self.current_components.insert(T::default());
        self.next_components.insert(T::default());
    }

    fn run<F, C>(&mut self, f: F)
        where F: Fn(&C, &[E], &EventSender<E>) -> C + Sync,
              C: Debug + Send + Sync + 'static
    {
        if let Some(resource) = self.current_components.get::<VecResource<C>>() {
            if let Some(next_components) = self.next_components.get_mut::<VecResource<C>>() {
                let d: &[C] = &resource.data;
                let v = &mut next_components.data;
                let next_events = &self.next_events;
                d.par_iter()
                    .zip(&self.current_events.channels)
                    .map(|(c, e)| {
                        let event_queue = e.read().expect("Aiee event queue is poisoned in World::run()");
                        f(c, &event_queue[..], next_events)
                    })
                    .collect_into(v);
            } else {
                panic!("current_components exists but next_components does not, this should never happen!")
            }
        } else {
            panic!("Tried to run a system on an unknown component type");
        }
    }

    // This function finalizes the end of the frame.
    // Delivers events, flips the current and next components, etc.
    fn finish(&mut self) {
        // Switch components
        {
            let m1 = &mut self.current_components;
            let m2 = &mut self.next_components;
            mem::swap(m1, m2);
        }

        // empty out old events, deliver new ones.
        // Making the iterator work easily takes a little
        // bit of explicit type-mongling
        {
            let e1 = &mut self.current_events;
            let e2 = &mut self.next_events;
            mem::swap(e1, e2);
        }
        self.next_events.clear();
    }

    fn next_entity(&self) -> Entity {
        use std::u32;
        assert!(self.entities.len() < u32::MAX as usize);
        Entity(self.entities.len() as u32)
    }

    fn create_entity<T>(&mut self, component: T) where T: Debug + Send + Sync + Clone + 'static {
        let e = self.next_entity();
        self.entities.push(e);

        let nc: &mut VecResource<T> = self.next_components.entry().or_insert_with(VecResource::new);
        nc.data.push(component.clone());
        let components: &mut VecResource<T> = self.current_components.entry().or_insert_with(VecResource::new);
        components.data.push(component);

        self.current_events.channels.push(RwLock::new(Vec::new()));
        self.next_events.channels.push(RwLock::new(Vec::new()));
    }

    fn send_to_entity(&mut self, entity: Entity, event: E) {
        self.next_events.send_to_entity(entity, event);
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_world_thingy() {
        let entity_count = 10;
        let loops = 10;
        let mut w = World::new();
        for i in 0..entity_count {
            w.create_entity(i as usize);
        }
        w.send_to_entity(Entity(3), 0);
        for _ in 0..loops {
            // Call finish to make the event routing happen.
            w.finish();
            let results = w.run(|comp: &usize, events: &[usize], writer: &EventSender<usize>| {
                println!("Component: {} Event: {:?}", comp, events);
                for e in events {
                    writer.send_to_entity(Entity(((*comp+1) % entity_count) as u32), *e + 1);
                }
                *comp
            });
            //println!("Entit are {:?}", results);
        }
        let mut desired_results: Vec<u32> = Vec::new();
        desired_results.extend(&[2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..]);
        assert!(false);
    }
}
<commit_msg>Minor corrections and cleanups of ECS code.<commit_after>use std::fmt::Debug;
use std::mem;
use std::sync::mpsc;
use std::sync::RwLock;

use rayon::prelude::*;
use rayon;
use anymap;

#[derive(Clone, Default, Debug)]
pub struct Component {
    data: i32,
}

// #[derive(Clone, Default)]
// pub struct VecResource<T> {
//     data: Vec<T>,
// }

#[derive(Clone, Default, Debug)]
pub struct VecResource<T>
    where T: Debug
{
    data: Vec<T>,
}

impl<T> VecResource<T>
    where T: Debug
{
    pub fn new() -> Self {
        VecResource { data: Vec::new() }
    }
}

pub struct Entity(u32);

pub type InputChannel<T> = Vec<T>;
pub type OutputChannel<T> = mpsc::Sender<T>;

pub struct EventSender<E> {
    channels: Vec<RwLock<Vec<E>>>
}

// We never clone the channel senders, so I'm not sure if this is
// really better than just having a Vec<RwLock<E>>, but...
impl<E> EventSender<E> where E: Send + Sync {
    fn new() -> Self {
        EventSender {
            channels: Vec::new(),
        }
    }

    pub fn send_to_entity(&self, entity: Entity, event: E) {
        let channel = self.channels.get(entity.0 as usize).expect("Sent message to non-existent entity!");
        let channel_write = &mut channel.write().expect("Attempted to write on poisoned RwLock, aiee!");
        channel_write.push(event);
    }

    pub fn clear(&mut self) {
        // Might as well parallelize?
        // Overhead might not make it worth it.
        // Try it later, see if it matters.

        self.channels.par_iter()
            .for_each(|q| {
                // Not sure if this is actually an optimization but it might be?
                // Depends on how expensive getting a write lock is.
                // ...Probably not more expensive than getting a read lock, tbh.
                let to_clear = {
                    let q_read = &mut q.try_read().unwrap();
                    q_read.len() > 0
                };
                if to_clear {
                    let q_write = &mut q.try_write().expect("Tried to clear event queues while in use; should never happen!");
                    q_write.clear();
                }
            });
    }
}

// I feel a little ghetto making one global event type for everything,
// but we'll roll with it for now.
pub struct World<E> where E: Send {
    entities: Vec<Entity>,
    current_components: anymap::AnyMap,
    next_components: anymap::AnyMap,
    current_events: EventSender<E>,
    next_events: EventSender<E>,
}

impl<E> World<E> where E: Send + Sync {
    pub fn new() -> Self {
        World {
            entities: Vec::new(),
            current_components: anymap::AnyMap::new(),
            next_components: anymap::AnyMap::new(),
            current_events: EventSender::new(),
            next_events: EventSender::new(),
        }
    }

    fn register<T>(&mut self)
        where T: Default + 'static
    {
        self.current_components.insert(T::default());
        self.next_components.insert(T::default());
    }

    fn run<F, C>(&mut self, f: F)
        where F: Fn(&C, &[E], &EventSender<E>) -> C + Sync,
              C: Debug + Send + Sync + 'static
    {
        if let Some(resource) = self.current_components.get::<VecResource<C>>() {
            if let Some(next_components) = self.next_components.get_mut::<VecResource<C>>() {
                let d: &[C] = &resource.data;
                let v = &mut next_components.data;
                let next_events = &self.next_events;
                d.par_iter()
                    .zip(&self.current_events.channels)
                    .map(|(c, e)| {
                        let event_queue = e.read().expect("Aiee event queue is poisoned in World::run()");
                        f(c, &event_queue[..], next_events)
                    })
                    .collect_into(v);
            } else {
                panic!("current_components exists but next_components does not, this should never happen!")
            }
        } else {
            panic!("Tried to run a system on an unknown component type");
        }
    }

    // This function finalizes the end of the frame.
    // Delivers events, flips the current and next components, etc.
    fn finish(&mut self) {
        // Switch components
        {
            let m1 = &mut self.current_components;
            let m2 = &mut self.next_components;
            mem::swap(m1, m2);
        }

        // empty out old events, deliver new ones.
        // Making the iterator work easily takes a little
        // bit of explicit type-mongling
        {
            let e1 = &mut self.current_events;
            let e2 = &mut self.next_events;
            mem::swap(e1, e2);
        }
        self.next_events.clear();
    }

    fn next_entity(&self) -> Entity {
        use std::u32;
        assert!(self.entities.len() < u32::MAX as usize);
        Entity(self.entities.len() as u32)
    }

    fn create_entity<T>(&mut self, component: T) where T: Debug + Send + Sync + Clone + 'static {
        let e = self.next_entity();
        self.entities.push(e);

        let nc: &mut VecResource<T> = self.next_components.entry().or_insert_with(VecResource::new);
        nc.data.push(component.clone());
        let components: &mut VecResource<T> = self.current_components.entry().or_insert_with(VecResource::new);
        components.data.push(component);

        self.current_events.channels.push(RwLock::new(Vec::new()));
        self.next_events.channels.push(RwLock::new(Vec::new()));
    }

    fn send_to_entity(&mut self, entity: Entity, event: E) {
        self.next_events.send_to_entity(entity, event);
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use rand;

    #[test]
    fn test_world_thingy() {
        let entity_count = 100;
        let message_count = 1000;
        let loops = 100;
        let mut w = World::new();
        for i in 0..entity_count {
            w.create_entity(i as usize);
        }
        for i in 0..message_count {
            let dest = rand::random::<u32>() % (entity_count as u32);
            w.send_to_entity(Entity(dest), 0);
        }
        for _ in 0..loops {
            // Call finish to make the event routing happen.
            w.finish();
            w.run(|comp: &usize, events: &[usize], writer: &EventSender<usize>| {
                // println!("Component: {} Event: {:?}", comp, events);
                // Just send any event you get to the next entity index;
                // the event number is how many times it's been sent.
                for e in events {
                    writer.send_to_entity(Entity(((*comp+1) % entity_count) as u32), *e + 1);
                }
                *comp
            });
            //println!("Entit are {:?}", results);
        }
        let mut desired_results: Vec<u32> = Vec::new();
        desired_results.extend(&[2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..]);
        assert!(false);
    }
}
<|endoftext|>


<commit_before>use std::env;

use crate::error::*;
use crate::map::Map;
use crate::source::Source;
use crate::value::{Value, ValueKind};

#[derive(Clone, Debug)]
pub struct Environment {
    /// Optional prefix that will limit access to the environment to only keys that
    /// begin with the defined prefix.
    ///
    /// A prefix with a separator of `_` is tested to be present on each key before its considered
    /// to be part of the source environment.
    ///
    /// For example, the key `CONFIG_DEBUG` would become `DEBUG` with a prefix of `config`.
    prefix: Option<String>,

    /// Optional character sequence that separates each key segment in an environment key pattern.
    /// Consider a nested configuration such as `redis.password`, a separator of `_` would allow
    /// an environment key of `REDIS_PASSWORD` to match.
    separator: Option<String>,

    /// Ignore empty env values (treat as unset).
    ignore_empty: bool,

    /// Parses booleans, integers and floats if they're detected (can be safely parsed).
    try_parsing: bool,
}

impl Environment {
    pub fn new() -> Self {
        Environment::default()
    }

    pub fn with_prefix(s: &str) -> Self {
        Environment {
            prefix: Some(s.into()),
            ..Environment::default()
        }
    }

    pub fn prefix(mut self, s: &str) -> Self {
        self.prefix = Some(s.into());
        self
    }

    pub fn separator(mut self, s: &str) -> Self {
        self.separator = Some(s.into());
        self
    }

    pub fn ignore_empty(mut self, ignore: bool) -> Self {
        self.ignore_empty = ignore;
        self
    }

    /// Note: enabling `try_parsing` can reduce performance it will try and parse
    /// each environment variable 3 times (bool, i64, f64)
    pub fn try_parsing(mut self, try_parsing: bool) -> Self {
        self.try_parsing = try_parsing;
        self
    }
}

impl Default for Environment {
    fn default() -> Environment {
        Environment {
            prefix: None,
            separator: None,
            ignore_empty: false,
            try_parsing: false,
        }
    }
}

impl Source for Environment {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<Map<String, Value>> {
        let mut m = Map::new();
        let uri: String = "the environment".into();

        let separator = self.separator.as_deref().unwrap_or("");
        let group_separator = self.separator.as_deref().unwrap_or("_");

        // Define a prefix pattern to test and exclude from keys
        let prefix_pattern = self
            .prefix
            .as_ref()
            .map(|prefix| format!("{}{}", prefix, group_separator).to_lowercase());

        for (key, value) in env::vars() {
            // Treat empty environment variables as unset
            if self.ignore_empty && value.is_empty() {
                continue;
            }

            let mut key = key.to_lowercase();

            // Check for prefix
            if let Some(ref prefix_pattern) = prefix_pattern {
                if key.starts_with(prefix_pattern) {
                    // Remove this prefix from the key
                    key = key[prefix_pattern.len()..].to_string();
                } else {
                    // Skip this key
                    continue;
                }
            }

            // If separator is given replace with `.`
            if !separator.is_empty() {
                key = key.replace(separator, ".");
            }

            let value = if self.try_parsing {
                // convert to lowercase because bool parsing expects all lowercase
                if let Ok(parsed) = value.to_lowercase().parse::<bool>() {
                    ValueKind::Boolean(parsed)
                } else if let Ok(parsed) = value.parse::<i64>() {
                    ValueKind::Integer(parsed)
                } else if let Ok(parsed) = value.parse::<f64>() {
                    ValueKind::Float(parsed)
                } else {
                    ValueKind::String(value)
                }
            } else {
                ValueKind::String(value)
            };

            m.insert(key, Value::new(Some(&uri), value));
        }

        Ok(m)
    }
}
<commit_msg>Fix clippy: Remove Default impl for Environment, derive it<commit_after>use std::env;

use crate::error::*;
use crate::map::Map;
use crate::source::Source;
use crate::value::{Value, ValueKind};

#[derive(Clone, Debug, Default)]
pub struct Environment {
    /// Optional prefix that will limit access to the environment to only keys that
    /// begin with the defined prefix.
    ///
    /// A prefix with a separator of `_` is tested to be present on each key before its considered
    /// to be part of the source environment.
    ///
    /// For example, the key `CONFIG_DEBUG` would become `DEBUG` with a prefix of `config`.
    prefix: Option<String>,

    /// Optional character sequence that separates each key segment in an environment key pattern.
    /// Consider a nested configuration such as `redis.password`, a separator of `_` would allow
    /// an environment key of `REDIS_PASSWORD` to match.
    separator: Option<String>,

    /// Ignore empty env values (treat as unset).
    ignore_empty: bool,

    /// Parses booleans, integers and floats if they're detected (can be safely parsed).
    try_parsing: bool,
}

impl Environment {
    pub fn new() -> Self {
        Environment::default()
    }

    pub fn with_prefix(s: &str) -> Self {
        Environment {
            prefix: Some(s.into()),
            ..Environment::default()
        }
    }

    pub fn prefix(mut self, s: &str) -> Self {
        self.prefix = Some(s.into());
        self
    }

    pub fn separator(mut self, s: &str) -> Self {
        self.separator = Some(s.into());
        self
    }

    pub fn ignore_empty(mut self, ignore: bool) -> Self {
        self.ignore_empty = ignore;
        self
    }

    /// Note: enabling `try_parsing` can reduce performance it will try and parse
    /// each environment variable 3 times (bool, i64, f64)
    pub fn try_parsing(mut self, try_parsing: bool) -> Self {
        self.try_parsing = try_parsing;
        self
    }
}

impl Source for Environment {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<Map<String, Value>> {
        let mut m = Map::new();
        let uri: String = "the environment".into();

        let separator = self.separator.as_deref().unwrap_or("");
        let group_separator = self.separator.as_deref().unwrap_or("_");

        // Define a prefix pattern to test and exclude from keys
        let prefix_pattern = self
            .prefix
            .as_ref()
            .map(|prefix| format!("{}{}", prefix, group_separator).to_lowercase());

        for (key, value) in env::vars() {
            // Treat empty environment variables as unset
            if self.ignore_empty && value.is_empty() {
                continue;
            }

            let mut key = key.to_lowercase();

            // Check for prefix
            if let Some(ref prefix_pattern) = prefix_pattern {
                if key.starts_with(prefix_pattern) {
                    // Remove this prefix from the key
                    key = key[prefix_pattern.len()..].to_string();
                } else {
                    // Skip this key
                    continue;
                }
            }

            // If separator is given replace with `.`
            if !separator.is_empty() {
                key = key.replace(separator, ".");
            }

            let value = if self.try_parsing {
                // convert to lowercase because bool parsing expects all lowercase
                if let Ok(parsed) = value.to_lowercase().parse::<bool>() {
                    ValueKind::Boolean(parsed)
                } else if let Ok(parsed) = value.parse::<i64>() {
                    ValueKind::Integer(parsed)
                } else if let Ok(parsed) = value.parse::<f64>() {
                    ValueKind::Float(parsed)
                } else {
                    ValueKind::String(value)
                }
            } else {
                ValueKind::String(value)
            };

            m.insert(key, Value::new(Some(&uri), value));
        }

        Ok(m)
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::slice;

use libc::{c_void, c_double};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}

use super::convert_to_bng_threaded_vec;
use super::convert_to_lonlat_threaded_vec;
use super::convert_to_osgb36_threaded_vec;
use super::convert_to_etrs89_threaded_vec;
use super::convert_etrs89_to_osgb36_threaded_vec;
use super::convert_etrs89_to_ll_threaded_vec;
use super::convert_osgb36_to_ll_threaded_vec;
use super::convert_osgb36_to_etrs89_threaded_vec;

/// Free memory which Rust has allocated across the FFI boundary (f64 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_float_array(eastings, northings);
/// ```
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(lons.data as *mut c_double, lons.len, lons.len) };
    unsafe { Vec::from_raw_parts(lats.data as *mut c_double, lats.len, lats.len) };
}

impl Array {
    pub unsafe fn as_f64_slice(&self) -> &[f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f64, self.len as usize)
    }

    pub fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t,
        };

        // Leak the memory, and now the raw pointer (and
        // eventually the FFI parent process) is the owner
        mem::forget(vec);

        array
    }
}

/// A threaded, FFI-compatible wrapper for `lonlat_bng::convert_bng`
///
/// # Examples
///
/// ```
/// extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306,
///                              0.95511887434519682,
///                              0.44975855518383501,
///                              -0.096813621191803811,
///                              -0.36807065656416427,
///                              0.63486335458665621];
/// let lat_vec: Vec<f64> = vec![54.589097162646141,
///                              51.560873800587828,
///                              50.431429161121699,
///                              54.535021436247419,
///                              50.839059313135706,
///                              55.412189281234419];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// ```
/// For an FFI implementation, see the code at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py).
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_bng_threaded(longitudes: Array, latitudes: Array) -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_bng_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_lonlat`](fn.convert_lonlat.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) , substituting i32 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_lonlat_threaded(eastings: Array, northings: Array) -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_to_lonlat_threaded_vec(&eastings_vec,
                                                                               &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36`](fn.convert_osgb36.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_osgb36_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_osgb36_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89`](fn.convert_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_etrs89_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_etrs89_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_osgb36`](fn.convert_etrs89_to_osgb36.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_osgb36_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) =
        convert_etrs89_to_osgb36_threaded_vec(&eastings_vec, &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_ll`](fn.convert_etrs89_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_etrs89_to_ll_threaded_vec(&eastings_vec,
                                                                                &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_osgb36_to_ll_threaded_vec(&eastings_vec,
                                                                                &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_etrs89`](fn.convert_osgb36_to_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_etrs89_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) =
        convert_osgb36_to_etrs89_threaded_vec(&eastings_vec, &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}
<commit_msg>Re-add missing libc declaration<commit_after>use std::mem;
use std::slice;

extern crate libc;
use libc::{c_void, c_double};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: libc::size_t,
}

use super::convert_to_bng_threaded_vec;
use super::convert_to_lonlat_threaded_vec;
use super::convert_to_osgb36_threaded_vec;
use super::convert_to_etrs89_threaded_vec;
use super::convert_etrs89_to_osgb36_threaded_vec;
use super::convert_etrs89_to_ll_threaded_vec;
use super::convert_osgb36_to_ll_threaded_vec;
use super::convert_osgb36_to_etrs89_threaded_vec;

/// Free memory which Rust has allocated across the FFI boundary (f64 values)
///
/// # Examples
///
/// ```
/// # extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306];
/// let lat_vec: Vec<f64> = vec![54.589097162646141];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// drop_float_array(eastings, northings);
/// ```
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(lons: Array, lats: Array) {
    if lons.data.is_null() {
        return;
    }
    if lats.data.is_null() {
        return;
    }
    unsafe { Vec::from_raw_parts(lons.data as *mut c_double, lons.len, lons.len) };
    unsafe { Vec::from_raw_parts(lats.data as *mut c_double, lats.len, lats.len) };
}

impl Array {
    pub unsafe fn as_f64_slice(&self) -> &[f64] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f64, self.len as usize)
    }

    pub fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t,
        };

        // Leak the memory, and now the raw pointer (and
        // eventually the FFI parent process) is the owner
        mem::forget(vec);

        array
    }
}

/// A threaded, FFI-compatible wrapper for `lonlat_bng::convert_bng`
///
/// # Examples
///
/// ```
/// extern crate libc;
/// let lon_vec: Vec<f64> = vec![-2.0183041005533306,
///                              0.95511887434519682,
///                              0.44975855518383501,
///                              -0.096813621191803811,
///                              -0.36807065656416427,
///                              0.63486335458665621];
/// let lat_vec: Vec<f64> = vec![54.589097162646141,
///                              51.560873800587828,
///                              50.431429161121699,
///                              54.535021436247419,
///                              50.839059313135706,
///                              55.412189281234419];
/// let lon_arr = Array {
///     data: lon_vec.as_ptr() as *const libc::c_void,
///     len: lon_vec.len() as libc::size_t,
/// };
/// let lat_arr = Array {
///     data: lat_vec.as_ptr() as *const libc::c_void,
///     len: lat_vec.len() as libc::size_t,
/// };
/// let (eastings, northings) = convert_to_bng_threaded(lon_arr, lat_arr);
/// ```
/// For an FFI implementation, see the code at [Convertbng](https://github.com/urschrei/convertbng/blob/master/convertbng/util.py).
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_bng_threaded(longitudes: Array, latitudes: Array) -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_bng_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_lonlat`](fn.convert_lonlat.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) , substituting i32 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_lonlat_threaded(eastings: Array, northings: Array) -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_to_lonlat_threaded_vec(&eastings_vec,
                                                                               &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36`](fn.convert_osgb36.html)
///
/// # Examples
///
/// See [`lonlat_bng::convert_to_bng_threaded`](fn.convert_to_bng_threaded.html) for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_osgb36_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_osgb36_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89`](fn.convert_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples, substituting f64 vectors
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_to_etrs89_threaded(longitudes: Array,
                                             latitudes: Array)
                                             -> (Array, Array) {
    let longitudes_vec = unsafe { longitudes.as_f64_slice().to_vec() };
    let latitudes_vec = unsafe { latitudes.as_f64_slice().to_vec() };
    let (eastings, northings) = convert_to_etrs89_threaded_vec(&longitudes_vec, &latitudes_vec);
    (Array::from_vec(eastings), Array::from_vec(northings))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_osgb36`](fn.convert_etrs89_to_osgb36.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_osgb36_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) =
        convert_etrs89_to_osgb36_threaded_vec(&eastings_vec, &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_etrs89_to_ll`](fn.convert_etrs89_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_etrs89_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_etrs89_to_ll_threaded_vec(&eastings_vec,
                                                                                &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_ll`](fn.convert_osgb36_to_ll.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_ll_threaded(eastings: Array,
                                                northings: Array)
                                                -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) = convert_osgb36_to_ll_threaded_vec(&eastings_vec,
                                                                                &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}

/// A threaded, FFI-compatible wrapper for [`lonlat_bng::convert_osgb36_to_etrs89`](fn.convert_osgb36_to_etrs89.html)
///
/// # Examples
///
/// See `lonlat_bng::convert_to_bng_threaded` for examples
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn convert_osgb36_to_etrs89_threaded(eastings: Array,
                                                    northings: Array)
                                                    -> (Array, Array) {
    let eastings_vec = unsafe { eastings.as_f64_slice().to_vec() };
    let northings_vec = unsafe { northings.as_f64_slice().to_vec() };
    let (eastings_shifted, northings_shifted) =
        convert_osgb36_to_etrs89_threaded_vec(&eastings_vec, &northings_vec);
    (Array::from_vec(eastings_shifted),
     Array::from_vec(northings_shifted))
}
<|endoftext|>


<commit_before>// -*- flycheck-rust-crate-root: "lib.rs" -*-
use libc::{c_char, c_int, c_double, c_void, c_ushort};
use std::ptr;

pub struct Document;
pub struct Context;
pub struct XPathObject {
    xpath_type: c_ushort,
    node_set: *const NodeSet,
    bool_val: c_int,
    float_val: c_double,
    string_val: *const c_char,
    user: *const c_void,
    index: c_int,
    user2: *const c_void,
    index2: c_int
}
pub struct NodeSet {
    node_nr: c_int,
    node_max: c_int,
    node_tab: *const Node
}
pub struct Node {
    private: *const c_void,
    element_type: c_ushort,
    name: *const c_char,
    children: *const Node,
    last: *const Node,
    parent: *const Node,
    next: *const Node,
    prev: *const Node,
    doc: *const Document,
    namespace: *const Namespace,
    content: *const c_char,
    properties: *const Attribute,
    namespace_def: *const Namespace,
    psvi: *const c_void,
    line: c_ushort,
    extra: c_ushort
}
pub struct Namespace;
pub struct Attribute;

#[link(name = "xml2")]
extern {
    pub fn xmlParseDoc(body: *const c_char) -> *const Document;
    pub fn xmlParseFile(filename: *const c_char) -> *const Document;
    pub fn xmlFreeDoc(doc: *const Document);

    pub fn xmlXPathNewContext(doc: *const Document) -> *const Context;
    pub fn xmlXPathFreeContext(context: *const Context);

    pub fn xmlXPathEvalExpression(xpath: *const c_char, context: *const Context)
                                  -> *const XPathObject;
    pub fn xmlXPathFreeObject(object: *const XPathObject);
}

#[inline]
fn xml_xpath_node_set_is_empty(ns: *const NodeSet) -> bool {
    unsafe {
        ns.is_null() || (*ns).node_nr==0 || (*ns).node_tab.is_null()
    }
}

impl XPathObject {
    pub fn from_context(context: *const Context,
                        xpath: &str) -> *const XPathObject
    {
        unsafe {
            let result = xmlXPathEvalExpression(xpath.to_c_str().as_ptr(),
                                                context);
            if result.is_null() {
                ptr::null()
            } else if xml_xpath_node_set_is_empty((*result).node_set) {
                xmlXPathFreeObject(result);
                ptr::null()
            } else {
                result
            }
        }
    }
}
<commit_msg>Most fields are irrelevant to the library.<commit_after>// -*- flycheck-rust-crate-root: "lib.rs" -*-
use libc::{c_char, c_int, c_double, c_void, c_ushort};
use std::ptr;

pub struct Document;
pub struct Context;
#[allow(dead_code)]
pub struct XPathObject {
    xpath_type: c_ushort,
    node_set: *const NodeSet,
    bool_val: c_int,
    float_val: c_double,
    string_val: *const c_char,
    user: *const c_void,
    index: c_int,
    user2: *const c_void,
    index2: c_int
}
#[allow(dead_code)]
pub struct NodeSet {
    node_nr: c_int,
    node_max: c_int,
    node_tab: *const Node
}
#[allow(dead_code)]
pub struct Node {
    private: *const c_void,
    element_type: c_ushort,
    name: *const c_char,
    children: *const Node,
    last: *const Node,
    parent: *const Node,
    next: *const Node,
    prev: *const Node,
    doc: *const Document,
    namespace: *const Namespace,
    content: *const c_char,
    properties: *const Attribute,
    namespace_def: *const Namespace,
    psvi: *const c_void,
    line: c_ushort,
    extra: c_ushort
}
pub struct Namespace;
pub struct Attribute;

#[link(name = "xml2")]
extern {
    pub fn xmlParseDoc(body: *const c_char) -> *const Document;
    pub fn xmlParseFile(filename: *const c_char) -> *const Document;
    pub fn xmlFreeDoc(doc: *const Document);

    pub fn xmlXPathNewContext(doc: *const Document) -> *const Context;
    pub fn xmlXPathFreeContext(context: *const Context);

    pub fn xmlXPathEvalExpression(xpath: *const c_char, context: *const Context)
                                  -> *const XPathObject;
    pub fn xmlXPathFreeObject(object: *const XPathObject);
}

#[inline]
fn xml_xpath_node_set_is_empty(ns: *const NodeSet) -> bool {
    unsafe {
        ns.is_null() || (*ns).node_nr==0 || (*ns).node_tab.is_null()
    }
}

impl XPathObject {
    pub fn from_context(context: *const Context,
                        xpath: &str) -> *const XPathObject
    {
        unsafe {
            let result = xmlXPathEvalExpression(xpath.to_c_str().as_ptr(),
                                                context);
            if result.is_null() {
                ptr::null()
            } else if xml_xpath_node_set_is_empty((*result).node_set) {
                xmlXPathFreeObject(result);
                ptr::null()
            } else {
                result
            }
        }
    }
}
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! FFI bindings
use libc::{c_int, c_uchar, c_uint, c_void};

pub const SECP256K1_START_VERIFY: c_uint = 0x1;
pub const SECP256K1_START_SIGN: c_uint = 0x2;

/// A nonce generation function. Ordinary users of the library
/// never need to see this type; only if you need to control
/// nonce generation do you need to use it. I have deliberately
/// made this hard to do: you have to write your own wrapper
/// around the FFI functions to use it. And it's an unsafe type.
/// Nonces are generated deterministically by RFC6979 by
/// default; there should be no need to ever change this.
pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar,
                                        msg32: *const c_uchar,
                                        key32: *const c_uchar,
                                        attempt: c_uint,
                                        data: *const c_void);

#[repr(C)]
struct ContextInner;

/// A Secp256k1 context, containing various precomputed values and such
/// needed to do elliptic curve computations. If you create one of these
/// with `secp256k1_context_create` you MUST destroy it with
/// `secp256k1_context_destroy`, or else you will have a memory leak.
/// Furthermore, you MUST NOT use this object after destroying it; it is
/// `Copy` so the compiler will not help you to avoid this. There is no
/// need for ordinary users of this library to ever use this type directly.
#[repr(C)]
#[allow(raw_pointer_derive)]
#[derive(Copy, Clone, Debug)]
pub struct Context(*mut ContextInner);

#[link(name = "secp256k1")]
extern "C" {
    pub static secp256k1_nonce_function_rfc6979: NonceFn;

    pub static secp256k1_nonce_function_default: NonceFn;

    pub fn secp256k1_context_create(flags: c_uint) -> Context;

    pub fn secp256k1_context_clone(cx: Context) -> Context;

    pub fn secp256k1_context_destroy(cx: Context);

    pub fn secp256k1_ecdsa_verify(cx: Context, msg32: *const c_uchar,
                                  sig: *const c_uchar, sig_len: c_int,
                                  pk: *const c_uchar, pk_len: c_int)
                                  -> c_int;

    pub fn secp256k1_ec_pubkey_create(cx: Context,
                                      pk: *mut c_uchar, pk_len: *mut c_int,
                                      sk: *const c_uchar, compressed: c_int)
                                      -> c_int;

    pub fn secp256k1_ecdsa_sign(cx: Context, msg32: *const c_uchar,
                                sig: *mut c_uchar, sig_len: *mut c_int,
                                sk: *const c_uchar,
                                noncefn: NonceFn, noncedata: *const c_void)
                                -> c_int;

    pub fn secp256k1_ecdsa_sign_compact(cx: Context, msg: *const c_uchar,
                                        sig64: *mut c_uchar, sk: *const c_uchar,
                                        noncefn: NonceFn, noncedata: *const c_void,
                                        recid: *mut c_int)
                                        -> c_int;

    pub fn secp256k1_ecdsa_recover_compact(cx: Context, msg32: *const c_uchar,
                                           sig64: *const c_uchar, pk: *mut c_uchar,
                                           pk_len: *mut c_int, compressed: c_int,
                                           recid: c_int) -> c_int;

    pub fn secp256k1_ec_seckey_verify(cx: Context,
                                      sk: *const c_uchar) -> c_int;

    pub fn secp256k1_ec_pubkey_verify(cx: Context,
                                      pk: *const c_uchar,
                                      pk_len: c_int) -> c_int;

//TODO secp256k1_ec_pubkey_decompress
//TODO secp256k1_ec_privkey_export
//TODO secp256k1_ec_privkey_import

    pub fn secp256k1_ec_privkey_tweak_add(cx: Context,
                                          sk: *mut c_uchar,
                                          tweak: *const c_uchar)
                                          -> c_int;

    pub fn secp256k1_ec_pubkey_tweak_add(cx: Context,
                                         pk: *mut c_uchar,
                                         pk_len: c_int,
                                         tweak: *const c_uchar)
                                         -> c_int;

    pub fn secp256k1_ec_privkey_tweak_mul(cx: Context,
                                          sk: *mut c_uchar,
                                          tweak: *const c_uchar)
                                          -> c_int;

    pub fn secp256k1_ec_pubkey_tweak_mul(cx: Context,
                                         pk: *mut c_uchar,
                                         pk_len: c_int,
                                         tweak: *const c_uchar)
                                         -> c_int;
}

<commit_msg>Impl `Send` and `Sync` for secp256k1 contexts<commit_after>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! FFI bindings
use libc::{c_int, c_uchar, c_uint, c_void};

pub const SECP256K1_START_VERIFY: c_uint = 0x1;
pub const SECP256K1_START_SIGN: c_uint = 0x2;

/// A nonce generation function. Ordinary users of the library
/// never need to see this type; only if you need to control
/// nonce generation do you need to use it. I have deliberately
/// made this hard to do: you have to write your own wrapper
/// around the FFI functions to use it. And it's an unsafe type.
/// Nonces are generated deterministically by RFC6979 by
/// default; there should be no need to ever change this.
pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar,
                                        msg32: *const c_uchar,
                                        key32: *const c_uchar,
                                        attempt: c_uint,
                                        data: *const c_void);

#[repr(C)]
struct ContextInner;

/// A Secp256k1 context, containing various precomputed values and such
/// needed to do elliptic curve computations. If you create one of these
/// with `secp256k1_context_create` you MUST destroy it with
/// `secp256k1_context_destroy`, or else you will have a memory leak.
/// Furthermore, you MUST NOT use this object after destroying it; it is
/// `Copy` so the compiler will not help you to avoid this. There is no
/// need for ordinary users of this library to ever use this type directly.
#[repr(C)]
#[allow(raw_pointer_derive)]
#[derive(Copy, Clone, Debug)]
pub struct Context(*mut ContextInner);

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

#[link(name = "secp256k1")]
extern "C" {
    pub static secp256k1_nonce_function_rfc6979: NonceFn;

    pub static secp256k1_nonce_function_default: NonceFn;

    pub fn secp256k1_context_create(flags: c_uint) -> Context;

    pub fn secp256k1_context_clone(cx: Context) -> Context;

    pub fn secp256k1_context_destroy(cx: Context);

    pub fn secp256k1_ecdsa_verify(cx: Context, msg32: *const c_uchar,
                                  sig: *const c_uchar, sig_len: c_int,
                                  pk: *const c_uchar, pk_len: c_int)
                                  -> c_int;

    pub fn secp256k1_ec_pubkey_create(cx: Context,
                                      pk: *mut c_uchar, pk_len: *mut c_int,
                                      sk: *const c_uchar, compressed: c_int)
                                      -> c_int;

    pub fn secp256k1_ecdsa_sign(cx: Context, msg32: *const c_uchar,
                                sig: *mut c_uchar, sig_len: *mut c_int,
                                sk: *const c_uchar,
                                noncefn: NonceFn, noncedata: *const c_void)
                                -> c_int;

    pub fn secp256k1_ecdsa_sign_compact(cx: Context, msg: *const c_uchar,
                                        sig64: *mut c_uchar, sk: *const c_uchar,
                                        noncefn: NonceFn, noncedata: *const c_void,
                                        recid: *mut c_int)
                                        -> c_int;

    pub fn secp256k1_ecdsa_recover_compact(cx: Context, msg32: *const c_uchar,
                                           sig64: *const c_uchar, pk: *mut c_uchar,
                                           pk_len: *mut c_int, compressed: c_int,
                                           recid: c_int) -> c_int;

    pub fn secp256k1_ec_seckey_verify(cx: Context,
                                      sk: *const c_uchar) -> c_int;

    pub fn secp256k1_ec_pubkey_verify(cx: Context,
                                      pk: *const c_uchar,
                                      pk_len: c_int) -> c_int;

//TODO secp256k1_ec_pubkey_decompress
//TODO secp256k1_ec_privkey_export
//TODO secp256k1_ec_privkey_import

    pub fn secp256k1_ec_privkey_tweak_add(cx: Context,
                                          sk: *mut c_uchar,
                                          tweak: *const c_uchar)
                                          -> c_int;

    pub fn secp256k1_ec_pubkey_tweak_add(cx: Context,
                                         pk: *mut c_uchar,
                                         pk_len: c_int,
                                         tweak: *const c_uchar)
                                         -> c_int;

    pub fn secp256k1_ec_privkey_tweak_mul(cx: Context,
                                          sk: *mut c_uchar,
                                          tweak: *const c_uchar)
                                          -> c_int;

    pub fn secp256k1_ec_pubkey_tweak_mul(cx: Context,
                                         pk: *mut c_uchar,
                                         pk_len: c_int,
                                         tweak: *const c_uchar)
                                         -> c_int;
}

<|endoftext|>