<commit_before>//! Runs the data provision server, as a component of the patch server.
extern crate rand;
extern crate crypto;
extern crate psocrypto;
extern crate idola;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate byteorder;

use std::net::TcpListener;
use std::net::TcpStream;
use std::thread;
use std::io;
use std::io::{Cursor, Read, Write};

use crypto::symmetriccipher::{Decryptor, Encryptor};
use crypto::buffer::{RefReadBuffer, RefWriteBuffer};
use psocrypto::PcCipher;

use rand::random;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::*;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

struct ClientContext {
    pub stream: TcpStream,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    fn read_ack(&mut self, enc: bool) -> io::Result<(u16, u16)> {
        let size;
        let ty;
        let mut rbuf = [0u8; 4];
        let mut ebuf = [0u8; 4];
        let mut cur;
        {try!(self.stream.read(&mut rbuf));}
        if enc {
            {
                if let Err(e) = self.client_cipher.decrypt(
                    &mut RefReadBuffer::new(&rbuf[..]),
                    &mut RefWriteBuffer::new(&mut ebuf[..]), false) {
                    return Err(io::Error::new(io::ErrorKind::Other, format!("unable to encrypt: {:?}", e)))
                }
            }
            {
                cur = Cursor::new(&ebuf);
                size = cur.read_u16::<LittleEndian>().unwrap();
                ty = cur.read_u16::<LittleEndian>().unwrap();
            }
        } else {
            cur = Cursor::new(&rbuf);
            size = cur.read_u16::<LittleEndian>().unwrap();
            ty = cur.read_u16::<LittleEndian>().unwrap();
        }
        Ok((size, ty))
    }

    fn write_ack(&mut self, enc: bool, ack: (u16, u16)) -> io::Result<()> {
        let (size, ty) = ack;
        let mut wbuf = [0u8; 4];
        let mut ebuf = [0u8; 4];
        {
            let mut cur = Cursor::new(&mut wbuf[..]);
            try!(cur.write_u16::<LittleEndian>(size));
            try!(cur.write_u16::<LittleEndian>(ty));
        }
        if enc {
            if let Err(e) = self.server_cipher.encrypt(
                &mut RefReadBuffer::new(& wbuf[..]),
                &mut RefWriteBuffer::new(&mut ebuf), false) {
                Err(io::Error::new(
                    io::ErrorKind::Other, format!("unable to encrypt ack message: {:?}", e)))
            } else {
                try!(self.stream.write_all(&ebuf));
                self.stream.flush()
            }
        } else {
            try!(self.stream.write_all(&wbuf));
            self.stream.flush()
        }
    }

    /// Send a message struct.
    fn send_msg(&mut self, msg: &MessageEncode, encrypt: bool) -> io::Result<()> {
        if encrypt {
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum. Will
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

fn handle_client(mut ctx: ClientContext) {
    let peer = ctx.stream.peer_addr().unwrap();

    info!("connected {}", peer);

    let w = Welcome {
        client_vector: ctx.client_cipher.seed(),
        server_vector: ctx.server_cipher.seed()
    };
    ctx.send_msg(&w, false).unwrap();

    if let Ok((4, 2)) = ctx.read_ack(true) {
        ctx.write_ack(true, (4, 4)).unwrap();
    } else { return }

    loop {
        let m = ctx.recv_msg(true);
        if let Ok(m) = m {match m {
            Message::Login(Login { .. }) => {
                ctx.send_msg(&StartList, true).unwrap();
                ctx.send_msg(&SetDirectory { dirname: Vec::new() }, true).unwrap();
                ctx.send_msg(&InfoFinished, true).unwrap();
                ctx.send_msg(&FileListDone, true).unwrap();
            },
            Message::FileListDone(_) => {
                ctx.send_msg(&SendDone, true).unwrap();
                info!("client {} was updated successfully", peer);
            }
            e => info!("recv something else! {:?}", e)
        }} else {
            return
        }
    }

    info!("disconnecting {}", peer);
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Data Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11001").unwrap();
    info!("Started");
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                thread::spawn(move|| handle_client(ClientContext {
                    stream: s,
                    client_cipher: PcCipher::new(random()),
                    server_cipher: PcCipher::new(random())
                }));
            },
            _ => ()
        };
    };
}
<commit_msg>One last attempt for tonight.<commit_after>//! Runs the data provision server, as a component of the patch server.
extern crate rand;
extern crate crypto;
extern crate psocrypto;
extern crate idola;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate byteorder;

use std::net::TcpListener;
use std::net::TcpStream;
use std::thread;
use std::io;
use std::io::{Cursor, Read, Write};

use crypto::symmetriccipher::{Decryptor, Encryptor};
use crypto::buffer::{RefReadBuffer, RefWriteBuffer};
use psocrypto::PcCipher;

use rand::random;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::*;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

struct ClientContext {
    pub stream: TcpStream,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    fn read_ack(&mut self, enc: bool) -> io::Result<(u16, u16)> {
        let size;
        let ty;
        let mut rbuf = [0u8; 4];
        let mut ebuf = [0u8; 4];
        let mut cur;
        {try!(self.stream.read(&mut rbuf));}
        if enc {
            {
                if let Err(e) = self.client_cipher.decrypt(
                    &mut RefReadBuffer::new(&rbuf[..]),
                    &mut RefWriteBuffer::new(&mut ebuf[..]), false) {
                    return Err(io::Error::new(io::ErrorKind::Other, format!("unable to encrypt: {:?}", e)))
                }
            }
            {
                cur = Cursor::new(&ebuf);
                size = cur.read_u16::<LittleEndian>().unwrap();
                ty = cur.read_u16::<LittleEndian>().unwrap();
            }
        } else {
            cur = Cursor::new(&rbuf);
            size = cur.read_u16::<LittleEndian>().unwrap();
            ty = cur.read_u16::<LittleEndian>().unwrap();
        }
        Ok((size, ty))
    }

    fn write_ack(&mut self, enc: bool, ack: (u16, u16)) -> io::Result<()> {
        let (size, ty) = ack;
        let mut wbuf = [0u8; 4];
        let mut ebuf = [0u8; 4];
        {
            let mut cur = Cursor::new(&mut wbuf[..]);
            try!(cur.write_u16::<LittleEndian>(size));
            try!(cur.write_u16::<LittleEndian>(ty));
        }
        if enc {
            if let Err(e) = self.server_cipher.encrypt(
                &mut RefReadBuffer::new(& wbuf[..]),
                &mut RefWriteBuffer::new(&mut ebuf), false) {
                Err(io::Error::new(
                    io::ErrorKind::Other, format!("unable to encrypt ack message: {:?}", e)))
            } else {
                try!(self.stream.write_all(&ebuf));
                self.stream.flush()
            }
        } else {
            try!(self.stream.write_all(&wbuf));
            self.stream.flush()
        }
    }

    /// Send a message struct.
    fn send_msg(&mut self, msg: &MessageEncode, encrypt: bool) -> io::Result<()> {
        if encrypt {
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum. Will
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

fn handle_client(mut ctx: ClientContext) {
    let peer = ctx.stream.peer_addr().unwrap();

    info!("connected {}", peer);

    let w = Welcome {
        client_vector: ctx.client_cipher.seed(),
        server_vector: ctx.server_cipher.seed()
    };
    ctx.send_msg(&w, false).unwrap();

    if let Ok((4, 2)) = ctx.read_ack(true) {
        ctx.write_ack(true, (4, 4)).unwrap();
    } else { return }

    loop {
        let m = ctx.recv_msg(true);
        if let Ok(m) = m {match m {
            Message::Login(Login { .. }) => {
                ctx.send_msg(&StartList, true).unwrap();
                ctx.send_msg(&SetDirectory { dirname: vec![46] }, true).unwrap();
                ctx.send_msg(&InfoFinished, true).unwrap();
                ctx.send_msg(&FileListDone, true).unwrap();
            },
            Message::FileListDone(_) => {
                ctx.send_msg(&SetDirectory { dirname: vec![46] }, true).unwrap();
                ctx.send_msg(&OneDirUp, true).unwrap();
                ctx.send_msg(&SendDone, true).unwrap();
                info!("client {} was updated successfully", peer);
            }
            e => info!("recv something else! {:?}", e)
        }} else {
            return
        }
    }

    info!("disconnecting {}", peer);
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Data Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11001").unwrap();
    info!("Started");
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                thread::spawn(move|| handle_client(ClientContext {
                    stream: s,
                    client_cipher: PcCipher::new(random()),
                    server_cipher: PcCipher::new(random())
                }));
            },
            _ => ()
        };
    };
}
<|endoftext|>


<commit_before>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{atomic::AtomicBool, Arc, Mutex},
};

use smithay::{
    backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
    reexports::{
        calloop::EventLoop,
        wayland_server::{protocol::wl_output, Display},
    },
    wayland::{
        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
        output::{Mode, Output, PhysicalProperties},
        seat::{CursorImageStatus, Seat, XkbConfig},
        shm::init_shm_global,
    },
};

