<commit_before>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

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

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            if bytes.len() >= length as usize {
                Some(MessageHeader {
                    graph: graph,
                    channel: channel,
                    source: source,
                    target: target,
                    length: length,
                })
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer
    staging:    Vec<u8>,    // 1 << 20 of buffer to read into
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {

            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            staging:    vec![0u8; 1 << 20],
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            // TODO : Could consider optimizing for the self.buffer.len() == 0 case, swapping
            // TODO : self.staging with self.buffer, rather than using write_all.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {

                    let h_len = header.length as usize;  // length in bytes
                    let target = self.targets.ensure(header.target, header.graph, header.channel);
                    let mut buffer = target.1.try_recv().unwrap_or(Vec::new());

                    buffer.clear();
                    buffer.write_all(&slice[..h_len]).unwrap();
                    slice = &slice[h_len..];

                    target.0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                // if slice.len() < self.buffer.len() {
                    self.double.clear();
                    self.double.write_all(slice).unwrap();
                // }
            }

            // if self.double.len() > 0 {
                mem::swap(&mut self.buffer, &mut self.double);
                // self.double.clear();
            // }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        // we've just ensured that this is not None
        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    // println!("addresses.len() : {} vs workers : {}", addresses.len(), workers);
    // assert!(addresses.len() as u64 == workers);
    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64,
                                               BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()),
                                               sender_channels_r,
                                               writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<commit_msg>removed asserts<commit_after>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

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

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            if bytes.len() >= length as usize {
                Some(MessageHeader {
                    graph: graph,
                    channel: channel,
                    source: source,
                    target: target,
                    length: length,
                })
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer
    staging:    Vec<u8>,    // 1 << 20 of buffer to read into
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {

            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            staging:    vec![0u8; 1 << 20],
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            // TODO : Could consider optimizing for the self.buffer.len() == 0 case, swapping
            // TODO : self.staging with self.buffer, rather than using write_all.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {

                    let h_len = header.length as usize;  // length in bytes
                    let target = self.targets.ensure(header.target, header.graph, header.channel);
                    let mut buffer = target.1.try_recv().unwrap_or(Vec::new());

                    buffer.clear();
                    buffer.write_all(&slice[..h_len]).unwrap();
                    slice = &slice[h_len..];

                    target.0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                // if slice.len() < self.buffer.len() {
                    self.double.clear();
                    self.double.write_all(slice).unwrap();
                // }
            }

            // if self.double.len() > 0 {
                mem::swap(&mut self.buffer, &mut self.double);
                // self.double.clear();
            // }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        // we've just ensured that this is not None
        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64,
                                               BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()),
                                               sender_channels_r,
                                               writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<|endoftext|>


<commit_before>extern crate gltf;

use std::{fs, io};

use gltf::{Glb, Gltf};
use std::boxed::Box;
use std::error::Error as StdError;

fn print_tree(node: &gltf::Node, depth: i32) {
    for _ in 0..(depth - 1) {
        print!("  ");
    }
    print!(" -");
    let index = node.index();
    let name = node.name().unwrap_or("<Unnamed>");
    println!(" Node {} ({})", index, name);
    for child in node.children() {
        print_tree(&child, depth + 1);
    }
}

fn run(path: &str) -> Result<(), Box<StdError>> {
    use io::Read;
    let file = fs::File::open(&path)?;
    let mut data = Vec::with_capacity(file.metadata()?.len() as usize);
    let mut reader = io::BufReader::new(file);
    let _ = reader.read_to_end(&mut data)?;
    let gltf = if gltf::is_binary(&data) {
        let glb = Glb::from_slice(&data)?;
        Gltf::from_slice(glb.json)
    } else {
        Gltf::from_slice(&data)
    }?.validate_completely()?;
    for scene in gltf.scenes() {
        let index = scene.index();
        let name = scene.name().unwrap_or("<Unnamed>");
        println!("Scene {} ({})", index, name);
        for node in scene.nodes() {
            print_tree(&node, 1);
        }
    }
    Ok(())
}

fn main() {
    if let Some(path) = std::env::args().nth(1) {
        run(&path).expect("runtime error");
    } else {
        println!("usage: gltf-tree <FILE>");
    }
}
<commit_msg>Fix tree example<commit_after>extern crate gltf;

use std::{fs, io};

use gltf::{Glb, Gltf};
use std::boxed::Box;
use std::error::Error as StdError;

fn print_tree(node: &gltf::Node, depth: i32) {
    for _ in 0..(depth - 1) {
        print!("  ");
    }
    print!(" -");
    let index = node.index();
    let name = node.name().unwrap_or("<Unnamed>");
    println!(" Node {} ({})", index, name);
    for child in node.children() {
        print_tree(&child, depth + 1);
    }
}

fn run(path: &str) -> Result<(), Box<StdError>> {
    use io::Read;
    let file = fs::File::open(&path)?;
    let mut data = Vec::with_capacity(file.metadata()?.len() as usize);
    let mut reader = io::BufReader::new(file);
    let _ = reader.read_to_end(&mut data)?;
    let gltf = if gltf::is_binary(&data) {
        let glb = Glb::from_slice(&data)?;
        Gltf::from_slice(&glb.json)
    } else {
        Gltf::from_slice(&data)
    }?.validate_completely()?;
    for scene in gltf.scenes() {
        let index = scene.index();
        let name = scene.name().unwrap_or("<Unnamed>");
        println!("Scene {} ({})", index, name);
        for node in scene.nodes() {
            print_tree(&node, 1);
        }
    }
    Ok(())
}