use slog::Logger;

use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::init_shell;

pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Logger) -> Result<(), ()> {
    let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;

    #[cfg(feature = "egl")]
    let egl_display = Rc::new(RefCell::new(
        if let Ok(egl_display) = renderer.bind_wl_display(&display) {
            info!(log, "EGL hardware-acceleration enabled");
            Some(egl_display)
        } else {
            None
        },
    ));

    let (w, h) = renderer.get_framebuffer_dimensions();
    #[cfg(feature = "egl")]
    let drawer = GliumDrawer::init(renderer, egl_display, log.clone());
    #[cfg(not(feature = "egl"))]
    let drawer = GliumDrawer::init(renderer, log.clone());

    let name = display.add_socket_auto().unwrap().into_string().unwrap();
    info!(log, "Listening on wayland socket"; "name" => name.clone());
    ::std::env::set_var("WAYLAND_DISPLAY", name);

    let running = Arc::new(AtomicBool::new(true));

    /*
     * Initialize the globals
     */

    init_shm_global(display, vec![], log.clone());

    let (compositor_token, _, _, window_map) = init_shell(display, log.clone());

    let dnd_icon = Arc::new(Mutex::new(None));

    let dnd_icon2 = dnd_icon.clone();
    init_data_device(
        display,
        move |event| match event {
            DataDeviceEvent::DnDStarted { icon, .. } => {
                *dnd_icon2.lock().unwrap() = icon;
            }
            DataDeviceEvent::DnDDropped => {
                *dnd_icon2.lock().unwrap() = None;
            }
            _ => {}
        },
        default_action_chooser,
        compositor_token.clone(),
        log.clone(),
    );

    let (mut seat, _) = Seat::new(display, "winit".into(), compositor_token.clone(), log.clone());

    let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));

    let cursor_status2 = cursor_status.clone();
    let pointer = seat.add_pointer(compositor_token.clone(), move |new_status| {
        // TODO: hide winit system cursor when relevant
        *cursor_status2.lock().unwrap() = new_status
    });

    let keyboard = seat
        .add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
            set_data_device_focus(seat, focus.and_then(|s| s.as_ref().client()))
        })
        .expect("Failed to initialize the keyboard");

    let (output, _) = Output::new(
        display,
        "Winit".into(),
        PhysicalProperties {
            width: 0,
            height: 0,
            subpixel: wl_output::Subpixel::Unknown,
            make: "Smithay".into(),
            model: "Winit".into(),
        },
        log.clone(),
    );

    output.change_current_state(
        Some(Mode {
            width: w as i32,
            height: h as i32,
            refresh: 60_000,
        }),
        None,
        None,
    );
    output.set_preferred(Mode {
        width: w as i32,
        height: h as i32,
        refresh: 60_000,
    });

    let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));

    input.set_handler(AnvilInputHandler::new(
        log.clone(),
        pointer,
        keyboard,
        window_map.clone(),
        (0, 0),
        running.clone(),
        pointer_location.clone(),
    ));

    info!(log, "Initialization completed, starting the main loop.");

    loop {
        input.dispatch_new_events().unwrap();

        // drawing logic
        {
            use glium::Surface;
            let mut frame = drawer.draw();
            frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);

            // draw the windows
            drawer.draw_windows(&mut frame, &*window_map.borrow(), compositor_token);

            let (x, y) = *pointer_location.borrow();
            // draw the dnd icon if any
            {
                let guard = dnd_icon.lock().unwrap();
                if let Some(ref surface) = *guard {
                    if surface.as_ref().is_alive() {
                        drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), compositor_token);
                    }
                }
            }
            // draw the cursor as relevant
            {
                let mut guard = cursor_status.lock().unwrap();
                // reset the cursor if the surface is no longer alive
                let mut reset = false;
                if let CursorImageStatus::Image(ref surface) = *guard {
                    reset = !surface.as_ref().is_alive();
                }
                if reset {
                    *guard = CursorImageStatus::Default;
                }
                // draw as relevant
                if let CursorImageStatus::Image(ref surface) = *guard {
                    drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), compositor_token);
                }
            }

            if let Err(err) = frame.finish() {
                error!(log, "Error during rendering: {:?}", err);
            }
        }

        event_loop
            .dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
            .unwrap();
        display.flush_clients();

        window_map.borrow_mut().refresh();
    }
}
<commit_msg>Make winit backend exit on Super-Q<commit_after>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex,
    },
};

use smithay::{
    backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
    reexports::{
        calloop::EventLoop,
        wayland_server::{protocol::wl_output, Display},
    },
    wayland::{
        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
        output::{Mode, Output, PhysicalProperties},
        seat::{CursorImageStatus, Seat, XkbConfig},
        shm::init_shm_global,
    },
};

use slog::Logger;

use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::init_shell;

pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Logger) -> Result<(), ()> {
    let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;

    #[cfg(feature = "egl")]
    let egl_display = Rc::new(RefCell::new(
        if let Ok(egl_display) = renderer.bind_wl_display(&display) {
            info!(log, "EGL hardware-acceleration enabled");
            Some(egl_display)
        } else {
            None
        },
    ));

    let (w, h) = renderer.get_framebuffer_dimensions();
    #[cfg(feature = "egl")]
    let drawer = GliumDrawer::init(renderer, egl_display, log.clone());
    #[cfg(not(feature = "egl"))]
    let drawer = GliumDrawer::init(renderer, log.clone());

    let name = display.add_socket_auto().unwrap().into_string().unwrap();
    info!(log, "Listening on wayland socket"; "name" => name.clone());
    ::std::env::set_var("WAYLAND_DISPLAY", name);

    let running = Arc::new(AtomicBool::new(true));

    /*
     * Initialize the globals
     */

    init_shm_global(display, vec![], log.clone());

    let (compositor_token, _, _, window_map) = init_shell(display, log.clone());

    let dnd_icon = Arc::new(Mutex::new(None));

    let dnd_icon2 = dnd_icon.clone();
    init_data_device(
        display,
        move |event| match event {
            DataDeviceEvent::DnDStarted { icon, .. } => {
                *dnd_icon2.lock().unwrap() = icon;
            }
            DataDeviceEvent::DnDDropped => {
                *dnd_icon2.lock().unwrap() = None;
            }
            _ => {}
        },
        default_action_chooser,
        compositor_token.clone(),
        log.clone(),
    );

    let (mut seat, _) = Seat::new(display, "winit".into(), compositor_token.clone(), log.clone());

    let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));

    let cursor_status2 = cursor_status.clone();
    let pointer = seat.add_pointer(compositor_token.clone(), move |new_status| {
        // TODO: hide winit system cursor when relevant
        *cursor_status2.lock().unwrap() = new_status
    });

    let keyboard = seat
        .add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
            set_data_device_focus(seat, focus.and_then(|s| s.as_ref().client()))
        })
        .expect("Failed to initialize the keyboard");

    let (output, _) = Output::new(
        display,
        "Winit".into(),
        PhysicalProperties {
            width: 0,
            height: 0,
            subpixel: wl_output::Subpixel::Unknown,
            make: "Smithay".into(),
            model: "Winit".into(),
        },
        log.clone(),
    );

    output.change_current_state(
        Some(Mode {
            width: w as i32,
            height: h as i32,
            refresh: 60_000,
        }),
        None,
        None,
    );
    output.set_preferred(Mode {
        width: w as i32,
        height: h as i32,
        refresh: 60_000,
    });

    let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));

    input.set_handler(AnvilInputHandler::new(
        log.clone(),
        pointer,
        keyboard,
        window_map.clone(),
        (0, 0),
        running.clone(),
        pointer_location.clone(),
    ));

    info!(log, "Initialization completed, starting the main loop.");

    while running.load(Ordering::SeqCst) {
        input.dispatch_new_events().unwrap();

        // drawing logic
        {
            use glium::Surface;
            let mut frame = drawer.draw();
            frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);

            // draw the windows
            drawer.draw_windows(&mut frame, &*window_map.borrow(), compositor_token);

            let (x, y) = *pointer_location.borrow();
            // draw the dnd icon if any
            {
                let guard = dnd_icon.lock().unwrap();
                if let Some(ref surface) = *guard {
                    if surface.as_ref().is_alive() {
                        drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), compositor_token);
                    }
                }
            }
            // draw the cursor as relevant
            {
                let mut guard = cursor_status.lock().unwrap();
                // reset the cursor if the surface is no longer alive
                let mut reset = false;
                if let CursorImageStatus::Image(ref surface) = *guard {
                    reset = !surface.as_ref().is_alive();
                }
                if reset {
                    *guard = CursorImageStatus::Default;
                }
                // draw as relevant
                if let CursorImageStatus::Image(ref surface) = *guard {
                    drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), compositor_token);
                }
            }

            if let Err(err) = frame.finish() {
                error!(log, "Error during rendering: {:?}", err);
            }
        }

        if event_loop
            .dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
            .is_err()
        {
            running.store(false, Ordering::SeqCst);
        } else {
            display.flush_clients();
            window_map.borrow_mut().refresh();
        }
    }

    // Cleanup stuff
    window_map.borrow_mut().clear();

    Ok(())
}
<|endoftext|>


<commit_before>use super::helpers::allocations;
use super::helpers::fixtures::{get_language, get_language_queries_path};
use std::ffi::CStr;
use std::ffi::CString;
use std::{fs, ptr, slice, str};
use tree_sitter::Point;
use tree_sitter_tags::c_lib as c;
use tree_sitter_tags::{Error, TagsConfiguration, TagsContext};

const PYTHON_TAG_QUERY: &'static str = r#"
(
  (function_definition
    name: (identifier) @name
    body: (block . (expression_statement (string) @doc))) @definition.function
  (#strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)")
)

(function_definition
  name: (identifier) @name) @definition.function

(
  (class_definition
    name: (identifier) @name
    body: (block
      . (expression_statement (string) @doc))) @definition.class
  (#strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)")
)

(class_definition
  name: (identifier) @name) @definition.class

(call
  function: (identifier) @name) @reference.call

(call
  function: (attribute
    attribute: (identifier) @name)) @reference.call
"#;

const JS_TAG_QUERY: &'static str = r#"
(
    (comment)* @doc .
    (class_declaration
        name: (identifier) @name) @definition.class
    (#select-adjacent! @doc @definition.class)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(
    (comment)* @doc .
    (method_definition
        name: (property_identifier) @name) @definition.method
    (#select-adjacent! @doc @definition.method)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(
    (comment)* @doc .
    (function_declaration
        name: (identifier) @name) @definition.function
    (#select-adjacent! @doc @definition.function)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(call_expression
    function: (identifier) @name) @reference.call
"#;

const RUBY_TAG_QUERY: &'static str = r#"
(method
    name: (_) @name) @definition.method

(method_call
    method: (identifier) @name) @reference.call

(setter (identifier) @ignore)

((identifier) @name @reference.call
 (#is-not? local))
"#;

#[test]
fn test_tags_python() {
    let language = get_language("python");
    let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
    let mut tag_context = TagsContext::new();

    let source = br#"
    class Customer:
        """
        Data about a customer
        """

        def age(self):
            '''
            Get the customer's age
            '''
            compute_age(self.id)
    }
    "#;

    let tags = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source, &t.name_range),
                tags_config.syntax_type_name(t.syntax_type_id)
            ))
            .collect::<Vec<_>>(),
        &[
            ("Customer", "class"),
            ("age", "function"),
            ("compute_age", "call"),
        ]
    );

    assert_eq!(substr(source, &tags[0].line_range), "class Customer:");
    assert_eq!(substr(source, &tags[1].line_range), "def age(self):");
    assert_eq!(tags[0].docs.as_ref().unwrap(), "Data about a customer");
    assert_eq!(tags[1].docs.as_ref().unwrap(), "Get the customer's age");
}

#[test]
fn test_tags_javascript() {
    let language = get_language("javascript");
    let tags_config = TagsConfiguration::new(language, JS_TAG_QUERY, "").unwrap();
    let source = br#"
    // hi

    // Data about a customer.
    // bla bla bla
    class Customer {
        /*
         * Get the customer's age
         */
        getAge() {
        }
    }

    // ok

    class Agent {

    }
    "#;

    let mut tag_context = TagsContext::new();
    let tags = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source, &t.name_range),
                t.span.clone(),
                tags_config.syntax_type_name(t.syntax_type_id)
            ))
            .collect::<Vec<_>>(),
        &[
            ("Customer", Point::new(5, 10)..Point::new(5, 18), "class",),
            ("getAge", Point::new(9, 8)..Point::new(9, 14), "method",),
            ("Agent", Point::new(15, 10)..Point::new(15, 15), "class",)
        ]
    );
    assert_eq!(
        tags[0].docs.as_ref().unwrap(),
        "Data about a customer.\nbla bla bla"
    );
    assert_eq!(tags[1].docs.as_ref().unwrap(), "Get the customer's age");
    assert_eq!(tags[2].docs, None);
}

#[test]
fn test_tags_columns_measured_in_utf16_code_units() {
    let language = get_language("python");
    let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
    let mut tag_context = TagsContext::new();

    let source = r#""❤❤❤".hello_α_ω()"#.as_bytes();

    let tag = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .next()
        .unwrap()
        .unwrap();

    assert_eq!(substr(source, &tag.name_range), "hello_α_ω");
    assert_eq!(tag.span, Point::new(0, 21)..Point::new(0, 32));
    assert_eq!(tag.utf16_column_range, 9..18);
}

#[test]
fn test_tags_ruby() {
    let language = get_language("ruby");
    let locals_query =
        fs::read_to_string(get_language_queries_path("ruby").join("locals.scm")).unwrap();
    let tags_config = TagsConfiguration::new(language, RUBY_TAG_QUERY, &locals_query).unwrap();
    let source = strip_whitespace(
        8,
        "
        b = 1

        def foo=()
            c = 1

            # a is a method because it is not in scope
            # b is a method because `b` doesn't capture variables from its containing scope
            bar a, b, c

            [1, 2, 3].each do |a|
                # a is a parameter
                # b is a method
                # c is a variable, because the block captures variables from its containing scope.
                baz a, b, c
            end
        end",
    );

    let mut tag_context = TagsContext::new();
    let tags = tag_context
        .generate_tags(&tags_config, source.as_bytes(), None)
        .unwrap()
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source.as_bytes(), &t.name_range),
                tags_config.syntax_type_name(t.syntax_type_id),
                (t.span.start.row, t.span.start.column),
            ))
            .collect::<Vec<_>>(),
        &[
            ("foo=", "method", (2, 4)),
            ("bar", "call", (7, 4)),
            ("a", "call", (7, 8)),
            ("b", "call", (7, 11)),
            ("each", "call", (9, 14)),
            ("baz", "call", (13, 8)),
            ("b", "call", (13, 15),),
        ]
    );
}

#[test]
fn test_tags_cancellation() {
    use std::sync::atomic::{AtomicUsize, Ordering};

    allocations::record(|| {
        // Large javascript document
        let source = (0..500)
            .map(|_| "/* hi */ class A { /* ok */ b() {} }\n")
            .collect::<String>();

        let cancellation_flag = AtomicUsize::new(0);
        let language = get_language("javascript");
        let tags_config = TagsConfiguration::new(language, JS_TAG_QUERY, "").unwrap();

        let mut tag_context = TagsContext::new();
        let tags = tag_context
            .generate_tags(&tags_config, source.as_bytes(), Some(&cancellation_flag))
            .unwrap();

        for (i, tag) in tags.enumerate() {
            if i == 150 {
                cancellation_flag.store(1, Ordering::SeqCst);
            }
            if let Err(e) = tag {
                assert_eq!(e, Error::Cancelled);
                return;
            }
        }

        panic!("Expected to halt tagging with an error");
    });
}

#[test]
fn test_invalid_capture() {
    let language = get_language("python");
    let e = TagsConfiguration::new(language, "(identifier) @method", "")
        .expect_err("expected InvalidCapture error");
    assert_eq!(e, Error::InvalidCapture("method".to_string()));
}

#[test]
fn test_tags_via_c_api() {
    allocations::record(|| {
        let tagger = c::ts_tagger_new();
        let buffer = c::ts_tags_buffer_new();
        let scope_name = "source.js";
        let language = get_language("javascript");

        let source_code = strip_whitespace(
            12,
            "
            var a = 1;

            // one
            // two
            // three
            function b() {
            }

            // four
            // five
            class C extends D {

            }

            b(a);",
        );

        let c_scope_name = CString::new(scope_name).unwrap();
        let result = c::ts_tagger_add_language(
            tagger,
            c_scope_name.as_ptr(),
            language,
            JS_TAG_QUERY.as_ptr(),
            ptr::null(),
            JS_TAG_QUERY.len() as u32,
            0,
        );
        assert_eq!(result, c::TSTagsError::Ok);

        let result = c::ts_tagger_tag(
            tagger,
            c_scope_name.as_ptr(),
            source_code.as_ptr(),
            source_code.len() as u32,
            buffer,
            ptr::null(),
        );
        assert_eq!(result, c::TSTagsError::Ok);
        let tags = unsafe {
            slice::from_raw_parts(
                c::ts_tags_buffer_tags(buffer),
                c::ts_tags_buffer_tags_len(buffer) as usize,
            )
        };
        let docs = str::from_utf8(unsafe {
            slice::from_raw_parts(
                c::ts_tags_buffer_docs(buffer) as *const u8,
                c::ts_tags_buffer_docs_len(buffer) as usize,
            )
        })
        .unwrap();

        let syntax_types: Vec<&str> = unsafe {
            let mut len: u32 = 0;
            let ptr =
                c::ts_tagger_syntax_kinds_for_scope_name(tagger, c_scope_name.as_ptr(), &mut len);
            slice::from_raw_parts(ptr, len as usize)
                .iter()
                .map(|i| CStr::from_ptr(*i).to_str().unwrap())
                .collect()
        };

        assert_eq!(
            tags.iter()
                .map(|tag| (
                    syntax_types[tag.syntax_type_id as usize],
                    &source_code[tag.name_start_byte as usize..tag.name_end_byte as usize],
                    &source_code[tag.line_start_byte as usize..tag.line_end_byte as usize],
                    &docs[tag.docs_start_byte as usize..tag.docs_end_byte as usize],
                ))
                .collect::<Vec<_>>(),
            &[
                ("function", "b", "function b() {", "one\ntwo\nthree"),
                ("class", "C", "class C extends D {", "four\nfive"),
                ("call", "b", "b(a);", "")
            ]
        );

        c::ts_tags_buffer_delete(buffer);
        c::ts_tagger_delete(tagger);
    });
}