fn main() {
    if let Some(path) = std::env::args().nth(1) {
        run(&path).expect("runtime error");
    } else {
        println!("usage: gltf-tree <FILE>");
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/grid-game/
pub fn grid_game(mut grid: Vec<Vec<i32>>) -> i64 {
    fn prefix_sums(v: &Vec<i32>) -> Vec<i64> {
        let num_cols = v.len();
        let mut prefix_sums = vec![0i64; num_cols];
        for i in 0..num_cols {
            if i == 0 {
                prefix_sums[i] = v[i] as i64;
            } else {
                prefix_sums[i] = prefix_sums[i - 1] + v[i] as i64;
            }
        }
        return prefix_sums;
    }

    let row1_prefix_sums = prefix_sums(&grid[0]);
    let row2_prefix_sums = prefix_sums(&grid[1]);
    let mut max = 0;
    let mut max_index = 0;
    let mut is_right = true;
    let num_cols = grid[0].len();
    for i in 0..num_cols {
        let right_sum = row1_prefix_sums[num_cols - 1] + grid[1][num_cols - 1] as i64;
        let down_sum = row1_prefix_sums[i]
            + (row2_prefix_sums[num_cols - 1] - if i == 0 { 0 } else { row2_prefix_sums[i - 1] });
        if max < right_sum {
            max = right_sum;
            max_index = i;
            is_right = true;
        }
        if max < down_sum {
            max = down_sum;
            max_index = i;
            is_right = false;
        }
    }
    if is_right {
        for i in 0..num_cols {
            grid[0][i] = 0;
            grid[1][num_cols - 1] = 0;
        }
    } else {
        for i in 0..=max_index {
            grid[0][i] = 0;
        }
        for i in max_index..num_cols {
            grid[1][i] = 0;
        }
    }
    let row1_prefix_sums = prefix_sums(&grid[0]);
    let row2_prefix_sums = prefix_sums(&grid[1]);
    let mut answer = 0;
    let num_cols = grid[0].len();
    for i in 0..num_cols {
        let right_sum = row1_prefix_sums[num_cols - 1] + grid[1][num_cols - 1] as i64;
        let down_sum = row1_prefix_sums[i]
            + (row2_prefix_sums[num_cols - 1] - if i == 0 { 0 } else { row2_prefix_sums[i - 1] });
        answer = answer.max(right_sum.max(down_sum));
    }
    answer
}

fn main() {
    // println!("{}", grid_game(vec![vec![2, 5, 4], vec![1, 5, 1]])); // 4
    // println!("{}", grid_game(vec![vec![3, 3, 1], vec![8, 5, 2]])); // 4
    // println!("{}", grid_game(vec![vec![1, 3, 1, 15], vec![1, 3, 3, 1]])); // 7
    println!(
        "{}",
        grid_game(vec![
            vec![28, 30, 40, 5, 2, 19],
            vec![94, 11, 40, 1, 40, 23]
        ])
    ); // 94
}
<commit_msg>Solve problem 2017<commit_after>// https://leetcode.com/problems/grid-game/
pub fn grid_game(grid: Vec<Vec<i32>>) -> i64 {
    fn prefix_sums(v: &Vec<i32>) -> Vec<i64> {
        let num_cols = v.len();
        let mut prefix_sums = vec![0i64; num_cols];
        for i in 0..num_cols {
            if i == 0 {
                prefix_sums[i] = v[i] as i64;
            } else {
                prefix_sums[i] = prefix_sums[i - 1] + v[i] as i64;
            }
        }
        return prefix_sums;
    }

    let num_cols = grid[0].len();
    let row0_prefix_sums = prefix_sums(&grid[0]);
    let row1_prefix_sums = prefix_sums(&grid[1]);
    // row0: -xxxxxx
    // row1: |------
    let sum1 = row0_prefix_sums[num_cols - 1] - grid[0][0] as i64;
    // row0: -------
    // row1: xxxxxx|
    let sum2 = row1_prefix_sums[num_cols - 1] - grid[1][num_cols - 1] as i64;
    let mut answer = sum1.min(sum2);
    for i in 1..num_cols - 1 {
        // row0: ---|xxx
        // row1: xxx|---
        let sum3 = row0_prefix_sums[num_cols - 1] - row0_prefix_sums[i];
        let sum4 = row1_prefix_sums[i] - grid[1][i] as i64;
        answer = answer.min(sum3.max(sum4));
    }
    answer
}

fn main() {
    println!("{}", grid_game(vec![vec![2, 5, 4], vec![1, 5, 1]])); // 4
    println!("{}", grid_game(vec![vec![3, 3, 1], vec![8, 5, 2]])); // 4
    println!("{}", grid_game(vec![vec![1, 3, 1, 15], vec![1, 3, 3, 1]])); // 7
    println!(
        "{}",
        grid_game(vec![
            vec![28, 30, 40, 5, 2, 19],
            vec![94, 11, 40, 1, 40, 23]
        ])
    ); // 94
}
<|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")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

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

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s = "a"; // &str
    /// let ss = s.to_owned(); // String
    ///
    /// let v = &[1, 2]; // slice
    /// let vv = v.to_owned(); // Vec
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// # #[allow(dead_code)]
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(
        #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
    ),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<commit_msg>Rollup merge of #34305 - Aaronepower:master, r=alexcrichton<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")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::default::Default;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

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

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s = "a"; // &str
    /// let ss = s.to_owned(); // String
    ///
    /// let v = &[1, 2]; // slice
    /// let vv = v.to_owned(); // Vec
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// # #[allow(dead_code)]
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(
        #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
    ),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: Default
{
    fn default() -> Cow<'a, B> {
        Owned(<B as ToOwned>::Owned::default())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"]
#[stable(feature = "futures_api", since = "1.36.0")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<commit_msg>Rollup merge of #60808 - Schultzer:improve-must-use-linit-for-future, r=Centril<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<|endoftext|>


<commit_before><commit_msg>events: Make MediaSource an exhaustive enum<commit_after><|endoftext|>


<commit_before>use crate::model::id::{StickerId, StickerPackId};

/// A sticker sent with a message.
///
/// Bots currently can only receive messages with stickers, not send.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct Sticker {
    /// The unique ID given to this sticker.
    pub id: StickerId,
    /// The unique ID of the pack the sticker is from.
    pub pack_id: StickerPackId,
    /// The name of the sticker.
    pub name: String,
    /// Description of the sticker
    pub description: String,
    /// A comma-separated list of tags for the sticker.
    pub tags: Option<String>,
    /// The sticker asset hash.
    pub asset: String,
    /// The sticker preview asset hash.
    pub preview_asset: Option<String>,
    /// The type of sticker format.
    pub format_type: StickerFormatType,
}

/// Differentiates between sticker formats.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum StickerFormatType {
    /// A PNG format sticker.
    Png = 1,
    /// An APNG format animated sticker.
    Apng = 2,
    /// A LOTTIE format animated sticker.
    Lottie = 3,
    /// Unknown sticker format type.
    Unknown = !0,
}

enum_number!(StickerFormatType {
    Png,
    Apng,
    Lottie
});
<commit_msg>Define `Sticker::pack_id` as optional (#1482)<commit_after>use crate::model::id::{StickerId, StickerPackId};

/// A sticker sent with a message.
///
/// Bots currently can only receive messages with stickers, not send.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct Sticker {
    /// The unique ID given to this sticker.
    pub id: StickerId,
    /// The unique ID of the pack the sticker is from.
    pub pack_id: Option<StickerPackId>,
    /// The name of the sticker.
    pub name: String,
    /// Description of the sticker
    pub description: String,
    /// A comma-separated list of tags for the sticker.
    pub tags: Option<String>,
    /// The sticker asset hash.
    pub asset: String,
    /// The sticker preview asset hash.
    pub preview_asset: Option<String>,
    /// The type of sticker format.
    pub format_type: StickerFormatType,
}

/// Differentiates between sticker formats.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum StickerFormatType {
    /// A PNG format sticker.
    Png = 1,
    /// An APNG format animated sticker.
    Apng = 2,
    /// A LOTTIE format animated sticker.
    Lottie = 3,
    /// Unknown sticker format type.
    Unknown = !0,
}