fn substr<'a>(source: &'a [u8], range: &std::ops::Range<usize>) -> &'a str {
    std::str::from_utf8(&source[range.clone()]).unwrap()
}

fn strip_whitespace(indent: usize, s: &str) -> String {
    s.lines()
        .skip(1)
        .map(|line| &line[line.len().min(indent)..])
        .collect::<Vec<_>>()
        .join("\n")
}
<commit_msg>Fix the tests<commit_after>use super::helpers::allocations;
use super::helpers::fixtures::{get_language, get_language_queries_path};
use std::ffi::CStr;
use std::ffi::CString;
use std::{fs, ptr, slice, str};
use tree_sitter::Point;
use tree_sitter_tags::c_lib as c;
use tree_sitter_tags::{Error, TagsConfiguration, TagsContext};

const PYTHON_TAG_QUERY: &'static str = r#"
(
  (function_definition
    name: (identifier) @name
    body: (block . (expression_statement (string) @doc))) @definition.function
  (#strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)")
)

(function_definition
  name: (identifier) @name) @definition.function

(
  (class_definition
    name: (identifier) @name
    body: (block
      . (expression_statement (string) @doc))) @definition.class
  (#strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)")
)

(class_definition
  name: (identifier) @name) @definition.class

(call
  function: (identifier) @name) @reference.call

(call
  function: (attribute
    attribute: (identifier) @name)) @reference.call
"#;

const JS_TAG_QUERY: &'static str = r#"
(
    (comment)* @doc .
    (class_declaration
        name: (identifier) @name) @definition.class
    (#select-adjacent! @doc @definition.class)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(
    (comment)* @doc .
    (method_definition
        name: (property_identifier) @name) @definition.method
    (#select-adjacent! @doc @definition.method)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(
    (comment)* @doc .
    (function_declaration
        name: (identifier) @name) @definition.function
    (#select-adjacent! @doc @definition.function)
    (#strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)")
)

(call_expression
    function: (identifier) @name) @reference.call
"#;

const RUBY_TAG_QUERY: &'static str = r#"
(method
    name: (_) @name) @definition.method

(method_call
    method: (identifier) @name) @reference.call

(setter (identifier) @ignore)

((identifier) @name @reference.call
 (#is-not? local))
"#;

#[test]
fn test_tags_python() {
    let language = get_language("python");
    let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
    let mut tag_context = TagsContext::new();

    let source = br#"
    class Customer:
        """
        Data about a customer
        """

        def age(self):
            '''
            Get the customer's age
            '''
            compute_age(self.id)
    }
    "#;

    let tags = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .0
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source, &t.name_range),
                tags_config.syntax_type_name(t.syntax_type_id)
            ))
            .collect::<Vec<_>>(),
        &[
            ("Customer", "class"),
            ("age", "function"),
            ("compute_age", "call"),
        ]
    );

    assert_eq!(substr(source, &tags[0].line_range), "class Customer:");
    assert_eq!(substr(source, &tags[1].line_range), "def age(self):");
    assert_eq!(tags[0].docs.as_ref().unwrap(), "Data about a customer");
    assert_eq!(tags[1].docs.as_ref().unwrap(), "Get the customer's age");
}

#[test]
fn test_tags_javascript() {
    let language = get_language("javascript");
    let tags_config = TagsConfiguration::new(language, JS_TAG_QUERY, "").unwrap();
    let source = br#"
    // hi

    // Data about a customer.
    // bla bla bla
    class Customer {
        /*
         * Get the customer's age
         */
        getAge() {
        }
    }

    // ok

    class Agent {

    }
    "#;

    let mut tag_context = TagsContext::new();
    let tags = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .0
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source, &t.name_range),
                t.span.clone(),
                tags_config.syntax_type_name(t.syntax_type_id)
            ))
            .collect::<Vec<_>>(),
        &[
            ("Customer", Point::new(5, 10)..Point::new(5, 18), "class",),
            ("getAge", Point::new(9, 8)..Point::new(9, 14), "method",),
            ("Agent", Point::new(15, 10)..Point::new(15, 15), "class",)
        ]
    );
    assert_eq!(
        tags[0].docs.as_ref().unwrap(),
        "Data about a customer.\nbla bla bla"
    );
    assert_eq!(tags[1].docs.as_ref().unwrap(), "Get the customer's age");
    assert_eq!(tags[2].docs, None);
}

#[test]
fn test_tags_columns_measured_in_utf16_code_units() {
    let language = get_language("python");
    let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
    let mut tag_context = TagsContext::new();

    let source = r#""❤❤❤".hello_α_ω()"#.as_bytes();

    let tag = tag_context
        .generate_tags(&tags_config, source, None)
        .unwrap()
        .0
        .next()
        .unwrap()
        .unwrap();

    assert_eq!(substr(source, &tag.name_range), "hello_α_ω");
    assert_eq!(tag.span, Point::new(0, 21)..Point::new(0, 32));
    assert_eq!(tag.utf16_column_range, 9..18);
}

#[test]
fn test_tags_ruby() {
    let language = get_language("ruby");
    let locals_query =
        fs::read_to_string(get_language_queries_path("ruby").join("locals.scm")).unwrap();
    let tags_config = TagsConfiguration::new(language, RUBY_TAG_QUERY, &locals_query).unwrap();
    let source = strip_whitespace(
        8,
        "
        b = 1

        def foo=()
            c = 1

            # a is a method because it is not in scope
            # b is a method because `b` doesn't capture variables from its containing scope
            bar a, b, c

            [1, 2, 3].each do |a|
                # a is a parameter
                # b is a method
                # c is a variable, because the block captures variables from its containing scope.
                baz a, b, c
            end
        end",
    );

    let mut tag_context = TagsContext::new();
    let tags = tag_context
        .generate_tags(&tags_config, source.as_bytes(), None)
        .unwrap()
        .0
        .collect::<Result<Vec<_>, _>>()
        .unwrap();

    assert_eq!(
        tags.iter()
            .map(|t| (
                substr(source.as_bytes(), &t.name_range),
                tags_config.syntax_type_name(t.syntax_type_id),
                (t.span.start.row, t.span.start.column),
            ))
            .collect::<Vec<_>>(),
        &[
            ("foo=", "method", (2, 4)),
            ("bar", "call", (7, 4)),
            ("a", "call", (7, 8)),
            ("b", "call", (7, 11)),
            ("each", "call", (9, 14)),
            ("baz", "call", (13, 8)),
            ("b", "call", (13, 15),),
        ]
    );
}

#[test]
fn test_tags_cancellation() {
    use std::sync::atomic::{AtomicUsize, Ordering};

    allocations::record(|| {
        // Large javascript document
        let source = (0..500)
            .map(|_| "/* hi */ class A { /* ok */ b() {} }\n")
            .collect::<String>();

        let cancellation_flag = AtomicUsize::new(0);
        let language = get_language("javascript");
        let tags_config = TagsConfiguration::new(language, JS_TAG_QUERY, "").unwrap();

        let mut tag_context = TagsContext::new();
        let tags = tag_context
            .generate_tags(&tags_config, source.as_bytes(), Some(&cancellation_flag))
            .unwrap();

        for (i, tag) in tags.0.enumerate() {
            if i == 150 {
                cancellation_flag.store(1, Ordering::SeqCst);
            }
            if let Err(e) = tag {
                assert_eq!(e, Error::Cancelled);
                return;
            }
        }

        panic!("Expected to halt tagging with an error");
    });
}

#[test]
fn test_invalid_capture() {
    let language = get_language("python");
    let e = TagsConfiguration::new(language, "(identifier) @method", "")
        .expect_err("expected InvalidCapture error");
    assert_eq!(e, Error::InvalidCapture("method".to_string()));
}

#[test]
fn test_tags_via_c_api() {
    allocations::record(|| {
        let tagger = c::ts_tagger_new();
        let buffer = c::ts_tags_buffer_new();
        let scope_name = "source.js";
        let language = get_language("javascript");

        let source_code = strip_whitespace(
            12,
            "
            var a = 1;

            // one
            // two
            // three
            function b() {
            }

            // four
            // five
            class C extends D {

            }

            b(a);",
        );

        let c_scope_name = CString::new(scope_name).unwrap();
        let result = c::ts_tagger_add_language(
            tagger,
            c_scope_name.as_ptr(),
            language,
            JS_TAG_QUERY.as_ptr(),
            ptr::null(),
            JS_TAG_QUERY.len() as u32,
            0,
        );
        assert_eq!(result, c::TSTagsError::Ok);

        let result = c::ts_tagger_tag(
            tagger,
            c_scope_name.as_ptr(),
            source_code.as_ptr(),
            source_code.len() as u32,
            buffer,
            ptr::null(),
        );
        assert_eq!(result, c::TSTagsError::Ok);
        let tags = unsafe {
            slice::from_raw_parts(
                c::ts_tags_buffer_tags(buffer),
                c::ts_tags_buffer_tags_len(buffer) as usize,
            )
        };
        let docs = str::from_utf8(unsafe {
            slice::from_raw_parts(
                c::ts_tags_buffer_docs(buffer) as *const u8,
                c::ts_tags_buffer_docs_len(buffer) as usize,
            )
        })
        .unwrap();

        let syntax_types: Vec<&str> = unsafe {
            let mut len: u32 = 0;
            let ptr =
                c::ts_tagger_syntax_kinds_for_scope_name(tagger, c_scope_name.as_ptr(), &mut len);
            slice::from_raw_parts(ptr, len as usize)
                .iter()
                .map(|i| CStr::from_ptr(*i).to_str().unwrap())
                .collect()
        };

        assert_eq!(
            tags.iter()
                .map(|tag| (
                    syntax_types[tag.syntax_type_id as usize],
                    &source_code[tag.name_start_byte as usize..tag.name_end_byte as usize],
                    &source_code[tag.line_start_byte as usize..tag.line_end_byte as usize],
                    &docs[tag.docs_start_byte as usize..tag.docs_end_byte as usize],
                ))
                .collect::<Vec<_>>(),
            &[
                ("function", "b", "function b() {", "one\ntwo\nthree"),
                ("class", "C", "class C extends D {", "four\nfive"),
                ("call", "b", "b(a);", "")
            ]
        );

        c::ts_tags_buffer_delete(buffer);
        c::ts_tagger_delete(tagger);
    });
}

fn substr<'a>(source: &'a [u8], range: &std::ops::Range<usize>) -> &'a str {
    std::str::from_utf8(&source[range.clone()]).unwrap()
}

fn strip_whitespace(indent: usize, s: &str) -> String {
    s.lines()
        .skip(1)
        .map(|line| &line[line.len().min(indent)..])
        .collect::<Vec<_>>()
        .join("\n")
}
<|endoftext|>


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

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement
/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/first-edition/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}
<commit_msg>Rollup merge of #46518 - partim:asref-borrow-doc, r=dtolnay<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

/// A trait for borrowing data.
///
/// In Rust, it is common to provide different representations of a type for
/// different use cases. For instance, storage location and management for a
/// value can be specifically chosen as appropriate for a particular use via
/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic
/// wrappers that can be used with any type, some types provide optional
/// facets providing potentially costly functionality. An example for such a
/// type is [`String`] which adds the ability to extend a string to the basic
/// [`str`]. This requires keeping additional information unnecessary for a
/// simple, immutable string.
///
/// These types provide access to the underlying data through references
/// to the type of that data. They are said to be ‘borrowed as’ that type.
/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`]
/// can be borrowed as `str`.
///
/// Types express that they can be borrowed as some type `T` by implementing
/// `Borrow<T>`, providing a reference to a `T` in the trait’s
/// [`borrow`] method. A type is free to borrow as several different types.
/// If it wishes to mutably borrow as the type – allowing the underlying data
/// to be modified, it can additionally implement [`BorrowMut<T>`].
///
/// Further, when providing implementations for additional traits, it needs
/// to be considered whether they should behave identical to those of the
/// underlying type as a consequence of acting as a representation of that
/// underlying type. Generic code typically uses `Borrow<T>` when it relies
/// on the identical behavior of these additional trait implementations.
/// These traits will likely appear as additional trait bounds.
///
/// If generic code merely needs to work for all types that can
/// provide a reference to related type `T`, it is often better to use
/// [`AsRef<T>`] as more types can safely implement it.
///
/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html
/// [`BorrowMut<T>`]: trait.BorrowMut.html
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
/// [`str`]: ../../std/primitive.str.html
/// [`String`]: ../../std/string/struct.String.html
/// [`borrow`]: #tymethod.borrow
///
/// # Examples
///
/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If
/// the key’s actual data is wrapped in a managing type of some kind, it
/// should, however, still be possible to search for a value using a
/// reference to the key’s data. For instance, if the key is a string, then
/// it is likely stored with the hash map as a [`String`], while it should
/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to
/// operate on a `String` while `get` needs to be able to use a `&str`.
///
/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like
/// this:
///
/// ```
/// use std::borrow::Borrow;
/// use std::hash::Hash;
///
/// pub struct HashMap<K, V> {
///     # marker: ::std::marker::PhantomData<(K, V)>,
///     // fields omitted
/// }
///
/// impl<K, V> HashMap<K, V> {
///     pub fn insert(&self, key: K, value: V) -> Option<V>
///     where K: Hash + Eq
///     {
///         # unimplemented!()
///         // ...
///     }
///
///     pub fn get<Q>(&self, k: &Q) -> Option<&V>
///     where
///         K: Borrow<Q>,
///         Q: Hash + Eq + ?Sized
///     {
///         # unimplemented!()
///         // ...
///     }
/// }
/// ```
///
/// The entire hash map is generic over a key type `K`. Because these keys
/// are stored with the hash map, this type has to own the key’s data.
/// When inserting a key-value pair, the map is given such a `K` and needs
/// to find the correct hash bucket and check if the key is already present
/// based on that `K`. It therefore requires `K: Hash + Eq`.
///
/// When searching for a value in the map, however, having to provide a
/// reference to a `K` as the key to search for would require to always
/// create such an owned value. For string keys, this would mean a `String`
/// value needs to be created just for the search for cases where only a
/// `str` is available.
///
/// Instead, the `get` method is generic over the type of the underlying key
/// data, called `Q` in the method signature above. It states that `K`
/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally
/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q`
/// have implementations of the `Hash` and `Eq` traits that produce identical
/// results.
///
/// The implementation of `get` relies in particular on identical
/// implementations of `Hash` by determining the key’s hash bucket by calling
/// `Hash::hash` on the `Q` value even though it inserted the key based on
/// the hash value calculated from the `K` value.
///
/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value
/// produces a different hash than `Q`. For instance, imagine you have a
/// type that wraps a string but compares ASCII letters ignoring their case:
///
/// ```
/// pub struct CaseInsensitiveString(String);
///
/// impl PartialEq for CaseInsensitiveString {
///     fn eq(&self, other: &Self) -> bool {
///         self.0.eq_ignore_ascii_case(&other.0)
///     }
/// }
///
/// impl Eq for CaseInsensitiveString { }
/// ```
///
/// Because two equal values need to produce the same hash value, the
/// implementation of `Hash` needs to ignore ASCII case, too:
///
/// ```
/// # use std::hash::{Hash, Hasher};
/// # pub struct CaseInsensitiveString(String);
/// impl Hash for CaseInsensitiveString {
///     fn hash<H: Hasher>(&self, state: &mut H) {
///         for c in self.0.as_bytes() {
///             c.to_ascii_lowercase().hash(state)
///         }
///     }
/// }
/// ```
///
/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can
/// provide a reference to a string slice via its contained owned string.
/// But because its `Hash` implementation differs, it behaves differently
/// from `str` and therefore must not, in fact, implement `Borrow<str>`.
/// If it wants to allow others access to the underlying `str`, it can do
/// that via `AsRef<str>` which doesn’t carry any extra requirements.
///
/// [`Hash`]: ../../std/hash/trait.Hash.html
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
/// [`String`]: ../../std/string/struct.String.html
/// [`str`]: ../../std/primitive.str.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
/// for more information on borrowing as another type.
///
/// [`Borrow<T>`]: trait.Borrow.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}
<|endoftext|>


<commit_before>use crate::libyaml::cstr::{self, CStr};
use crate::libyaml::error::{Error, Mark, Result};
use crate::libyaml::tag::Tag;
use crate::libyaml::util::Owned;
use std::borrow::Cow;
use std::fmt::{self, Debug};
use std::mem::MaybeUninit;
use std::ptr::{addr_of_mut, NonNull};
use std::slice;
use unsafe_libyaml as sys;

pub(crate) struct Parser<'input> {
    pin: Owned<ParserPinned<'input>>,
}

struct ParserPinned<'input> {
    sys: sys::yaml_parser_t,
    input: Cow<'input, [u8]>,
}

#[derive(Debug)]
pub(crate) enum Event {
    StreamStart,
    StreamEnd,
    DocumentStart,
    DocumentEnd,
    Alias(Anchor),
    Scalar(Scalar),
    SequenceStart(SequenceStart),
    SequenceEnd,
    MappingStart(MappingStart),
    MappingEnd,
}