enum_number!(StickerFormatType {
    Png,
    Apng,
    Lottie
});
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::collections::BinaryHeap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("23.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

type Cube = (isize, isize, isize, isize, isize, isize);
type Position = (isize, isize, isize);

#[derive(Debug, Clone, Eq, PartialEq)]
struct Nanobot {
    position: Position,
    radius: usize
}

fn parse(input: &str) -> Vec<Nanobot> {
    input.lines()
    .map(|line| line.split(|c| ['<', '>', ',', '='].contains(&c)))
    .map(|mut tokens| [tokens.nth(2), tokens.next(), tokens.next(), tokens.nth(2)])
    .map(|tokens| {
        tokens.into_iter()
        .filter_map(|token| token.and_then(|x| x.parse::<isize>().ok()))
        .collect::<Vec<_>>()
    })
    .filter(|tokens| tokens.len() == 4)
    .map(|tokens| Nanobot {
        position: (tokens[0], tokens[1], tokens[2]),
        radius: tokens[3] as usize
    })
    .collect()
}

fn manhattan_dist((x1, y1, z1): Position, (x2, y2, z2): Position) -> usize {
    ((x2 - x1).abs() + (y2 - y1).abs() + (z2 - z1).abs()) as usize
}

fn in_bot_range(bot: &Nanobot, p: Position) -> bool {
    manhattan_dist(bot.position, p) <= bot.radius
}

fn has_range_overlap(bot1: &Nanobot, bot2: &Nanobot) -> bool {
    manhattan_dist(bot1.position, bot2.position) <= bot1.radius + bot2.radius
}

fn subdivide_cube((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> Vec<Cube> {
    let xmid = (xmin + xmax) / 2;
    let ymid = (ymin + ymax) / 2;
    let zmid = (zmin + zmax) / 2;

    vec![
        (xmin, xmid, ymin, ymid, zmin, zmid),
        (xmin, xmid, ymin, ymid, zmid + 1, zmax),
        (xmin, xmid, ymid + 1, ymax, zmin, zmid),
        (xmin, xmid, ymid + 1, ymax, zmid + 1, zmax),
        (xmid + 1, xmax, ymin, ymid, zmin, zmid),
        (xmid + 1, xmax, ymin, ymid, zmid + 1, zmax),
        (xmid + 1, xmax, ymid + 1, ymax, zmin, zmid),
        (xmid + 1, xmax, ymid + 1, ymax, zmid + 1, zmax)
    ].into_iter()
    .filter(|&(xmin, xmax, ymin, ymax, zmin, zmax)| xmin <= xmax && ymin <= ymax && zmin <= zmax)
    .collect()
}

fn cube_to_range((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> Nanobot {
    let xmid = (xmin + xmax) / 2;
    let ymid = (ymin + ymax) / 2;
    let zmid = (zmin + zmax) / 2;
    let position = (xmid, ymid, zmid);
    let radius = [
        manhattan_dist(position, (xmin, ymin, zmin)),
        manhattan_dist(position, (xmin, ymin, zmax)),
        manhattan_dist(position, (xmin, ymax, zmin)),
        manhattan_dist(position, (xmin, ymax, zmax)),
        manhattan_dist(position, (xmax, ymin, zmin)),
        manhattan_dist(position, (xmax, ymin, zmax)),
        manhattan_dist(position, (xmax, ymax, zmin)),
        manhattan_dist(position, (xmax, ymax, zmax))
    ].into_iter().cloned().min().unwrap();

    Nanobot {
        position,
        radius
    }
}

fn is_position((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> bool {
    xmin == xmax && ymin == ymax && zmin == zmax
}

fn bots_near_cube(bots: &[Nanobot], cube: Cube) -> Vec<&Nanobot> {
    let range = cube_to_range(cube);

    bots.iter()
    .filter(|&bot| has_range_overlap(bot, &range))
    .collect()
}

fn find_position(bots: &[Nanobot]) -> Option<Position> {
    let mut heap = BinaryHeap::new();
    let mut max = None;

    let start_cube = {
        let xmin = bots.iter().map(|bot| bot.position.0).min().unwrap_or(0);
        let xmax = bots.iter().map(|bot| bot.position.0).max().unwrap_or(0);
        let ymin = bots.iter().map(|bot| bot.position.1).min().unwrap_or(0);
        let ymax = bots.iter().map(|bot| bot.position.1).max().unwrap_or(0);
        let zmin = bots.iter().map(|bot| bot.position.2).min().unwrap_or(0);
        let zmax = bots.iter().map(|bot| bot.position.2).max().unwrap_or(0);

        (xmin, xmax, ymin, ymax, zmin, zmax)
    };

    heap.push((bots.len(), start_cube));

    while let Some((bots_count, cube)) = heap.pop() {
        if is_position(cube) {
            let position = (cube.0, cube.2, cube.4);
            let distance = manhattan_dist(position, (0, 0, 0)) as isize;

            if max.is_none() || max.unwrap() < (bots_count, -distance, position) {
                max = Some((bots_count, -distance, position));
            }
        }

        for subcube in subdivide_cube(cube).into_iter() {
            let bots_count = bots_near_cube(bots, subcube).len();

            if max.is_none() || bots_count > max.unwrap().0 {
                heap.push((bots_count, subcube))
            }
        }
    }

    max.map(|(_, _, p)| p)
}

fn main() {
    let input = get_input().unwrap();
    let nanobots = parse(&input);

    nanobots.iter()
    .max_by_key(|bot| bot.radius)
    .map(|strongest| {
        nanobots.iter()
        .filter(|bot| in_bot_range(strongest, bot.position))
        .count()
    })
    .map(|count| println!("Part 1: {}", count));

    find_position(&nanobots)
    .map(|p| println!("Part 2: {}", manhattan_dist(p, (0, 0, 0))));
}
<commit_msg>Fix some logic errors<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::collections::BinaryHeap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("23.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

type Cube = (isize, isize, isize, isize, isize, isize);
type Position = (isize, isize, isize);

#[derive(Debug, Clone, Eq, PartialEq)]
struct Nanobot {
    position: Position,
    radius: usize
}

fn parse(input: &str) -> Vec<Nanobot> {
    input.lines()
    .map(|line| line.split(|c| ['<', '>', ',', '='].contains(&c)))
    .map(|mut tokens| [tokens.nth(2), tokens.next(), tokens.next(), tokens.nth(2)])
    .map(|tokens| {
        tokens.into_iter()
        .filter_map(|token| token.and_then(|x| x.parse::<isize>().ok()))
        .collect::<Vec<_>>()
    })
    .filter(|tokens| tokens.len() == 4)
    .map(|tokens| Nanobot {
        position: (tokens[0], tokens[1], tokens[2]),
        radius: tokens[3] as usize
    })
    .collect()
}

fn manhattan_dist((x1, y1, z1): Position, (x2, y2, z2): Position) -> usize {
    ((x2 - x1).abs() + (y2 - y1).abs() + (z2 - z1).abs()) as usize
}

fn in_bot_range(bot: &Nanobot, p: Position) -> bool {
    manhattan_dist(bot.position, p) <= bot.radius
}

fn has_range_overlap(bot1: &Nanobot, bot2: &Nanobot) -> bool {
    manhattan_dist(bot1.position, bot2.position) <= bot1.radius + bot2.radius
}

fn subdivide_cube((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> Vec<Cube> {
    let xmid = (xmin + xmax) / 2;
    let ymid = (ymin + ymax) / 2;
    let zmid = (zmin + zmax) / 2;

    vec![
        (xmin, xmid, ymin, ymid, zmin, zmid),
        (xmin, xmid, ymin, ymid, zmid + 1, zmax),
        (xmin, xmid, ymid + 1, ymax, zmin, zmid),
        (xmin, xmid, ymid + 1, ymax, zmid + 1, zmax),
        (xmid + 1, xmax, ymin, ymid, zmin, zmid),
        (xmid + 1, xmax, ymin, ymid, zmid + 1, zmax),
        (xmid + 1, xmax, ymid + 1, ymax, zmin, zmid),
        (xmid + 1, xmax, ymid + 1, ymax, zmid + 1, zmax)
    ].into_iter()
    .filter(|&(xmin, xmax, ymin, ymax, zmin, zmax)| xmin <= xmax && ymin <= ymax && zmin <= zmax)
    .collect()
}

fn approximate_cube_by_range((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> Nanobot {
    let xmid = (xmin + xmax) / 2;
    let ymid = (ymin + ymax) / 2;
    let zmid = (zmin + zmax) / 2;
    let position = (xmid, ymid, zmid);
    let radius = [
        manhattan_dist(position, (xmin, ymin, zmin)),
        manhattan_dist(position, (xmin, ymin, zmax)),
        manhattan_dist(position, (xmin, ymax, zmin)),
        manhattan_dist(position, (xmin, ymax, zmax)),
        manhattan_dist(position, (xmax, ymin, zmin)),
        manhattan_dist(position, (xmax, ymin, zmax)),
        manhattan_dist(position, (xmax, ymax, zmin)),
        manhattan_dist(position, (xmax, ymax, zmax))
    ].into_iter().cloned().max().unwrap();

    Nanobot {
        position,
        radius
    }
}

fn is_point((xmin, xmax, ymin, ymax, zmin, zmax): Cube) -> bool {
    xmin == xmax && ymin == ymax && zmin == zmax
}

fn bots_near_cube(bots: &[Nanobot], cube: Cube) -> Vec<&Nanobot> {
    let range = approximate_cube_by_range(cube);

    bots.iter()
    .filter(|&bot| has_range_overlap(bot, &range))
    .collect()
}

fn find_position(bots: &[Nanobot]) -> Option<Position> {
    let mut heap = BinaryHeap::new();
    let mut max = None;

    let start_cube = {
        let xmin = bots.iter().map(|bot| bot.position.0).min().unwrap_or(0);
        let xmax = bots.iter().map(|bot| bot.position.0).max().unwrap_or(0);
        let ymin = bots.iter().map(|bot| bot.position.1).min().unwrap_or(0);
        let ymax = bots.iter().map(|bot| bot.position.1).max().unwrap_or(0);
        let zmin = bots.iter().map(|bot| bot.position.2).min().unwrap_or(0);
        let zmax = bots.iter().map(|bot| bot.position.2).max().unwrap_or(0);

        (xmin, xmax, ymin, ymax, zmin, zmax)
    };

    heap.push((bots.len(), start_cube));

    while let Some((bots_count, cube)) = heap.pop() {
        if is_point(cube) {
            let position = (cube.0, cube.2, cube.4);
            let distance = manhattan_dist(position, (0, 0, 0)) as isize;
            let potential_max = (bots_count, -distance, position);

            if max.is_none() || max.unwrap() < potential_max {
                max = Some(potential_max);
            }
        }

        for subcube in subdivide_cube(cube).into_iter() {
            let bots_count = bots_near_cube(bots, subcube).len();

            if max.is_none() || bots_count > max.unwrap().0 {
                heap.push((bots_count, subcube))
            }
        }
    }

    max.map(|(_, _, p)| p)
}

fn main() {
    let input = get_input().unwrap();
    let nanobots = parse(&input);

    nanobots.iter()
    .max_by_key(|bot| bot.radius)
    .map(|strongest| {
        nanobots.iter()
        .filter(|bot| in_bot_range(strongest, bot.position))
        .count()
    })
    .map(|count| println!("Part 1: {}", count));

    find_position(&nanobots)
    .map(|p| println!("Part 2: {}", manhattan_dist(p, (0, 0, 0))));
}
<|endoftext|>


<commit_before>//! A CLI tool for inspecting the contents of a DICOM file.
//! Despite the name, this tool may have a different interface and output
//! from other `dcmdump` tools, and does not aim to make a drop-in
//! replacement.
//!
//! Usage:
//!
//! ```none
//! dcmdump <file.dcm>
//! ```
use dicom::core::dictionary::{DataDictionary, DictionaryEntry};
use dicom::core::header::Header;
use dicom::core::value::{PrimitiveValue, Value as DicomValue};
use dicom::core::VR;
use dicom::object::mem::{InMemDicomObject, InMemElement};
use dicom::object::{open_file, DefaultDicomObject, FileMetaTable, StandardDataDictionary};

use std::borrow::Cow;
use std::io::{stdout, ErrorKind, Result as IoResult, Write};

type DynResult<T> = Result<T, Box<dyn std::error::Error>>;

fn main() -> DynResult<()> {
    let filename = ::std::env::args()
        .nth(1)
        .expect("Missing path to DICOM file");

    let obj = open_file(filename)?;

    match dump_file(obj) {
        Err(ref e) if e.kind() == ErrorKind::BrokenPipe => {
            Ok(()) // handle broken pipe separately with a no-op
        }
        Err(e) => Err(e.into()), // raise other errors
        _ => Ok(()),             // all good
    }
}

fn dump_file(obj: DefaultDicomObject) -> IoResult<()> {
    let mut to = stdout();
    write!(to, "# Dicom-File-Format\n\n")?;

    let meta = obj.meta();

    let width = 40;

    meta_dump(&mut to, &meta, width)?;

    dump(&mut to, &obj, width, 0)?;

    Ok(())
}

fn meta_dump<W>(to: &mut W, meta: &FileMetaTable, width: u32) -> IoResult<()>
where
    W: ?Sized + Write,
{
    writeln!(
        to,
        "Media Storage SOP Class UID: {}",
        meta.media_storage_sop_class_uid
    )?;
    writeln!(
        to,
        "Media Storage SOP Instance UID: {}",
        meta.media_storage_sop_instance_uid
    )?;
    writeln!(to, "Transfer Syntax: {}", meta.transfer_syntax)?;
    writeln!(to, "Implementation Class UID: {}", meta.transfer_syntax)?;

    if let Some(v) = meta.implementation_version_name.as_ref() {
        writeln!(to, "Implementation version name: {}", v)?;
    }
    if let Some(v) = meta.source_application_entity_title.as_ref() {
        writeln!(to, "Source Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.sending_application_entity_title.as_ref() {
        writeln!(to, "Sending Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.receiving_application_entity_title.as_ref() {
        writeln!(to, "Receiving Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.private_information_creator_uid.as_ref() {
        writeln!(to, "Private Information Creator UID: {}", v)?;
    }

    if let Some(v) = meta.private_information.as_ref() {
        writeln!(
            to,
            "Private Information: {}",
            format_value_list(v.iter().map(|n| format!("{:#x}", n)), width,)
        )?;
    }

    writeln!(to)?;
    Ok(())
}

fn dump<W, D>(to: &mut W, obj: &InMemDicomObject<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    for elem in obj {
        dump_element(&mut *to, &elem, width, depth)?;
    }

    Ok(())
}

fn dump_element<W, D>(to: &mut W, elem: &InMemElement<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    let indent = vec![b' '; (depth * 2) as usize];
    let tag_alias = StandardDataDictionary
        .by_tag(elem.tag())
        .map(DictionaryEntry::alias)
        .unwrap_or("«Unknown Attribute»");
    to.write_all(&indent)?;
    let vm = match elem.vr() {
        VR::OB | VR::OW | VR::UN => 1,
        _ => elem.value().multiplicity(),
    };

    if let DicomValue::Sequence { ref items, .. } = elem.value() {
        writeln!(
            to,
            "{} {}                                # {},    {}",
            elem.tag(),
            elem.vr(),
            vm,
            tag_alias
        )?;
        for item in items {
            dump_item(&mut *to, item, width, depth + 1)?;
        }
    } else {
        let vr = elem.vr();
        let value = elem.value().primitive().unwrap();
        let byte_len = value.calculate_byte_len();
        writeln!(
            to,
            "{} {} {:48} # {}, {} {}",
            elem.tag(),
            vr,
            value_summary(&value, vr, width),
            byte_len,
            vm,
            tag_alias
        )?;
    }

    Ok(())
}

fn dump_item<W, D>(to: &mut W, item: &InMemDicomObject<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    let indent: String = std::iter::repeat(' ').take((depth * 2) as usize).collect();
    let trail: String = std::iter::repeat(' ')
        .take(usize::max(21, width as usize - 21 - indent.len()))
        .collect();
    writeln!(to, "{}(FFFE,E000) na Item {} # 0, 0 Item", indent, trail)?;
    dump(to, item, width, depth + 1)?;
    writeln!(
        to,
        "(FFFE,E00D) na (ItemDelimitationItem)  # 0, 0 ItemDelimitationItem"
    )?;
    Ok(())
}

fn value_summary(value: &PrimitiveValue, vr: VR, max_characters: u32) -> Cow<str> {
    use PrimitiveValue::*;
    match (value, vr) {
        (F32(values), _) => format_value_list(values, max_characters).into(),
        (F64(values), _) => format_value_list(values, max_characters).into(),
        (I32(values), _) => format_value_list(values, max_characters).into(),
        (I64(values), _) => format_value_list(values, max_characters).into(),
        (U32(values), _) => format_value_list(values, max_characters).into(),
        (U64(values), _) => format_value_list(values, max_characters).into(),
        (I16(values), _) => format_value_list(values, max_characters).into(),
        (U16(values), VR::OW) => format_value_list(
            values.into_iter().map(|n| format!("{:#x}", n)),
            max_characters,
        )
        .into(),
        (U16(values), _) => format_value_list(values, max_characters).into(),
        (U8(values), VR::OB) | (U8(values), VR::UN) => format_value_list(
            values.into_iter().map(|n| format!("{:#x}", n)),
            max_characters,
        )
        .into(),
        (U8(values), _) => format_value_list(values, max_characters).into(),
        (Tags(values), _) => format_value_list(values, max_characters).into(),
        (Strs(values), _) => format_value_list(values, max_characters).into(),
        (Date(values), _) => format_value_list(values, max_characters).into(),
        (Time(values), _) => format_value_list(values, max_characters).into(),
        (DateTime(values), _) => format_value_list(values, max_characters).into(),
        (Str(value), _) => cut_str(&value.to_string(), max_characters)
            .into_owned()
            .into(),
        (Empty, _) => "".into(),
    }
}

fn format_value_list<I>(values: I, max_characters: u32) -> String
where
    I: IntoIterator,
    I::Item: std::fmt::Display,
{
    let pieces = values.into_iter().take(64);
    let max = max_characters as usize;
    let mut o = String::with_capacity(max);
    for piece in pieces {
        o.push_str(&piece.to_string());
        o.push(',');
        if o.len() > max {
            break;
        }
    }
    o.pop();
    cut_str(&o, max_characters).into_owned()
}

fn cut_str(s: &str, max_characters: u32) -> Cow<str> {
    let max = (max_characters - 3) as usize;
    if s.len() > max {
        format!("{}...", &s[..max]).into()
    } else {
        s.into()
    }
}
<commit_msg>[dcmdump] indent ItemDelimitationitem<commit_after>//! A CLI tool for inspecting the contents of a DICOM file.
//! Despite the name, this tool may have a different interface and output
//! from other `dcmdump` tools, and does not aim to make a drop-in
//! replacement.
//!
//! Usage:
//!
//! ```none
//! dcmdump <file.dcm>
//! ```
use dicom::core::dictionary::{DataDictionary, DictionaryEntry};
use dicom::core::header::Header;
use dicom::core::value::{PrimitiveValue, Value as DicomValue};
use dicom::core::VR;
use dicom::object::mem::{InMemDicomObject, InMemElement};
use dicom::object::{open_file, DefaultDicomObject, FileMetaTable, StandardDataDictionary};

use std::borrow::Cow;
use std::io::{stdout, ErrorKind, Result as IoResult, Write};

type DynResult<T> = Result<T, Box<dyn std::error::Error>>;

fn main() -> DynResult<()> {
    let filename = ::std::env::args()
        .nth(1)
        .expect("Missing path to DICOM file");

    let obj = open_file(filename)?;

    match dump_file(obj) {
        Err(ref e) if e.kind() == ErrorKind::BrokenPipe => {
            Ok(()) // handle broken pipe separately with a no-op
        }
        Err(e) => Err(e.into()), // raise other errors
        _ => Ok(()),             // all good
    }
}

fn dump_file(obj: DefaultDicomObject) -> IoResult<()> {
    let mut to = stdout();
    write!(to, "# Dicom-File-Format\n\n")?;

    let meta = obj.meta();

    let width = 40;

    meta_dump(&mut to, &meta, width)?;

    dump(&mut to, &obj, width, 0)?;

    Ok(())
}

fn meta_dump<W>(to: &mut W, meta: &FileMetaTable, width: u32) -> IoResult<()>
where
    W: ?Sized + Write,
{
    writeln!(
        to,
        "Media Storage SOP Class UID: {}",
        meta.media_storage_sop_class_uid
    )?;
    writeln!(
        to,
        "Media Storage SOP Instance UID: {}",
        meta.media_storage_sop_instance_uid
    )?;
    writeln!(to, "Transfer Syntax: {}", meta.transfer_syntax)?;
    writeln!(to, "Implementation Class UID: {}", meta.transfer_syntax)?;

    if let Some(v) = meta.implementation_version_name.as_ref() {
        writeln!(to, "Implementation version name: {}", v)?;
    }
    if let Some(v) = meta.source_application_entity_title.as_ref() {
        writeln!(to, "Source Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.sending_application_entity_title.as_ref() {
        writeln!(to, "Sending Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.receiving_application_entity_title.as_ref() {
        writeln!(to, "Receiving Application Entity Title: {}", v)?;
    }

    if let Some(v) = meta.private_information_creator_uid.as_ref() {
        writeln!(to, "Private Information Creator UID: {}", v)?;
    }

    if let Some(v) = meta.private_information.as_ref() {
        writeln!(
            to,
            "Private Information: {}",
            format_value_list(v.iter().map(|n| format!("{:#x}", n)), width,)
        )?;
    }

    writeln!(to)?;
    Ok(())
}

fn dump<W, D>(to: &mut W, obj: &InMemDicomObject<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    for elem in obj {
        dump_element(&mut *to, &elem, width, depth)?;
    }

    Ok(())
}

fn dump_element<W, D>(to: &mut W, elem: &InMemElement<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    let indent = vec![b' '; (depth * 2) as usize];
    let tag_alias = StandardDataDictionary
        .by_tag(elem.tag())
        .map(DictionaryEntry::alias)
        .unwrap_or("«Unknown Attribute»");
    to.write_all(&indent)?;
    let vm = match elem.vr() {
        VR::OB | VR::OW | VR::UN => 1,
        _ => elem.value().multiplicity(),
    };

    if let DicomValue::Sequence { ref items, .. } = elem.value() {
        writeln!(
            to,
            "{} {}                                # {},    {}",
            elem.tag(),
            elem.vr(),
            vm,
            tag_alias
        )?;
        for item in items {
            dump_item(&mut *to, item, width, depth + 1)?;
        }
    } else {
        let vr = elem.vr();
        let value = elem.value().primitive().unwrap();
        let byte_len = value.calculate_byte_len();
        writeln!(
            to,
            "{} {} {:48} # {}, {} {}",
            elem.tag(),
            vr,
            value_summary(&value, vr, width),
            byte_len,
            vm,
            tag_alias
        )?;
    }

    Ok(())
}

fn dump_item<W, D>(to: &mut W, item: &InMemDicomObject<D>, width: u32, depth: u32) -> IoResult<()>
where
    W: ?Sized + Write,
    D: DataDictionary,
{
    let indent: String = std::iter::repeat(' ').take((depth * 2) as usize).collect();
    let trail: String = std::iter::repeat(' ')
        .take(usize::max(21, width as usize - 21 - indent.len()))
        .collect();
    writeln!(to, "{}(FFFE,E000) na Item {} # 0, 0 Item", indent, trail)?;
    dump(to, item, width, depth + 1)?;
    writeln!(
        to,
        "{}(FFFE,E00D) na (ItemDelimitationItem)  # 0, 0 ItemDelimitationItem",
        indent,
    )?;
    Ok(())
}

fn value_summary(value: &PrimitiveValue, vr: VR, max_characters: u32) -> Cow<str> {
    use PrimitiveValue::*;
    match (value, vr) {
        (F32(values), _) => format_value_list(values, max_characters).into(),
        (F64(values), _) => format_value_list(values, max_characters).into(),
        (I32(values), _) => format_value_list(values, max_characters).into(),
        (I64(values), _) => format_value_list(values, max_characters).into(),
        (U32(values), _) => format_value_list(values, max_characters).into(),
        (U64(values), _) => format_value_list(values, max_characters).into(),
        (I16(values), _) => format_value_list(values, max_characters).into(),
        (U16(values), VR::OW) => format_value_list(
            values.into_iter().map(|n| format!("{:#x}", n)),
            max_characters,
        )
        .into(),
        (U16(values), _) => format_value_list(values, max_characters).into(),
        (U8(values), VR::OB) | (U8(values), VR::UN) => format_value_list(
            values.into_iter().map(|n| format!("{:#x}", n)),
            max_characters,
        )
        .into(),
        (U8(values), _) => format_value_list(values, max_characters).into(),
        (Tags(values), _) => format_value_list(values, max_characters).into(),
        (Strs(values), _) => format_value_list(values, max_characters).into(),
        (Date(values), _) => format_value_list(values, max_characters).into(),
        (Time(values), _) => format_value_list(values, max_characters).into(),
        (DateTime(values), _) => format_value_list(values, max_characters).into(),
        (Str(value), _) => cut_str(&value.to_string(), max_characters)
            .into_owned()
            .into(),
        (Empty, _) => "".into(),
    }
}

fn format_value_list<I>(values: I, max_characters: u32) -> String
where
    I: IntoIterator,
    I::Item: std::fmt::Display,
{
    let pieces = values.into_iter().take(64);
    let max = max_characters as usize;
    let mut o = String::with_capacity(max);
    for piece in pieces {
        o.push_str(&piece.to_string());
        o.push(',');
        if o.len() > max {
            break;
        }
    }
    o.pop();
    cut_str(&o, max_characters).into_owned()
}

fn cut_str(s: &str, max_characters: u32) -> Cow<str> {
    let max = (max_characters - 3) as usize;
    if s.len() > max {
        format!("{}...", &s[..max]).into()
    } else {
        s.into()
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use rustc::hir::{self, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use std::boxed;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io;
use std::path;
use syntax::ast;
use webidl::ast::*;
use webidl::visitor::*;
use webidl::*;

declare_lint!(
    WEBIDL_INHERIT_CORRECT,
    Deny,
    "Warn and report usage of incorrect webidl inheritance"
);

pub struct WebIdlPass;

#[derive(Clone, Debug)]
pub enum WebIdlError {
    ParentMismatch {
        name: String,
        rust_parent: String,
        webidl_parent: String,
    },
}

impl fmt::Display for WebIdlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            WebIdlError::ParentMismatch {
                name,
                rust_parent,
                webidl_parent,
            } => {
                return write!(f, "webidl-rust inheritance mismatch, rust: {:?}, rust parent: {:?}, webidl parent: {:?}",
                    &name, &rust_parent, &webidl_parent);
            },
        }
    }
}

impl Error for WebIdlError {
    fn description(&self) -> &str {
        "WebIdlError"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl WebIdlPass {
    pub fn new() -> WebIdlPass {
        WebIdlPass
    }
}

fn get_ty_name(ty: &str) -> &str {
    if let Some(i) = ty.rfind(':') {
        &ty[i + 1..]
    } else {
        ty
    }
}

fn get_webidl_path(struct_name: &str) -> io::Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    dir.push("components/script/dom/webidls/");
    dir.push(format!("{}.webidl", struct_name));

    Ok(dir)
}

fn is_webidl_ty(cx: &LateContext, ty: &ty::TyS) -> bool {
    let mut ret = false;
    ty.maybe_walk(|t| {
        match t.sty {
            ty::Adt(did, _substs) => {
                if cx.tcx.has_attr(did.did, "webidl") {
                    ret = true;
                }
                false
            },
            ty::Ref(..) => false,    // don't recurse down &ptrs
            ty::RawPtr(..) => false, // don't recurse down *ptrs
            ty::FnDef(..) | ty::FnPtr(_) => false,
            _ => true,
        }
    });
    ret
}

fn check_inherits(code: &str, name: &str, parent_name: &str) -> Result<(), Box<Error>> {
    let idl = parse_string(code)?;
    let mut visitor = InterfaceVisitor::new(name.to_string());
    visitor.visit(&idl);
    let inherits = visitor.get_inherits();

    println!("inherits: {:?}, parent_name: {:?}", inherits, parent_name);

    if inherits == parent_name {
        return Ok(());
    }
    Err(boxed::Box::from(WebIdlError::ParentMismatch {
        name: name.to_string(),
        rust_parent: parent_name.to_string(),
        webidl_parent: inherits.to_string(),
    }))
}

fn check_webidl(name: &str, parent_name: Option<&str>) -> Result<(), Box<Error>> {
    let path = get_webidl_path(&name)?;
    println!("struct_webidl_path: {:?}", &path);

    if let Some(parent) = parent_name {
        let code = fs::read_to_string(path)?;
        return check_inherits(&code, &name, parent);
    }

    Ok(())
}

impl LintPass for WebIdlPass {
    fn name(&self) -> &'static str {
        "ServoWebIDLPass"
    }

    fn get_lints(&self) -> LintArray {
        lint_array!(WEBIDL_INHERIT_CORRECT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WebIdlPass {
    fn check_struct_def(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        def: &'tcx hir::VariantData,
        n: ast::Name,
        _gen: &'tcx hir::Generics,
        id: HirId,
    ) {
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(id);
        if !is_webidl_ty(cx, cx.tcx.type_of(def_id)) {
            return;
        }

        let item = match cx.tcx.hir().get_by_hir_id(id) {
            hir::Node::Item(item) => item,
            _ => cx
                .tcx
                .hir()
                .expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)),
        };

        let struct_name = n.to_string();
        println!("struct_name: {:?}", struct_name);

        let ty: String;
        let mut parent_name: Option<&str> = None;
        for ref field in def.fields() {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id);
            ty = cx.tcx.type_of(def_id).to_string();
            let name = get_ty_name(&ty);
            parent_name = Some(name);

            // Only first field is relevant.
            break;
        }

        match check_webidl(&struct_name, parent_name) {
            Ok(()) => {},
            Err(e) => {
                let description = format!("{}", e);
                cx.span_lint(WEBIDL_INHERIT_CORRECT, item.ident.span, &description)
            },
        };
    }
}

struct InterfaceVisitor {
    name: String,
    inherits: String,
}

impl InterfaceVisitor {
    pub fn new(name: String) -> Self {
        InterfaceVisitor {
            name: name,
            inherits: String::new(),
        }
    }

    pub fn get_inherits(&self) -> &String {
        &self.inherits
    }
}

impl<'ast> ImmutableVisitor<'ast> for InterfaceVisitor {
    fn visit_callback_interface(&mut self, callback_interface: &'ast CallbackInterface) {
        if callback_interface.name == self.name {
            if let Some(ref inherit) = callback_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }

    fn visit_non_partial_interface(&mut self, non_partial_interface: &'ast NonPartialInterface) {
        if non_partial_interface.name == self.name {
            if let Some(ref inherit) = non_partial_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }
}
<commit_msg>Allow Reflector as a parent and special case PaintRenderingContext2D.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use rustc::hir::{self, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use std::boxed;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io;
use std::path;
use syntax::ast;
use webidl::ast::*;
use webidl::visitor::*;
use webidl::*;

declare_lint!(
    WEBIDL_INHERIT_CORRECT,
    Deny,
    "Warn and report usage of incorrect webidl inheritance"
);

pub struct WebIdlPass;

#[derive(Clone, Debug)]
pub enum WebIdlError {
    ParentMismatch {
        name: String,
        rust_parent: String,
        webidl_parent: String,
    },
}

impl fmt::Display for WebIdlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            WebIdlError::ParentMismatch {
                name,
                rust_parent,
                webidl_parent,
            } => {
                return write!(f, "webidl-rust inheritance mismatch, rust: {:?}, rust parent: {:?}, webidl parent: {:?}",
                    &name, &rust_parent, &webidl_parent);
            },
        }
    }
}

impl Error for WebIdlError {
    fn description(&self) -> &str {
        "WebIdlError"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl WebIdlPass {
    pub fn new() -> WebIdlPass {
        WebIdlPass
    }
}

fn get_ty_name(ty: &str) -> &str {
    if let Some(i) = ty.rfind(':') {
        &ty[i + 1..]
    } else {
        ty
    }
}

fn get_webidl_path(struct_name: &str) -> io::Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    dir.push("components/script/dom/webidls/");
    dir.push(format!("{}.webidl", struct_name));

    Ok(dir)
}

fn is_webidl_ty(cx: &LateContext, ty: &ty::TyS) -> bool {
    let mut ret = false;
    ty.maybe_walk(|t| {
        match t.sty {
            ty::Adt(did, _substs) => {
                if cx.tcx.has_attr(did.did, "webidl") {
                    ret = true;
                }
                false
            },
            ty::Ref(..) => false,    // don't recurse down &ptrs
            ty::RawPtr(..) => false, // don't recurse down *ptrs
            ty::FnDef(..) | ty::FnPtr(_) => false,
            _ => true,
        }
    });
    ret
}

fn check_inherits(code: &str, name: &str, parent_name: &str) -> Result<(), Box<Error>> {
    let idl = parse_string(code)?;
    let mut visitor = InterfaceVisitor::new(name.to_string());
    visitor.visit(&idl);
    let inherits = visitor.get_inherits();

    println!("inherits: {:?}, parent_name: {:?}", inherits, parent_name);

    if inherits == parent_name {
        return Ok(());
    }

    // If there is no parent, first field must be of type Reflector.
    if inherits == "" && parent_name == "Reflector" {
        return Ok(());
    }

    if inherits == "" &&
        name == "PaintRenderingContext2D" &&
        parent_name == "CanvasRenderingContext2D"
    {
        // PaintRenderingContext2D embeds a CanvasRenderingContext2D
        // instead of a Reflector as an optimization,
        // but this is fine since CanvasRenderingContext2D
        // also has a reflector
        return Ok(());
    }

    Err(boxed::Box::from(WebIdlError::ParentMismatch {
        name: name.to_string(),
        rust_parent: parent_name.to_string(),
        webidl_parent: inherits.to_string(),
    }))
}

fn check_webidl(name: &str, parent_name: Option<&str>) -> Result<(), Box<Error>> {
    let path = get_webidl_path(&name)?;
    println!("struct_webidl_path: {:?}", &path);

    if let Some(parent) = parent_name {
        let code = fs::read_to_string(path)?;
        return check_inherits(&code, &name, parent);
    }

    Ok(())
}

impl LintPass for WebIdlPass {
    fn name(&self) -> &'static str {
        "ServoWebIDLPass"
    }

    fn get_lints(&self) -> LintArray {
        lint_array!(WEBIDL_INHERIT_CORRECT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WebIdlPass {
    fn check_struct_def(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        def: &'tcx hir::VariantData,
        n: ast::Name,
        _gen: &'tcx hir::Generics,
        id: HirId,
    ) {
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(id);
        if !is_webidl_ty(cx, cx.tcx.type_of(def_id)) {
            return;
        }

        let item = match cx.tcx.hir().get_by_hir_id(id) {
            hir::Node::Item(item) => item,
            _ => cx
                .tcx
                .hir()
                .expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)),
        };

        let struct_name = n.to_string();
        println!("struct_name: {:?}", struct_name);

        let ty: String;
        let mut parent_name: Option<&str> = None;
        for ref field in def.fields() {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id);
            ty = cx.tcx.type_of(def_id).to_string();
            let name = get_ty_name(&ty);
            parent_name = Some(name);

            // Only first field is relevant.
            break;
        }

        match check_webidl(&struct_name, parent_name) {
            Ok(()) => {},
            Err(e) => {
                let description = format!("{}", e);
                cx.span_lint(WEBIDL_INHERIT_CORRECT, item.ident.span, &description)
            },
        };
    }
}

struct InterfaceVisitor {
    name: String,
    inherits: String,
}

impl InterfaceVisitor {
    pub fn new(name: String) -> Self {
        InterfaceVisitor {
            name: name,
            inherits: String::new(),
        }
    }

    pub fn get_inherits(&self) -> &String {
        &self.inherits
    }
}

impl<'ast> ImmutableVisitor<'ast> for InterfaceVisitor {
    fn visit_callback_interface(&mut self, callback_interface: &'ast CallbackInterface) {
        if callback_interface.name == self.name {
            if let Some(ref inherit) = callback_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }

    fn visit_non_partial_interface(&mut self, non_partial_interface: &'ast NonPartialInterface) {
        if non_partial_interface.name == self.name {
            if let Some(ref inherit) = non_partial_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }
}
<|endoftext|>