#[derive(Debug)]
pub(crate) struct Scalar {
    pub anchor: Option<Anchor>,
    pub tag: Option<Tag>,
    pub value: Box<[u8]>,
    pub style: ScalarStyle,
}

#[derive(Debug)]
pub(crate) struct SequenceStart {
    pub anchor: Option<Anchor>,
}

#[derive(Debug)]
pub(crate) struct MappingStart {
    pub anchor: Option<Anchor>,
}

#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Anchor(Box<[u8]>);

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(crate) enum ScalarStyle {
    Plain,
    SingleQuoted,
    DoubleQuoted,
    Literal,
    Folded,
}

impl<'input> Parser<'input> {
    pub fn new(input: Cow<'input, [u8]>) -> Parser<'input> {
        let owned = Owned::<ParserPinned>::new_uninit();
        let pin = unsafe {
            let parser = addr_of_mut!((*owned.ptr).sys);
            if sys::yaml_parser_initialize(parser) == 0 {
                panic!("malloc error: {}", Error::parse_error(parser));
            }
            sys::yaml_parser_set_encoding(parser, sys::YAML_UTF8_ENCODING);
            sys::yaml_parser_set_input_string(parser, input.as_ptr(), input.len() as u64);
            addr_of_mut!((*owned.ptr).input).write(input);
            Owned::assume_init(owned)
        };
        Parser { pin }
    }

    pub fn next(&mut self) -> Result<(Event, Mark)> {
        let mut event = MaybeUninit::<sys::yaml_event_t>::uninit();
        unsafe {
            let parser = addr_of_mut!((*self.pin.ptr).sys);
            let event = event.as_mut_ptr();
            if sys::yaml_parser_parse(parser, event) == 0 {
                return Err(Error::parse_error(parser));
            }
            let ret = convert_event(&*event);
            let mark = Mark {
                sys: (*event).start_mark,
            };
            sys::yaml_event_delete(event);
            Ok((ret, mark))
        }
    }
}

unsafe fn convert_event(sys: &sys::yaml_event_t) -> Event {
    match sys.type_ {
        sys::YAML_STREAM_START_EVENT => Event::StreamStart,
        sys::YAML_STREAM_END_EVENT => Event::StreamEnd,
        sys::YAML_DOCUMENT_START_EVENT => Event::DocumentStart,
        sys::YAML_DOCUMENT_END_EVENT => Event::DocumentEnd,
        sys::YAML_ALIAS_EVENT => Event::Alias(optional_anchor(sys.data.alias.anchor).unwrap()),
        sys::YAML_SCALAR_EVENT => Event::Scalar(Scalar {
            anchor: optional_anchor(sys.data.scalar.anchor),
            tag: optional_tag(sys.data.scalar.tag),
            value: Box::from(slice::from_raw_parts(
                sys.data.scalar.value,
                sys.data.scalar.length as usize,
            )),
            style: match sys.data.scalar.style {
                sys::YAML_PLAIN_SCALAR_STYLE => ScalarStyle::Plain,
                sys::YAML_SINGLE_QUOTED_SCALAR_STYLE => ScalarStyle::SingleQuoted,
                sys::YAML_DOUBLE_QUOTED_SCALAR_STYLE => ScalarStyle::DoubleQuoted,
                sys::YAML_LITERAL_SCALAR_STYLE => ScalarStyle::Literal,
                sys::YAML_FOLDED_SCALAR_STYLE => ScalarStyle::Folded,
                sys::YAML_ANY_SCALAR_STYLE | _ => unreachable!(),
            },
        }),
        sys::YAML_SEQUENCE_START_EVENT => Event::SequenceStart(SequenceStart {
            anchor: optional_anchor(sys.data.sequence_start.anchor),
        }),
        sys::YAML_SEQUENCE_END_EVENT => Event::SequenceEnd,
        sys::YAML_MAPPING_START_EVENT => Event::MappingStart(MappingStart {
            anchor: optional_anchor(sys.data.mapping_start.anchor),
        }),
        sys::YAML_MAPPING_END_EVENT => Event::MappingEnd,
        sys::YAML_NO_EVENT => unreachable!(),
        _ => unimplemented!(),
    }
}

unsafe fn optional_anchor(anchor: *const u8) -> Option<Anchor> {
    let ptr = NonNull::new(anchor as *mut i8)?;
    let cstr = CStr::from_ptr(ptr);
    Some(Anchor(Box::from(cstr.to_bytes())))
}

unsafe fn optional_tag(tag: *const u8) -> Option<Tag> {
    let ptr = NonNull::new(tag as *mut i8)?;
    let cstr = CStr::from_ptr(ptr);
    Some(Tag(Box::from(cstr.to_bytes())))
}

impl Debug for Anchor {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        cstr::debug_lossy(&self.0, formatter)
    }
}

impl<'input> Drop for ParserPinned<'input> {
    fn drop(&mut self) {
        unsafe { sys::yaml_parser_delete(&mut self.sys) }
    }
}
<commit_msg>Handwrite a better Debug for Scalar<commit_after>use crate::libyaml::cstr::{self, CStr};
use crate::libyaml::error::{Error, Mark, Result};
use crate::libyaml::tag::Tag;
use crate::libyaml::util::Owned;
use std::borrow::Cow;
use std::fmt::{self, Debug};
use std::mem::MaybeUninit;
use std::ptr::{addr_of_mut, NonNull};
use std::slice;
use unsafe_libyaml as sys;

pub(crate) struct Parser<'input> {
    pin: Owned<ParserPinned<'input>>,
}

struct ParserPinned<'input> {
    sys: sys::yaml_parser_t,
    input: Cow<'input, [u8]>,
}

#[derive(Debug)]
pub(crate) enum Event {
    StreamStart,
    StreamEnd,
    DocumentStart,
    DocumentEnd,
    Alias(Anchor),
    Scalar(Scalar),
    SequenceStart(SequenceStart),
    SequenceEnd,
    MappingStart(MappingStart),
    MappingEnd,
}

pub(crate) struct Scalar {
    pub anchor: Option<Anchor>,
    pub tag: Option<Tag>,
    pub value: Box<[u8]>,
    pub style: ScalarStyle,
}

#[derive(Debug)]
pub(crate) struct SequenceStart {
    pub anchor: Option<Anchor>,
}

#[derive(Debug)]
pub(crate) struct MappingStart {
    pub anchor: Option<Anchor>,
}

#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Anchor(Box<[u8]>);

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(crate) enum ScalarStyle {
    Plain,
    SingleQuoted,
    DoubleQuoted,
    Literal,
    Folded,
}

impl<'input> Parser<'input> {
    pub fn new(input: Cow<'input, [u8]>) -> Parser<'input> {
        let owned = Owned::<ParserPinned>::new_uninit();
        let pin = unsafe {
            let parser = addr_of_mut!((*owned.ptr).sys);
            if sys::yaml_parser_initialize(parser) == 0 {
                panic!("malloc error: {}", Error::parse_error(parser));
            }
            sys::yaml_parser_set_encoding(parser, sys::YAML_UTF8_ENCODING);
            sys::yaml_parser_set_input_string(parser, input.as_ptr(), input.len() as u64);
            addr_of_mut!((*owned.ptr).input).write(input);
            Owned::assume_init(owned)
        };
        Parser { pin }
    }

    pub fn next(&mut self) -> Result<(Event, Mark)> {
        let mut event = MaybeUninit::<sys::yaml_event_t>::uninit();
        unsafe {
            let parser = addr_of_mut!((*self.pin.ptr).sys);
            let event = event.as_mut_ptr();
            if sys::yaml_parser_parse(parser, event) == 0 {
                return Err(Error::parse_error(parser));
            }
            let ret = convert_event(&*event);
            let mark = Mark {
                sys: (*event).start_mark,
            };
            sys::yaml_event_delete(event);
            Ok((ret, mark))
        }
    }
}

unsafe fn convert_event(sys: &sys::yaml_event_t) -> Event {
    match sys.type_ {
        sys::YAML_STREAM_START_EVENT => Event::StreamStart,
        sys::YAML_STREAM_END_EVENT => Event::StreamEnd,
        sys::YAML_DOCUMENT_START_EVENT => Event::DocumentStart,
        sys::YAML_DOCUMENT_END_EVENT => Event::DocumentEnd,
        sys::YAML_ALIAS_EVENT => Event::Alias(optional_anchor(sys.data.alias.anchor).unwrap()),
        sys::YAML_SCALAR_EVENT => Event::Scalar(Scalar {
            anchor: optional_anchor(sys.data.scalar.anchor),
            tag: optional_tag(sys.data.scalar.tag),
            value: Box::from(slice::from_raw_parts(
                sys.data.scalar.value,
                sys.data.scalar.length as usize,
            )),
            style: match sys.data.scalar.style {
                sys::YAML_PLAIN_SCALAR_STYLE => ScalarStyle::Plain,
                sys::YAML_SINGLE_QUOTED_SCALAR_STYLE => ScalarStyle::SingleQuoted,
                sys::YAML_DOUBLE_QUOTED_SCALAR_STYLE => ScalarStyle::DoubleQuoted,
                sys::YAML_LITERAL_SCALAR_STYLE => ScalarStyle::Literal,
                sys::YAML_FOLDED_SCALAR_STYLE => ScalarStyle::Folded,
                sys::YAML_ANY_SCALAR_STYLE | _ => unreachable!(),
            },
        }),
        sys::YAML_SEQUENCE_START_EVENT => Event::SequenceStart(SequenceStart {
            anchor: optional_anchor(sys.data.sequence_start.anchor),
        }),
        sys::YAML_SEQUENCE_END_EVENT => Event::SequenceEnd,
        sys::YAML_MAPPING_START_EVENT => Event::MappingStart(MappingStart {
            anchor: optional_anchor(sys.data.mapping_start.anchor),
        }),
        sys::YAML_MAPPING_END_EVENT => Event::MappingEnd,
        sys::YAML_NO_EVENT => unreachable!(),
        _ => unimplemented!(),
    }
}

unsafe fn optional_anchor(anchor: *const u8) -> Option<Anchor> {
    let ptr = NonNull::new(anchor as *mut i8)?;
    let cstr = CStr::from_ptr(ptr);
    Some(Anchor(Box::from(cstr.to_bytes())))
}

unsafe fn optional_tag(tag: *const u8) -> Option<Tag> {
    let ptr = NonNull::new(tag as *mut i8)?;
    let cstr = CStr::from_ptr(ptr);
    Some(Tag(Box::from(cstr.to_bytes())))
}

impl Debug for Scalar {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let Scalar {
            anchor,
            tag,
            value,
            style,
        } = self;

        struct LossySlice<'a>(&'a [u8]);

        impl<'a> Debug for LossySlice<'a> {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                cstr::debug_lossy(self.0, formatter)
            }
        }

        formatter
            .debug_struct("Scalar")
            .field("anchor", anchor)
            .field("tag", tag)
            .field("value", &LossySlice(value))
            .field("style", style)
            .finish()
    }
}

impl Debug for Anchor {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        cstr::debug_lossy(&self.0, formatter)
    }
}

impl<'input> Drop for ParserPinned<'input> {
    fn drop(&mut self) {
        unsafe { sys::yaml_parser_delete(&mut self.sys) }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Utilities to check the status of all the outputs we have stored in
//! the wallet storage and update them.

use std::collections::hash_map::Entry;
use std::collections::HashMap;

use api;
use types::*;
use keychain::{Identifier, Keychain};
use util::secp::pedersen;
use util;
use util::LOGGER;

// Transitions a local wallet output from Unconfirmed -> Unspent.
// Also updates the height and lock_height based on latest from the api.
fn refresh_output(out: &mut OutputData, api_out: &api::Output) {
	out.height = api_out.height;
	out.lock_height = api_out.lock_height;

	match out.status {
		OutputStatus::Unconfirmed => {
			out.status = OutputStatus::Unspent;
		}
		_ => (),
	}
}

// Transitions a local wallet output (based on it not being in the node utxo
// set) -
// Unspent -> Spent
// Locked -> Spent
fn mark_spent_output(out: &mut OutputData) {
	match out.status {
		OutputStatus::Unspent | OutputStatus::Locked => out.status = OutputStatus::Spent,
		_ => (),
	}
}

/// Builds a single api query to retrieve the latest output data from the node.
/// So we can refresh the local wallet outputs.
pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), Error> {
	debug!(LOGGER, "Refreshing wallet outputs");
	let mut wallet_outputs: HashMap<pedersen::Commitment, Identifier> = HashMap::new();
	let mut commits: Vec<pedersen::Commitment> = vec![];

	// build a local map of wallet outputs by commits
	// and a list of outputs we want to query the node for
	let _ = WalletData::read_wallet(&config.data_file_dir, |wallet_data| {
		for out in wallet_data
			.outputs
			.values()
			.filter(|out| out.root_key_id == keychain.root_key_id())
			.filter(|out| out.status != OutputStatus::Spent)
		{
			let commit = keychain.commit_with_key_index(out.value, out.n_child).unwrap();
			commits.push(commit);
			wallet_outputs.insert(commit, out.key_id.clone());
		}
	});

	// build the necessary query params -
 // ?id=xxx&id=yyy&id=zzz
	let query_params: Vec<String> = commits
		.iter()
		.map(|commit| {
			let id = util::to_hex(commit.as_ref().to_vec());
			format!("id={}", id)
		})
		.collect();
	let query_string = query_params.join("&");

	let url = format!(
		"{}/v1/chain/utxos/byids?{}",
		config.check_node_api_http_addr,
		query_string,
	);

	// build a map of api outputs by commit so we can look them up efficiently
	let mut api_outputs: HashMap<pedersen::Commitment, api::Output> = HashMap::new();
	match api::client::get::<Vec<api::Output>>(url.as_str()) {
		Ok(outputs) => for out in outputs {
			api_outputs.insert(out.commit, out);
		},
		Err(e) => {
			// if we got anything other than 200 back from server, don't attempt to refresh the wallet
			// data after
			return Err(Error::Node(e));
		}
	};

	// now for each commit, find the output in the wallet and
 // the corresponding api output (if it exists)
 // and refresh it in-place in the wallet.
 // Note: minimizing the time we spend holding the wallet lock.
	WalletData::with_wallet(&config.data_file_dir, |wallet_data| for commit in commits {
		let id = wallet_outputs.get(&commit).unwrap();
		if let Entry::Occupied(mut output) = wallet_data.outputs.entry(id.to_hex()) {
			match api_outputs.get(&commit) {
				Some(api_output) => refresh_output(&mut output.get_mut(), api_output),
				None => mark_spent_output(&mut output.get_mut()),
			};
		}
	})
}

pub fn get_tip_from_node(config: &WalletConfig) -> Result<api::Tip, Error> {
	let url = format!("{}/v1/chain", config.check_node_api_http_addr);
	api::client::get::<api::Tip>(url.as_str()).map_err(|e| Error::Node(e))
}
<commit_msg>Fix #321 Limit length of API utxo queries (#579)<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Utilities to check the status of all the outputs we have stored in
//! the wallet storage and update them.

use std::collections::hash_map::Entry;
use std::collections::HashMap;

use api;
use types::*;
use keychain::{Identifier, Keychain};
use util::secp::pedersen;
use util;
use util::LOGGER;

// Transitions a local wallet output from Unconfirmed -> Unspent.
// Also updates the height and lock_height based on latest from the api.
fn refresh_output(out: &mut OutputData, api_out: &api::Output) {
	out.height = api_out.height;
	out.lock_height = api_out.lock_height;

	match out.status {
		OutputStatus::Unconfirmed => {
			out.status = OutputStatus::Unspent;
		}
		_ => (),
	}
}

// Transitions a local wallet output (based on it not being in the node utxo
// set) -
// Unspent -> Spent
// Locked -> Spent
fn mark_spent_output(out: &mut OutputData) {
	match out.status {
		OutputStatus::Unspent | OutputStatus::Locked => out.status = OutputStatus::Spent,
		_ => (),
	}
}

/// Builds multiple api queries to retrieve the latest output data from the node.
/// So we can refresh the local wallet outputs.
pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), Error> {
	debug!(LOGGER, "Refreshing wallet outputs");
	let mut wallet_outputs: HashMap<pedersen::Commitment, Identifier> = HashMap::new();
	let mut commits: Vec<pedersen::Commitment> = vec![];

	// build a local map of wallet outputs by commits
	// and a list of outputs we want to query the node for
	let _ = WalletData::read_wallet(&config.data_file_dir, |wallet_data| {
		for out in wallet_data
			.outputs
			.values()
			.filter(|out| out.root_key_id == keychain.root_key_id())
			.filter(|out| out.status != OutputStatus::Spent)
		{
			let commit = keychain
				.commit_with_key_index(out.value, out.n_child)
				.unwrap();
			commits.push(commit);
			wallet_outputs.insert(commit, out.key_id.clone());
		}
	});

	// build the necessary query params -
	// ?id=xxx&id=yyy&id=zzz
	let query_params: Vec<String> = commits
		.iter()
		.map(|commit| {
			let id = util::to_hex(commit.as_ref().to_vec());
			format!("id={}", id)
		})
		.collect();

	// build a map of api outputs by commit so we can look them up efficiently
	let mut api_outputs: HashMap<pedersen::Commitment, api::Output> = HashMap::new();

	// size of the batch size for the utxo query
	let batch_query_size = 500;

	let mut index_id = 0;
	while index_id < query_params.len() {
		let batch_query: Vec<String>;
		if index_id + batch_query_size > query_params.len() {
			batch_query = query_params[index_id..query_params.len()].to_vec();
			index_id = query_params.len();
		} else {
			batch_query = query_params[index_id..index_id + batch_query_size].to_vec();
			index_id = index_id + batch_query_size;
		}

		let query_string = batch_query.join("&");

		let url = format!(
			"{}/v1/chain/utxos/byids?{}",
			config.check_node_api_http_addr, query_string,
		);

		match api::client::get::<Vec<api::Output>>(url.as_str()) {
			Ok(outputs) => for out in outputs {
				api_outputs.insert(out.commit, out);
			},
			Err(e) => {
				// if we got anything other than 200 back from server, don't attempt to refresh
				// the wallet data after
				return Err(Error::Node(e));
			}
		};
	}

	// now for each commit, find the output in the wallet and
	// the corresponding api output (if it exists)
	// and refresh it in-place in the wallet.
	// Note: minimizing the time we spend holding the wallet lock.
	WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
		for commit in commits {
			let id = wallet_outputs.get(&commit).unwrap();
			if let Entry::Occupied(mut output) = wallet_data.outputs.entry(id.to_hex()) {
				match api_outputs.get(&commit) {
					Some(api_output) => refresh_output(&mut output.get_mut(), api_output),
					None => mark_spent_output(&mut output.get_mut()),
				};
			}
		}
	})
}

pub fn get_tip_from_node(config: &WalletConfig) -> Result<api::Tip, Error> {
	let url = format!("{}/v1/chain", config.check_node_api_http_addr);
	api::client::get::<api::Tip>(url.as_str()).map_err(|e| Error::Node(e))
}
<|endoftext|>


<commit_before>use std::cmp::min;

#[deriving(Clone, Eq)]
pub struct Point {
    x: f64,
    y: f64,
}

#[deriving(Clone, Eq)]
pub struct Size {
    width: f64,
    height: f64,
}

#[deriving(Clone, Eq)]
pub struct Rect {
    origin: Point,
    size: Size,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }

    pub fn add(&self, addPoint: Point) -> Point {
        Point { x: self.x + addPoint.x, y: self.y + addPoint.y }
    }

    pub fn subtract(&self, offsetPoint: Point) -> Point {
        Point { x: self.x - offsetPoint.x, y: self.y - offsetPoint.y }
    }
}

impl Size {
    pub fn new(width: f64, height: f64) -> Size {
        Size { width: width, height: height }
    }
}

impl Rect {
    pub fn new(origin: Point, size: Size) -> Rect {
        Rect { origin: origin, size: size }
    }

    /// Find which the rect has an origin farther to the left.
    pub fn minXRect<'a>(rect1: &'a Rect, rect2: &'a Rect) -> (&'a Rect, &'a Rect) {
        if rect1.minX() <= rect2.minX() {
            (rect1, rect2)
        } else {
            (rect2, rect1)
        }
    }

    /// Find which the rect has an origin with a lower y value.
    pub fn minYRect<'a>(rect1: &'a Rect, rect2: &'a Rect) -> (&'a Rect, &'a Rect) {
        if rect1.minY() <= rect2.minY() {
            (rect1, rect2)
        } else {
            (rect2, rect1)
        }
    }

    /**
     Check if this rect entirely contains another rect.
     */
    pub fn contains(&self, rect: &Rect) -> bool {
        // Find which the rect has an origin farther to the left.
        let (minXRect, otherRect) = Rect::minXRect(self, rect);

        // If the rectangles don't intersect, one cannot be contained in the other.
        self.intersects(rect)
        && (minXRect.maxX() >= otherRect.maxX() && minXRect.maxY() >= otherRect.maxY())
    }

    /**
     Check if this rect and another rect intersect.
     */
    pub fn intersects(&self, rect: &Rect) -> bool {
        let (minXRect, otherRect) = Rect::minXRect(self, rect);

        let intersects: bool = (minXRect.maxX() >= otherRect.minX())
            && ((minXRect.minY() >= otherRect.minY() && minXRect.minY() <= otherRect.maxY())
                || (minXRect.minY() <= otherRect.minY() && minXRect.maxY() >= otherRect.minY()));

        intersects
    }

    /**
     Get the intersection with another rect.
     */
    pub fn intersect(&self, rect: &Rect) -> Option<Rect> {
        if !self.intersects(rect) {
            return None;
        }

        let (minXRect, otherXRect) = Rect::minXRect(self, rect);
        let (minYRect, otherYRect) = Rect::minYRect(self, rect);
        let commonXStart = otherXRect.minX();
        let commonYStart = otherYRect.minY();

        let commonXEnd = min(minXRect.maxX(), otherXRect.maxX());
        let commonYEnd = min(minYRect.maxY(), otherYRect.maxY());

        let width = commonXEnd - commonXStart;
        let height = commonYEnd - commonYStart;

        Some(Rect::new(Point { x: commonXStart, y: commonYStart }, Size { width: width, height: height }))
    }

    pub fn maxX(&self) -> f64 {
        self.origin.x + self.size.width
    }

    pub fn maxY(&self) -> f64 {
        self.origin.y + self.size.height
    }

    pub fn minX(&self) -> f64 {
        self.origin.x
    }

    pub fn minY(&self) -> f64 {
        self.origin.y
    }

    pub fn height(&self) -> f64 {
        self.size.height
    }

    pub fn width(&self) -> f64 {
        self.size.width
    }
}
<commit_msg>Use more 'new' methods instead of directly initializing structs.<commit_after>use std::cmp::min;

#[deriving(Clone, Eq)]
pub struct Point {
    x: f64,
    y: f64,
}

#[deriving(Clone, Eq)]
pub struct Size {
    width: f64,
    height: f64,
}

#[deriving(Clone, Eq)]
pub struct Rect {
    origin: Point,
    size: Size,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }

    pub fn add(&self, addPoint: Point) -> Point {
        Point::new(self.x + addPoint.x, self.y + addPoint.y)
    }

    pub fn subtract(&self, offsetPoint: Point) -> Point {
        Point::new(self.x - offsetPoint.x, self.y - offsetPoint.y)
    }
}

impl Size {
    pub fn new(width: f64, height: f64) -> Size {
        Size { width: width, height: height }
    }
}

impl Rect {
    pub fn new(origin: Point, size: Size) -> Rect {
        Rect { origin: origin, size: size }
    }

    /// Find which the rect has an origin farther to the left.
    pub fn minXRect<'a>(rect1: &'a Rect, rect2: &'a Rect) -> (&'a Rect, &'a Rect) {
        if rect1.minX() <= rect2.minX() {
            (rect1, rect2)
        } else {
            (rect2, rect1)
        }
    }

    /// Find which the rect has an origin with a lower y value.
    pub fn minYRect<'a>(rect1: &'a Rect, rect2: &'a Rect) -> (&'a Rect, &'a Rect) {
        if rect1.minY() <= rect2.minY() {
            (rect1, rect2)
        } else {
            (rect2, rect1)
        }
    }

    /**
     Check if this rect entirely contains another rect.
     */
    pub fn contains(&self, rect: &Rect) -> bool {
        // Find which the rect has an origin farther to the left.
        let (minXRect, otherRect) = Rect::minXRect(self, rect);

        // If the rectangles don't intersect, one cannot be contained in the other.
        self.intersects(rect)
        && (minXRect.maxX() >= otherRect.maxX() && minXRect.maxY() >= otherRect.maxY())
    }

    /**
     Check if this rect and another rect intersect.
     */
    pub fn intersects(&self, rect: &Rect) -> bool {
        let (minXRect, otherRect) = Rect::minXRect(self, rect);

        let intersects: bool = (minXRect.maxX() >= otherRect.minX())
            && ((minXRect.minY() >= otherRect.minY() && minXRect.minY() <= otherRect.maxY())
                || (minXRect.minY() <= otherRect.minY() && minXRect.maxY() >= otherRect.minY()));

        intersects
    }

    /**
     Get the intersection with another rect.
     */
    pub fn intersect(&self, rect: &Rect) -> Option<Rect> {
        if !self.intersects(rect) {
            return None;
        }

        let (minXRect, otherXRect) = Rect::minXRect(self, rect);
        let (minYRect, otherYRect) = Rect::minYRect(self, rect);
        let commonXStart = otherXRect.minX();
        let commonYStart = otherYRect.minY();

        let commonXEnd = min(minXRect.maxX(), otherXRect.maxX());
        let commonYEnd = min(minYRect.maxY(), otherYRect.maxY());

        let width = commonXEnd - commonXStart;
        let height = commonYEnd - commonYStart;

        Some(Rect::new(Point::new(commonXStart, commonYStart), Size::new(width, height)))
    }

    pub fn maxX(&self) -> f64 {
        self.origin.x + self.size.width
    }

    pub fn maxY(&self) -> f64 {
        self.origin.y + self.size.height
    }

    pub fn minX(&self) -> f64 {
        self.origin.x
    }

    pub fn minY(&self) -> f64 {
        self.origin.y
    }

    pub fn height(&self) -> f64 {
        self.size.height
    }

    pub fn width(&self) -> f64 {
        self.size.width
    }
}
<|endoftext|>