<commit_before>/* diosix debug console output code
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

/* to avoid warnings about super::hardware when qemuprint is active */
#![allow(unused_imports)]

use super::error::Cause;
use core::fmt;
use super::lock::Mutex;
use alloc::string::String;
use super::hardware;

lazy_static!
{
    pub static ref DEBUG_LOCK: Mutex<bool> = Mutex::new(false);
    static ref DEBUG_QUEUE: Mutex<String> = Mutex::new(String::new());
}

/* top level debug macros */
/* useful messages */
#[macro_export]
macro_rules! hvlog
{
    ($fmt:expr) => (hvprintln!("[+] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[+] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* bad news: bug detection, failures, etc. */
#[macro_export]
macro_rules! hvalert
{
    ($fmt:expr) => (hvprintln!("[!] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[!] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* only output if debug build is enabled */
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! hvdebug
{
    ($fmt:expr) => (hvprintln!("[?] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[?] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* silence debug if disabled */
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! hvdebug
{
    ($fmt:expr) => ({});
    ($fmt:expr, $($arg:tt)*) => ({});
}

/* don't include any metadata nor add a newline */
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! hvdebugraw
{
    ($fmt:expr) => (hvprint!("{}", $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprint!(concat!($fmt), $($arg)*));
}

/* silence debug if disabled */
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! hvdebugraw
{
    ($fmt:expr) => ({});
    ($fmt:expr, $($arg:tt)*) => ({});
}

/* low-level macros for hypervisor-only hvprintln and hvprint debug output routines */
macro_rules! hvprintln
{
    ($fmt:expr) => (hvprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (hvprint!(concat!($fmt, "\n"), $($arg)*));
}

macro_rules! hvprint
{
    ($($arg:tt)*) =>
    ({
        use core::fmt::Write;
        {
            let mut hvprint_lock = $crate::debug::DEBUG_LOCK.lock();
            *hvprint_lock = true;

            unsafe { $crate::debug::CONSOLE.write_fmt(format_args!($($arg)*)).unwrap(); }
        }
    });
}

macro_rules! debughousekeeper
{
    () => ($crate::debug::drain_queue());
}

/* create a generic debug console writer */
pub struct ConsoleWriter;
pub static mut CONSOLE: ConsoleWriter = ConsoleWriter {};

impl fmt::Write for ConsoleWriter
{
    #[cfg(not(feature = "qemuprint"))]
    fn write_str(&mut self, s: &str) -> core::fmt::Result
    {
        DEBUG_QUEUE.lock().push_str(s);
        Ok(())
    }

    #[cfg(feature = "qemuprint")]
    fn write_str(&mut self, s: &str) -> core::fmt::Result
    {
        /* force debug output to Qemu's serial port. useful for early debugging */
        for c in s.as_bytes()
        {
            /* FIXME: hardwired to the RISC-V Qemu serial port */
            unsafe { *(0x10000000 as *mut u8) = *c };
        }
        Ok(())
    }
}

/* attempt to empty queue out to the device-tree-defined debug port */
#[cfg(not(feature = "qemuprint"))]
pub fn drain_queue()
{
    /* avoid blocking if we can't write at this time */
    if DEBUG_LOCK.is_locked() == false
    {
        let debug_lock = DEBUG_LOCK.lock();
        let mut debug_queue = DEBUG_QUEUE.lock();

        if hardware::write_debug_string(&debug_queue) == true
        {
            debug_queue.clear();
        }

        drop(debug_queue);
        drop(debug_lock);
    }
}

#[cfg(feature = "qemuprint")]
pub fn drain_queue() { }<commit_msg>Use named mutexes Avoid needless drop()s<commit_after>/* diosix debug console output code
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

/* to avoid warnings about super::hardware when qemuprint is active */
#![allow(unused_imports)]

use super::error::Cause;
use core::fmt;
use super::lock::Mutex;
use alloc::string::String;
use super::hardware;

lazy_static!
{
    pub static ref DEBUG_LOCK: Mutex<bool> = Mutex::new("debug output", false);
    static ref DEBUG_QUEUE: Mutex<String> = Mutex::new("debug queue", String::new());
}

/* top level debug macros */
/* useful messages */
#[macro_export]
macro_rules! hvlog
{
    ($fmt:expr) => (hvprintln!("[+] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[+] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* bad news: bug detection, failures, etc. */
#[macro_export]
macro_rules! hvalert
{
    ($fmt:expr) => (hvprintln!("[!] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[!] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* only output if debug build is enabled */
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! hvdebug
{
    ($fmt:expr) => (hvprintln!("[?] CPU {}: {}", $crate::pcore::PhysicalCore::get_id(), $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprintln!(concat!("[?] CPU {}: ", $fmt), $crate::pcore::PhysicalCore::get_id(), $($arg)*));
}

/* silence debug if disabled */
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! hvdebug
{
    ($fmt:expr) => ({});
    ($fmt:expr, $($arg:tt)*) => ({});
}

/* don't include any metadata nor add a newline */
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! hvdebugraw
{
    ($fmt:expr) => (hvprint!("{}", $fmt));
    ($fmt:expr, $($arg:tt)*) => (hvprint!(concat!($fmt), $($arg)*));
}

/* silence debug if disabled */
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! hvdebugraw
{
    ($fmt:expr) => ({});
    ($fmt:expr, $($arg:tt)*) => ({});
}

/* low-level macros for hypervisor-only hvprintln and hvprint debug output routines */
macro_rules! hvprintln
{
    ($fmt:expr) => (hvprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (hvprint!(concat!($fmt, "\n"), $($arg)*));
}

macro_rules! hvprint
{
    ($($arg:tt)*) =>
    ({
        use core::fmt::Write;
        {
            let mut hvprint_lock = $crate::debug::DEBUG_LOCK.lock();
            *hvprint_lock = true;

            unsafe { $crate::debug::CONSOLE.write_fmt(format_args!($($arg)*)).unwrap(); }
        }
    });
}

macro_rules! debughousekeeper
{
    () => ($crate::debug::drain_queue());
}

/* create a generic debug console writer */
pub struct ConsoleWriter;
pub static mut CONSOLE: ConsoleWriter = ConsoleWriter {};

impl fmt::Write for ConsoleWriter
{
    #[cfg(not(feature = "qemuprint"))]
    fn write_str(&mut self, s: &str) -> core::fmt::Result
    {
        DEBUG_QUEUE.lock().push_str(s);
        Ok(())
    }

    #[cfg(feature = "qemuprint")]
    fn write_str(&mut self, s: &str) -> core::fmt::Result
    {
        /* force debug output to Qemu's serial port. useful for early debugging */
        for c in s.as_bytes()
        {
            /* FIXME: hardwired to the RISC-V Qemu serial port */
            unsafe { *(0x10000000 as *mut u8) = *c };
        }
        Ok(())
    }
}

/* attempt to empty queue out to the device-tree-defined debug port */
#[cfg(not(feature = "qemuprint"))]
pub fn drain_queue()
{
    /* avoid blocking if we can't write at this time */
    if DEBUG_LOCK.is_locked() == false
    {
        let mut debug_lock = DEBUG_LOCK.lock();
        *debug_lock = true;

        let mut debug_queue = DEBUG_QUEUE.lock();
        if hardware::write_debug_string(&debug_queue) == true
        {
            debug_queue.clear();
        }
    }
}

#[cfg(feature = "qemuprint")]
pub fn drain_queue() { }<|endoftext|>


<commit_before>//! A CLI tool for overriding a DICOM file's image with another one.
//!
//! This command line tool takes a base DICOM file
//! and replaces the various DICOM attributes of the image module
//! (including Rows, Columns, PixelData, and others)
//! with those of another file.
//! The new DICOM object is saved to a new file
//! encoded in Explicit VR Little Endian.
use std::path::PathBuf;

use dicom::{
    core::{value::PrimitiveValue, DataElement, VR},
    dictionary_std::tags,
    object::{open_file, FileMetaTableBuilder},
};
use image::GenericImageView;
use snafu::ErrorCompat;
use structopt::StructOpt;

/// Convert and replace a DICOM file's image with another image
#[derive(Debug, StructOpt)]
struct App {
    /// Path to the base DICOM file to read
    dcm_file: PathBuf,
    /// Path to the image file to replace the DICOM file
    img_file: PathBuf,
    /// Path to the output image
    /// (default is to replace input extension with `.new.dcm`)
    #[structopt(short = "o", long = "out")]
    output: Option<PathBuf>,
    /// Print more information about the image and the output file
    #[structopt(short = "v", long = "verbose")]
    verbose: bool,
}

fn report<E: 'static>(err: &E)
where
    E: std::error::Error,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }
}

fn report_backtrace<E: 'static>(err: &E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}

fn report_with_backtrace<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    report(&err);
    report_backtrace(&err);
}

fn main() {
    let App {
        dcm_file,
        img_file,
        output,
        verbose,
    } = App::from_args();

    let output = output.unwrap_or_else(|| {
        let mut path = dcm_file.clone();
        path.set_extension("new.dcm");
        path
    });

    let mut obj = open_file(&dcm_file).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-1);
    });

    let img = image::open(img_file).unwrap_or_else(|e| {
        report(&e);
        std::process::exit(-1);
    });

    let (pi, spp, bits_stored, pixeldata): (&str, u16, u16, Vec<u8>) = match img.color() {
        image::ColorType::L8 => ("MONOCHROME2", 1, 8, img.to_bytes()),
        image::ColorType::L16 => ("MONOCHROME2", 1, 16, img.to_bytes()),
        image::ColorType::Rgb8 => ("RGB", 3, 8, img.to_bytes()),
        image::ColorType::Bgr8 => ("RGB", 3, 8, img.to_rgb8().into_raw()),
        _ => {
            eprintln!("Unsupported image format {:?}", img.color());
            std::process::exit(-2);
        }
    };

    if verbose {
        println!("{}x{} {:?} image", img.width(), img.height(), img.color());
    }

    // override attributes at DICOM object
    obj.put(DataElement::new(
        tags::PHOTOMETRIC_INTERPRETATION,
        VR::CS,
        PrimitiveValue::from(pi),
    ));
    obj.put(DataElement::new(
        tags::SAMPLES_PER_PIXEL,
        VR::US,
        PrimitiveValue::from(spp),
    ));
    obj.put(DataElement::new(
        tags::COLUMNS,
        VR::US,
        PrimitiveValue::from(img.width() as u16),
    ));
    obj.put(DataElement::new(
        tags::ROWS,
        VR::US,
        PrimitiveValue::from(img.height() as u16),
    ));
    obj.put(DataElement::new(
        tags::BITS_ALLOCATED,
        VR::US,
        PrimitiveValue::from(bits_stored),
    ));
    obj.put(DataElement::new(
        tags::BITS_STORED,
        VR::US,
        PrimitiveValue::from(bits_stored),
    ));
    obj.put(DataElement::new(
        tags::HIGH_BIT,
        VR::US,
        PrimitiveValue::from(bits_stored - 1),
    ));

    obj.put(DataElement::new(
        tags::PIXEL_REPRESENTATION,
        VR::US,
        PrimitiveValue::from(0_u16),
    ));

    obj.put(DataElement::new(
        tags::PIXEL_DATA,
        if bits_stored == 8 { VR::OB } else { VR::OW },
        PrimitiveValue::from(pixeldata),
    ));

    let class_uid = obj.meta().media_storage_sop_class_uid.clone();

    let obj = obj.into_inner().with_meta(FileMetaTableBuilder::new()
            .transfer_syntax("1.2.840.10008.1.2.1")
            .media_storage_sop_class_uid(class_uid)
    ).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-3);
    });

    obj.write_to_file(&output).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-4);
    });

    if verbose {
        println!("DICOM file saved to {}", output.display());
    }
}
<commit_msg>[fromimage] extend changes to DICOM object<commit_after>//! A CLI tool for overriding a DICOM file's image with another one.
//!
//! This command line tool takes a base DICOM file
//! and replaces the various DICOM attributes of the [_Image Pixel_ module][1]
//! (such as Rows, Columns, PixelData, ...)
//! with those of another file.
//! The _Presentation LUT Shape_ attribute is set to `IDENTITY`.
//! Other attributes are copied as is.
//!
//! The new DICOM object is saved to a new file,
//! with the same SOP instance UID and SOP class UID as the base file,
//! encoded in Explicit VR Little Endian.
//!
//! [1]: https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.3.html
use std::path::PathBuf;

use dicom::{
    core::{value::PrimitiveValue, DataElement, VR},
    dictionary_std::tags,
    object::{open_file, FileMetaTableBuilder},
};
use image::GenericImageView;
use snafu::ErrorCompat;
use structopt::StructOpt;

/// Convert and replace a DICOM file's image with another image
#[derive(Debug, StructOpt)]
struct App {
    /// Path to the base DICOM file to read
    dcm_file: PathBuf,
    /// Path to the image file to replace the DICOM file
    img_file: PathBuf,
    /// Path to the output image
    /// (default is to replace input extension with `.new.dcm`)
    #[structopt(short = "o", long = "out")]
    output: Option<PathBuf>,
    /// Print more information about the image and the output file
    #[structopt(short = "v", long = "verbose")]
    verbose: bool,
}

fn report<E: 'static>(err: &E)
where
    E: std::error::Error,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }
}

fn report_backtrace<E: 'static>(err: &E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}

fn report_with_backtrace<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    report(&err);
    report_backtrace(&err);
}

fn main() {
    let App {
        dcm_file,
        img_file,
        output,
        verbose,
    } = App::from_args();

    let output = output.unwrap_or_else(|| {
        let mut path = dcm_file.clone();
        path.set_extension("new.dcm");
        path
    });

    let mut obj = open_file(&dcm_file).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-1);
    });

    let img = image::open(img_file).unwrap_or_else(|e| {
        report(&e);
        std::process::exit(-1);
    });

    let (pi, spp, bits_stored, pixeldata): (&str, u16, u16, Vec<u8>) = match img.color() {
        image::ColorType::L8 => ("MONOCHROME2", 1, 8, img.to_bytes()),
        image::ColorType::L16 => ("MONOCHROME2", 1, 16, img.to_bytes()),
        image::ColorType::Rgb8 => ("RGB", 3, 8, img.to_bytes()),
        image::ColorType::Bgr8 => ("RGB", 3, 8, img.to_rgb8().into_raw()),
        _ => {
            eprintln!("Unsupported image format {:?}", img.color());
            std::process::exit(-2);
        }
    };

    if verbose {
        println!("{}x{} {:?} image", img.width(), img.height(), img.color());
    }

    // override attributes at DICOM object
    obj.put(DataElement::new(
        tags::PHOTOMETRIC_INTERPRETATION,
        VR::CS,
        PrimitiveValue::from(pi),
    ));

    obj.put(DataElement::new(
        tags::PRESENTATION_LUT_SHAPE,
        VR::CS,
        PrimitiveValue::from("IDENTITY"),
    ));

    obj.put(DataElement::new(
        tags::SAMPLES_PER_PIXEL,
        VR::US,
        PrimitiveValue::from(spp),
    ));

    if spp > 1 {
        obj.put(DataElement::new(
            tags::PLANAR_CONFIGURATION,
            VR::US,
            PrimitiveValue::from(0_u16),
        ));
    } else {
        obj.remove_element(tags::PLANAR_CONFIGURATION);
    }

    obj.put(DataElement::new(
        tags::COLUMNS,
        VR::US,
        PrimitiveValue::from(img.width() as u16),
    ));
    obj.put(DataElement::new(
        tags::ROWS,
        VR::US,
        PrimitiveValue::from(img.height() as u16),
    ));
    obj.put(DataElement::new(
        tags::BITS_ALLOCATED,
        VR::US,
        PrimitiveValue::from(bits_stored),
    ));
    obj.put(DataElement::new(
        tags::BITS_STORED,
        VR::US,
        PrimitiveValue::from(bits_stored),
    ));
    obj.put(DataElement::new(
        tags::HIGH_BIT,
        VR::US,
        PrimitiveValue::from(bits_stored - 1),
    ));

    obj.put(DataElement::new(
        tags::PIXEL_REPRESENTATION,
        VR::US,
        PrimitiveValue::from(0_u16),
    ));

    for tag in [
        tags::PIXEL_ASPECT_RATIO,
        tags::SMALLEST_IMAGE_PIXEL_VALUE,
        tags::LARGEST_IMAGE_PIXEL_VALUE,
        tags::PIXEL_PADDING_RANGE_LIMIT,
        tags::RED_PALETTE_COLOR_LOOKUP_TABLE_DATA,
        tags::RED_PALETTE_COLOR_LOOKUP_TABLE_DESCRIPTOR,
        tags::GREEN_PALETTE_COLOR_LOOKUP_TABLE_DATA,
        tags::GREEN_PALETTE_COLOR_LOOKUP_TABLE_DESCRIPTOR,
        tags::BLUE_PALETTE_COLOR_LOOKUP_TABLE_DATA,
        tags::BLUE_PALETTE_COLOR_LOOKUP_TABLE_DESCRIPTOR,
        tags::ICC_PROFILE,
        tags::COLOR_SPACE,
        tags::PIXEL_DATA_PROVIDER_URL,
        tags::EXTENDED_OFFSET_TABLE,
        tags::EXTENDED_OFFSET_TABLE_LENGTHS,
    ] {
        obj.remove_element(tag);
    }

    obj.put(DataElement::new(
        tags::PIXEL_DATA,
        if bits_stored == 8 { VR::OB } else { VR::OW },
        PrimitiveValue::from(pixeldata),
    ));

    let class_uid = obj.meta().media_storage_sop_class_uid.clone();

    let obj = obj.into_inner().with_meta(FileMetaTableBuilder::new()
            .transfer_syntax("1.2.840.10008.1.2.1")
            .media_storage_sop_class_uid(class_uid)
    ).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-3);
    });

    obj.write_to_file(&output).unwrap_or_else(|e| {
        report_with_backtrace(e);
        std::process::exit(-4);
    });

    if verbose {
        println!("DICOM file saved to {}", output.display());
    }
}
<|endoftext|>


<commit_before>use super::operation::DeleteOperation;
use std::sync::{Arc, RwLock};
use std::mem;
use std::ops::DerefMut;

// The DeleteQueue is similar in conceptually to a multiple
// consumer single producer broadcast channel.
//
// All consumer will receive all messages.
//
// Consumer of the delete queue are holding a `DeleteCursor`,
// which points to a specific place of the `DeleteQueue`.
//
// New consumer can be created in two ways
// - calling `delete_queue.cursor()` returns a cursor, that
//   will include all future delete operation (and no past operations).
// - cloning an existing cursor returns a new cursor, that
//   is at the exact same position, and can now advance independantly
//   from the original cursor.
#[derive(Default)]
struct InnerDeleteQueue {
    writer: Vec<DeleteOperation>,
    last_block: Option<Arc<Block>>,
}

#[derive(Clone, Default)]
pub struct DeleteQueue {
    inner: Arc<RwLock<InnerDeleteQueue>>,
}

impl DeleteQueue {
    // Creates a new delete queue.
    pub fn new() -> DeleteQueue {

        let delete_queue = DeleteQueue { inner: Arc::default() };

        let next_block = NextBlock::from(delete_queue.clone());
        {
            let mut delete_queue_wlock = delete_queue.inner.write().unwrap();
            delete_queue_wlock.last_block = Some(Arc::new(Block {
                                                              operations: Arc::default(),
                                                              next: next_block,
                                                          }));
        }

        delete_queue
    }

    // Creates a new cursor that makes it possible to
    // consume future delete operations.
    //
    // Past delete operations are not accessible.
    pub fn cursor(&self) -> DeleteCursor {
        let last_block = self.inner
            .read()
            .expect("Read lock poisoned when opening delete queue cursor")
            .last_block
            .clone()
            .expect("Failed to unwrap last_block. This should never happen
                as the Option<> is only here to make
                initialization possible");
        let operations_len = last_block.operations.len();
        DeleteCursor {
            block: last_block,
            pos: operations_len,
        }
    }

    // Appends a new delete operations.
    pub fn push(&self, delete_operation: DeleteOperation) {
        self.inner
            .write()
            .expect("Failed to acquire write lock on delete queue writer")
            .writer
            .push(delete_operation);
    }

    // DeleteQueue is a linked list of blocks of
    // delete operations.
    //
    // Writing happens by simply appending to a vec.
    // `.flush()` takes this pending delete operations vec
    // creates a new read-only block from it,
    // and appends it to the linked list.
    //
    // `.flush()` happens when, for instance,
    // a consumer reaches the last read-only operations.
    // It then ask the delete queue if there happen to
    // be some unflushed operations.
    //
    fn flush(&self) -> Option<Arc<Block>> {
        let mut self_wlock = self.inner
            .write()
            .expect("Failed to acquire write lock on delete queue writer");

        let delete_operations;
        {
            let writer: &mut Vec<DeleteOperation> = &mut self_wlock.writer;
            if writer.is_empty() {
                return None;
            }
            delete_operations = mem::replace(writer, vec![]);
        }

        let next_block = NextBlock::from(self.clone());
        {
            self_wlock.last_block = Some(Arc::new(Block {
                                                      operations: Arc::new(delete_operations),
                                                      next: next_block,
                                                  }));
        }
        self_wlock.last_block.clone()
    }
}

enum InnerNextBlock {
    Writer(DeleteQueue),
    Closed(Arc<Block>),
}

struct NextBlock(RwLock<InnerNextBlock>);

impl From<DeleteQueue> for NextBlock {
    fn from(delete_queue: DeleteQueue) -> NextBlock {
        NextBlock(RwLock::new(InnerNextBlock::Writer(delete_queue)))
    }
}

impl NextBlock {
    fn next_block(&self) -> Option<Arc<Block>> {
        {
            let next_read_lock = self.0
                .read()
                .expect("Failed to acquire write lock in delete queue");
            match *next_read_lock {
                InnerNextBlock::Closed(ref block) => {
                    return Some(block.clone());
                }
                _ => {}
            }
        }
        let next_block;
        {
            let mut next_write_lock = self.0
                .write()
                .expect("Failed to acquire write lock in delete queue");
            match *next_write_lock {
                InnerNextBlock::Closed(ref block) => {
                    return Some(block.clone());
                }
                InnerNextBlock::Writer(ref writer) => {
                    match writer.flush() {
                        Some(flushed_next_block) => {
                            next_block = flushed_next_block;
                        }
                        None => {
                            return None;
                        }
                    }
                }
            }
            *next_write_lock.deref_mut() = InnerNextBlock::Closed(next_block.clone());
            Some(next_block)
        }
    }
}

struct Block {
    operations: Arc<Vec<DeleteOperation>>,
    next: NextBlock,
}

#[derive(Clone)]
pub struct DeleteCursor {
    block: Arc<Block>,
    pos: usize,
}

impl DeleteCursor {
    /// Skips operations and position it so that
    /// - either all of the delete operation currently in the
    ///   queue are consume and the next get will return None.
    /// - the next get will return the first operation with an
    /// `opstamp >= target_opstamp`.
    pub fn skip_to(&mut self, target_opstamp: u64) {
        // TODO Can be optimize as we work with block.
        loop {
            if let Some(operation) = self.get() {
                if operation.opstamp >= target_opstamp {
                    break;
                }
            } else {
                break;
            }
            self.advance();
        }
    }

    /// If the current block has been entirely
    /// consumed, try to load the next one.
    ///
    /// Return `true`, if after this attempt,
    /// the cursor is on a block that has not
    /// been entirely consumed.
    /// Return `false`, if we have reached the end of the queue.
    fn load_block_if_required(&mut self) -> bool {
        if self.pos >= self.block.operations.len() {
            // we have consumed our operations entirely.
            // let's ask our writer if he has more for us.
            // self.go_next_block();
            match self.block.next.next_block() {
                Some(block) => {
                    self.block = block;
                    self.pos = 0;
                    true
                }
                None => false,
            }
        } else {
            true
        }
    }

    /// Advance to the next delete operation.
    /// Returns true iff there is such an operation.
    pub fn advance(&mut self) -> bool {
        if self.load_block_if_required() {
            self.pos += 1;
            true
        } else {
            false
        }
    }

    /// Get the current delete operation.
    /// Calling `.get` does not advance the cursor.
    pub fn get(&mut self) -> Option<&DeleteOperation> {
        if self.load_block_if_required() {
            Some(&self.block.operations[self.pos])
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{DeleteQueue, DeleteOperation};
    use schema::{Term, Field};

    #[test]
    fn test_deletequeue() {
        let delete_queue = DeleteQueue::new();

        let make_op = |i: usize| {
            let field = Field(1u32);
            DeleteOperation {
                opstamp: i as u64,
                term: Term::from_field_u64(field, i as u64),
            }
        };

        delete_queue.push(make_op(1));
        delete_queue.push(make_op(2));

        let snapshot = delete_queue.cursor();
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.get().unwrap().opstamp, 1);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 2);
            operations_it.advance();
            assert!(operations_it.get().is_none());
            operations_it.advance();

            let mut snapshot2 = delete_queue.cursor();
            assert!(snapshot2.get().is_none());
            delete_queue.push(make_op(3));
            assert_eq!(snapshot2.get().unwrap().opstamp, 3);
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            operations_it.advance();
            assert!(operations_it.get().is_none());
            operations_it.advance();
        }
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.get().unwrap().opstamp, 1);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 2);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            operations_it.advance();
            assert!(operations_it.get().is_none());
        }

    }
}
<commit_msg>clippy: fix single_match warnings<commit_after>use super::operation::DeleteOperation;
use std::sync::{Arc, RwLock};
use std::mem;
use std::ops::DerefMut;

// The DeleteQueue is similar in conceptually to a multiple
// consumer single producer broadcast channel.
//
// All consumer will receive all messages.
//
// Consumer of the delete queue are holding a `DeleteCursor`,
// which points to a specific place of the `DeleteQueue`.
//
// New consumer can be created in two ways
// - calling `delete_queue.cursor()` returns a cursor, that
//   will include all future delete operation (and no past operations).
// - cloning an existing cursor returns a new cursor, that
//   is at the exact same position, and can now advance independantly
//   from the original cursor.
#[derive(Default)]
struct InnerDeleteQueue {
    writer: Vec<DeleteOperation>,
    last_block: Option<Arc<Block>>,
}

#[derive(Clone, Default)]
pub struct DeleteQueue {
    inner: Arc<RwLock<InnerDeleteQueue>>,
}

impl DeleteQueue {
    // Creates a new delete queue.
    pub fn new() -> DeleteQueue {

        let delete_queue = DeleteQueue { inner: Arc::default() };

        let next_block = NextBlock::from(delete_queue.clone());
        {
            let mut delete_queue_wlock = delete_queue.inner.write().unwrap();
            delete_queue_wlock.last_block = Some(Arc::new(Block {
                                                              operations: Arc::default(),
                                                              next: next_block,
                                                          }));
        }

        delete_queue
    }

    // Creates a new cursor that makes it possible to
    // consume future delete operations.
    //
    // Past delete operations are not accessible.
    pub fn cursor(&self) -> DeleteCursor {
        let last_block = self.inner
            .read()
            .expect("Read lock poisoned when opening delete queue cursor")
            .last_block
            .clone()
            .expect("Failed to unwrap last_block. This should never happen
                as the Option<> is only here to make
                initialization possible");
        let operations_len = last_block.operations.len();
        DeleteCursor {
            block: last_block,
            pos: operations_len,
        }
    }

    // Appends a new delete operations.
    pub fn push(&self, delete_operation: DeleteOperation) {
        self.inner
            .write()
            .expect("Failed to acquire write lock on delete queue writer")
            .writer
            .push(delete_operation);
    }

    // DeleteQueue is a linked list of blocks of
    // delete operations.
    //
    // Writing happens by simply appending to a vec.
    // `.flush()` takes this pending delete operations vec
    // creates a new read-only block from it,
    // and appends it to the linked list.
    //
    // `.flush()` happens when, for instance,
    // a consumer reaches the last read-only operations.
    // It then ask the delete queue if there happen to
    // be some unflushed operations.
    //
    fn flush(&self) -> Option<Arc<Block>> {
        let mut self_wlock = self.inner
            .write()
            .expect("Failed to acquire write lock on delete queue writer");

        let delete_operations;
        {
            let writer: &mut Vec<DeleteOperation> = &mut self_wlock.writer;
            if writer.is_empty() {
                return None;
            }
            delete_operations = mem::replace(writer, vec![]);
        }

        let next_block = NextBlock::from(self.clone());
        {
            self_wlock.last_block = Some(Arc::new(Block {
                                                      operations: Arc::new(delete_operations),
                                                      next: next_block,
                                                  }));
        }
        self_wlock.last_block.clone()
    }
}

enum InnerNextBlock {
    Writer(DeleteQueue),
    Closed(Arc<Block>),
}

struct NextBlock(RwLock<InnerNextBlock>);

impl From<DeleteQueue> for NextBlock {
    fn from(delete_queue: DeleteQueue) -> NextBlock {
        NextBlock(RwLock::new(InnerNextBlock::Writer(delete_queue)))
    }
}

impl NextBlock {
    fn next_block(&self) -> Option<Arc<Block>> {
        {
            let next_read_lock = self.0
                .read()
                .expect("Failed to acquire write lock in delete queue");
            if let InnerNextBlock::Closed(ref block) = *next_read_lock {
                return Some(block.clone());
            }
        }
        let next_block;
        {
            let mut next_write_lock = self.0
                .write()
                .expect("Failed to acquire write lock in delete queue");
            match *next_write_lock {
                InnerNextBlock::Closed(ref block) => {
                    return Some(block.clone());
                }
                InnerNextBlock::Writer(ref writer) => {
                    match writer.flush() {
                        Some(flushed_next_block) => {
                            next_block = flushed_next_block;
                        }
                        None => {
                            return None;
                        }
                    }
                }
            }
            *next_write_lock.deref_mut() = InnerNextBlock::Closed(next_block.clone());
            Some(next_block)
        }
    }
}

struct Block {
    operations: Arc<Vec<DeleteOperation>>,
    next: NextBlock,
}

#[derive(Clone)]
pub struct DeleteCursor {
    block: Arc<Block>,
    pos: usize,
}

impl DeleteCursor {
    /// Skips operations and position it so that
    /// - either all of the delete operation currently in the
    ///   queue are consume and the next get will return None.
    /// - the next get will return the first operation with an
    /// `opstamp >= target_opstamp`.
    pub fn skip_to(&mut self, target_opstamp: u64) {
        // TODO Can be optimize as we work with block.
        loop {
            if let Some(operation) = self.get() {
                if operation.opstamp >= target_opstamp {
                    break;
                }
            } else {
                break;
            }
            self.advance();
        }
    }

    /// If the current block has been entirely
    /// consumed, try to load the next one.
    ///
    /// Return `true`, if after this attempt,
    /// the cursor is on a block that has not
    /// been entirely consumed.
    /// Return `false`, if we have reached the end of the queue.
    fn load_block_if_required(&mut self) -> bool {
        if self.pos >= self.block.operations.len() {
            // we have consumed our operations entirely.
            // let's ask our writer if he has more for us.
            // self.go_next_block();
            match self.block.next.next_block() {
                Some(block) => {
                    self.block = block;
                    self.pos = 0;
                    true
                }
                None => false,
            }
        } else {
            true
        }
    }

    /// Advance to the next delete operation.
    /// Returns true iff there is such an operation.
    pub fn advance(&mut self) -> bool {
        if self.load_block_if_required() {
            self.pos += 1;
            true
        } else {
            false
        }
    }

    /// Get the current delete operation.
    /// Calling `.get` does not advance the cursor.
    pub fn get(&mut self) -> Option<&DeleteOperation> {
        if self.load_block_if_required() {
            Some(&self.block.operations[self.pos])
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{DeleteQueue, DeleteOperation};
    use schema::{Term, Field};

    #[test]
    fn test_deletequeue() {
        let delete_queue = DeleteQueue::new();

        let make_op = |i: usize| {
            let field = Field(1u32);
            DeleteOperation {
                opstamp: i as u64,
                term: Term::from_field_u64(field, i as u64),
            }
        };

        delete_queue.push(make_op(1));
        delete_queue.push(make_op(2));

        let snapshot = delete_queue.cursor();
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.get().unwrap().opstamp, 1);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 2);
            operations_it.advance();
            assert!(operations_it.get().is_none());
            operations_it.advance();

            let mut snapshot2 = delete_queue.cursor();
            assert!(snapshot2.get().is_none());
            delete_queue.push(make_op(3));
            assert_eq!(snapshot2.get().unwrap().opstamp, 3);
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            operations_it.advance();
            assert!(operations_it.get().is_none());
            operations_it.advance();
        }
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.get().unwrap().opstamp, 1);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 2);
            operations_it.advance();
            assert_eq!(operations_it.get().unwrap().opstamp, 3);
            operations_it.advance();
            assert!(operations_it.get().is_none());
        }

    }
}
<|endoftext|>


<commit_before>extern crate rand;
use std::cmp::Ordering;
use rand::Rng;
use std::vec;

fn binarySearch(dest : i32, data : &[i32], base : usize) -> isize {
    let dataLen : usize = data.len() as usize;
    //println!("");
    //println!("base: {}", base);
    //println!("datalen: {}", dataLen);

    if (dataLen == 0)
    {
        -1
    }
    else
    {
        let middle : usize = dataLen / 2;
        //println!("middle: {}", middle);
        match dest.cmp(&data[middle]) {
            Ordering::Less => {
                //println!("next: {} {}", base, base+middle);
                binarySearch(dest, &data[0..middle], base)
            },
            Ordering::Equal => {
                (middle + base) as isize
            },
            Ordering::Greater => {
                //println!("next: {} {}", base+middle+1, dataLen);
                binarySearch(dest, &data[middle+1..dataLen], base + middle + 1)
            },
        }
    }
}

fn main() {
    for x in 1..10000 {
        let count = rand::thread_rng().gen_range(10, 100);
        let mut data : Vec<i32> = Vec::new();
        for i in 1..count {
            data.push(i as i32);
        }
        let targetIndex : isize = rand::thread_rng().gen_range(0, count - 1);

        let searchResult = binarySearch(data[targetIndex as usize], &data, 0);

        if (searchResult != targetIndex) {
            println!("Error!");
        }
    }
}
<commit_msg>some small fix. like number range, performance and so on<commit_after>extern crate rand;
use std::cmp::Ordering;
use rand::Rng;
use std::vec;

fn binarySearch(dest : i32, data : &[i32], base : usize) -> isize {
    let dataLen : usize = data.len() as usize;
    //println!("");
    //println!("base: {}", base);
    //println!("datalen: {}", dataLen);

    if (dataLen == 0)
    {
        -1
    }
    else
    {
        let middle : usize = dataLen / 2;
        //println!("middle: {}", middle);
        match dest.cmp(&data[middle]) {
            Ordering::Less => {
                //println!("next: {} {}", base, base+middle);
                binarySearch(dest, &data[0..middle], base)
            },
            Ordering::Equal => {
                (middle + base) as isize
            },
            Ordering::Greater => {
                //println!("next: {} {}", base+middle+1, dataLen);
                binarySearch(dest, &data[middle+1..dataLen], base + middle + 1)
            },
        }
    }
}

fn main() {
    let mut rndGen = rand::thread_rng();
    for x in 1..10000 {
        let count = rndGen.gen_range(10, 500);
        let mut data : Vec<i32> = Vec::with_capacity(count as usize);
        for i in 0..count {
            data.push(i as i32);
        }
        let targetIndex : isize = rndGen.gen_range(0, count);

        let searchResult = binarySearch(data[targetIndex as usize], &data, 0);

        if (searchResult != targetIndex) {
            println!("Error!");
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use db;
use rustc_serialize;
use rustc_serialize::{Encodable};
use rustc_serialize::json::{self, Encoder};
use rustc_serialize::json::Json;
use elephant;

pub fn json_loader_elephant(conn: &Connection, pk_file: &i32, json :&rustc_serialize::json::Json) {
    let mut pk_job :i32 = 0;
    let mut pk_provider :i32 = 0;
    let mut pk_job_depend :i32 = 0;
    let mut pk_variable_name :i32 = 0;
    let mut order_job_depend :i32 = 0;

    if json.is_object() {
        let sssbill = json.as_object();
        for &movie in &sssbill {

            if movie.contains_key("name") {
                let resulkt = movie.get("name");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_string() {
                    let str_item = itemfdsd.as_string();
                    let foo = str_item.unwrap();
                    pk_job = elephant::elephant_job_pk(conn, &pk_file, &foo);
                    //println!("pk_job::name={}", pk_job);
                }
            }
            else
            {
                continue;
            }
            if movie.contains_key("provides") {
                let resulkt = movie.get("provides");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_array() {
                    //println!("is_arrayxxxxx");

                    let ssd = itemfdsd.as_array();
                    let sdf = ssd.unwrap();
                    let itemfdsd = sdf.iter();
                    for elem in itemfdsd{
                        if elem.is_string() {
                            let sss = elem.as_string();
                            let foo = sss.unwrap();
                            pk_provider = elephant::elephant_provider_pk(conn, &foo);
                            //println!("elephant_provider_pk={}", foo);
                            let sq_order = 1;
                            pk_provider = elephant::elephant_job_depend_pk(conn, pk_job, pk_provider, sq_order);
                            //println!("pk_provider::name={}", pk_provider);
                        }
                    }
                }
            }
            if movie.contains_key("depends") {
                //println!("depends");
                let resulkt = movie.get("provides");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_array() {
                    let ssd = itemfdsd.as_array();
                    let sdf = ssd.unwrap();
                    let george = sdf.len();
                    let itemfdsd = sdf.iter();
                    for elem in itemfdsd{

                        if elem.is_string() {
                                    let sss = elem.as_string();
                                    let foo = sss.unwrap();
                                    pk_provider = elephant::elephant_provider_pk(conn, &foo);

                                    order_job_depend += 10;
                                    pk_provider = elephant::elephant_provider_pk(conn, &foo);
                                    pk_job_depend = elephant::elephant_job_depend_pk(conn, pk_job, pk_provider, order_job_depend);
                                    //println!("pk_provider::name={}", pk_provider);

                        }
                    }
                }
            }
            if movie.contains_key("variables") {
                println!("variables");
                let resulkt = movie.get("variables");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_object() {
                    let objVariables = itemfdsd.as_object();
                    for &iVariables in &objVariables {
                        if iVariables.contains_key("require_keys") {
                            let resulkdt = movie.get("require_keys");
                            let sdf = resulkt.unwrap();
                            let mut itemfdsd = sdf.clone();
                            if itemfdsd.is_array() {
                                let ssd = itemfdsd.as_array();
                                let sdf = ssd.unwrap();
                                let george = sdf.len();
                                let itemfdsd = sdf.iter();
                                for elem in itemfdsd{
                                    if elem.is_string() {
                                        let sss = elem.as_string();
                                        let foo = sss.unwrap();
                                        let name = String::from(foo);
                                        pk_variable_name = elephant::elephant_variable_pk(conn, &name);
                                        elephant::elephant_job_require_variables(conn, &pk_job, &pk_variable_name);
                                    }
                                }
                            }
                        }
                        if iVariables.contains_key("provides_keys") {
                            let resulkdt = movie.get("provides_keys");
                            let sdf = resulkt.unwrap();
                            let mut itemfdsd = sdf.clone();
                            if itemfdsd.is_array() {
                                let ssd = itemfdsd.as_array();
                                let sdf = ssd.unwrap();
                                let george = sdf.len();
                                let itemfdsd = sdf.iter();
                                for elem in itemfdsd{
                                    if elem.is_string() {
                                        let sss = elem.as_string();
                                        let foo = sss.unwrap();
                                        let name = String::from(foo);
                                        pk_variable_name = elephant::elephant_variable_pk(conn, &name);
                                        elephant::elephant_job_provide_variables(conn, pk_job, pk_variable_name);
                                    }
                                }
                            }
                        }
                        if iVariables.contains_key("require_values") {
                            let resulkdtvv = iVariables.get("require_values");
                            let sdfc = resulkdtvv.unwrap();
                            let mut itemfdsdff = sdfc.clone();

                            if itemfdsdff.is_object(){
                                let sssbill = itemfdsdff.as_object();
                                for &dict_key in &sssbill {
                                    //let value_deep = sssbill.get(&dict_key);
                                    if dict_key.contains_key("provides_keys") {

                                        println!("require_values:dict_key:{:?}", dict_key);
                                    }
                                    if iVariables.contains_key("provides_keys") {
                                        println!("require_values:dict_key:{:?}", dict_key);
                                    }
                                    if iVariables.contains_key("provides_keys") {
                                        println!("require_values:dict_key:{:?}", dict_key);
                                    }
                                    if iVariables.contains_key("provides_keys") {
                                        println!("require_values:dict_key:{:?}", dict_key);
                                    }
                                }
                            }
                        }
                    }

                }
            }
        }
    }

    let found = json.find_path(&["variables"]);
    if found != None {

        for item in found {

            let bill = item.find_path(&["require_values"]);

            if bill != None {
                for item2 in bill {
                    if item2.is_array(){
                        println!("is_array:{:?}", item2);
                    }
                    if item2.is_object() {
                        println!("pk_variable_name:{:?}", pk_variable_name);
                        let object = item2.as_object();

                        println!("is_object:{:?}", object);

                    }

                }
            }
        }

    }
}

<commit_msg>Use referance ratehr than instances with elephant_job_depend_pk and increase pasre.<commit_after>use rusqlite::Connection;
use db;
use rustc_serialize;
use rustc_serialize::{Encodable};
use rustc_serialize::json::{self, Encoder};
use rustc_serialize::json::Json;
use elephant;

pub fn json_loader_elephant(conn: &Connection, pk_file: &i32, json :&rustc_serialize::json::Json) {
    let mut pk_job :i32 = 0;
    let mut pk_provider :i32 = 0;
    let mut pk_job_depend :i32 = 0;
    let mut pk_variable_name :i32 = 0;
    let mut order_job_depend :i32 = 0;

    if json.is_object() {
        let sssbill = json.as_object();
        for &movie in &sssbill {

            if movie.contains_key("name") {
                let resulkt = movie.get("name");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_string() {
                    let str_item = itemfdsd.as_string();
                    let foo = str_item.unwrap();
                    pk_job = elephant::elephant_job_pk(conn, &pk_file, &foo);
                    //println!("pk_job::name={}", pk_job);
                }
            }
            else
            {
                continue;
            }
            if movie.contains_key("provides") {
                let resulkt = movie.get("provides");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_array() {
                    //println!("is_arrayxxxxx");

                    let ssd = itemfdsd.as_array();
                    let sdf = ssd.unwrap();
                    let itemfdsd = sdf.iter();
                    for elem in itemfdsd{
                        if elem.is_string() {
                            let sss = elem.as_string();
                            let foo = sss.unwrap();
                            pk_provider = elephant::elephant_provider_pk(conn, &foo);
                            //println!("elephant_provider_pk={}", foo);
                            let sq_order = 1;
                            pk_provider = elephant::elephant_job_depend_pk(conn, &pk_job, &pk_provider, &sq_order);
                            //println!("pk_provider::name={}", pk_provider);
                        }
                    }
                }
            }
            if movie.contains_key("depends") {
                //println!("depends");
                let resulkt = movie.get("provides");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_array() {
                    let ssd = itemfdsd.as_array();
                    let sdf = ssd.unwrap();
                    let george = sdf.len();
                    let itemfdsd = sdf.iter();
                    for elem in itemfdsd{

                        if elem.is_string() {
                                    let sss = elem.as_string();
                                    let foo = sss.unwrap();
                                    pk_provider = elephant::elephant_provider_pk(conn, &foo);

                                    order_job_depend += 10;
                                    pk_provider = elephant::elephant_provider_pk(conn, &foo);
                                    pk_job_depend = elephant::elephant_job_depend_pk(conn, &pk_job, &pk_provider, &order_job_depend);
                                    //println!("pk_provider::name={}", pk_provider);

                        }
                    }
                }
            }
            if movie.contains_key("variables") {
                println!("variables");
                let resulkt = movie.get("variables");
                let sdf = resulkt.unwrap();
                let mut itemfdsd = sdf.clone();
                if itemfdsd.is_object() {
                    let objVariables = itemfdsd.as_object();
                    for &iVariables in &objVariables {
                        if iVariables.contains_key("require_keys") {
                            let resulkdt = movie.get("require_keys");
                            let sdf = resulkt.unwrap();
                            let mut itemfdsd = sdf.clone();
                            if itemfdsd.is_array() {
                                let ssd = itemfdsd.as_array();
                                let sdf = ssd.unwrap();
                                let george = sdf.len();
                                let itemfdsd = sdf.iter();
                                for elem in itemfdsd{
                                    if elem.is_string() {
                                        let sss = elem.as_string();
                                        let foo = sss.unwrap();
                                        let name = String::from(foo);
                                        pk_variable_name = elephant::elephant_variable_pk(conn, &name);
                                        elephant::elephant_job_require_variables(conn, &pk_job, &pk_variable_name);
                                    }
                                }
                            }
                        }
                        if iVariables.contains_key("provides_keys") {
                            let resulkdt = movie.get("provides_keys");
                            let sdf = resulkt.unwrap();
                            let mut itemfdsd = sdf.clone();
                            if itemfdsd.is_array() {
                                let ssd = itemfdsd.as_array();
                                let sdf = ssd.unwrap();
                                let george = sdf.len();
                                let itemfdsd = sdf.iter();
                                for elem in itemfdsd{
                                    if elem.is_string() {
                                        let sss = elem.as_string();
                                        let foo = sss.unwrap();
                                        let name = String::from(foo);
                                        pk_variable_name = elephant::elephant_variable_pk(conn, &name);
                                        elephant::elephant_job_provide_variables(conn, &pk_job, &pk_variable_name);
                                    }
                                }
                            }
                        }
                        if iVariables.contains_key("require_values") {
                            let resulkdtvv = iVariables.get("require_values");
                            let sdfc = resulkdtvv.unwrap();
                            let mut itemfdsdff = sdfc.clone();
                            if itemfdsdff.is_object(){
                                let sssbill = itemfdsdff.as_object();
                                for &dict_key in &sssbill {
                                    //let value_deep = sssbill.get(&dict_key);
                                    let mut key_want : String;
                                    let mut value_want : String;
                                    for variable_name in dict_key.keys(){
										pk_variable_name = elephant::elephant_variable_pk(&conn, &variable_name);
                                        let value = dict_key.get(variable_name);
                                        let unwrapped = value.unwrap();
                                        if unwrapped.is_string(){
                                            let sss = unwrapped.as_string();
                                            let foo = sss.unwrap();
                                            let name = String::from(foo);
                                            let variable_pair_pk = elephant::elephant_variable_pair_pk(&conn, &pk_variable_name, &name);
                                            let job_depend_pair_pk = elephant::elephant_job_depend_pair_pk(&conn, &pk_job, &variable_pair_pk);
										}
									}
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    let found = json.find_path(&["variables"]);
    if found != None {

        for item in found {

            let bill = item.find_path(&["require_values"]);

            if bill != None {
                for item2 in bill {
                    if item2.is_array(){
                        println!("is_array:{:?}", item2);
                    }
                    if item2.is_object() {
                        println!("pk_variable_name:{:?}", pk_variable_name);
                        let object = item2.as_object();

                        println!("is_object:{:?}", object);

                    }

                }
            }
        }

    }
}

<|endoftext|>


<commit_before>//!
//! https://tools.ietf.org/html/rfc5161
//!
//! The IMAP ENABLE Extension
//!

// rustfmt doesn't do a very good job on nom parser invocations.
#![cfg_attr(rustfmt, rustfmt_skip)]

use crate::types::*;
use crate::parser::core::atom;

// The ENABLED response lists capabilities that were enabled in response
// to a ENABLE command.
// [RFC5161 - 3.2 The ENABLED Response](https://tools.ietf.org/html/rfc5161#section-3.2)
named!(pub (crate) resp_enabled<Response>, map!(
    enabled_data,
    Response::Capabilities
));

named!(enabled_data<Vec<Capability>>, do_parse!(
        tag_no_case!("ENABLED") >>
        capabilities: many0!(preceded!(char!(' '), capability)) >>
        (capabilities)
));

named!(capability<Capability>,
       map!(atom, Capability::Atom)
);
<commit_msg>Rewrite RFC 5161 parser with function parsers<commit_after>//!
//! https://tools.ietf.org/html/rfc5161
//!
//! The IMAP ENABLE Extension
//!

use nom::{
    bytes::streaming::tag_no_case,
    character::streaming::char,
    combinator::map,
    multi::many0,
    sequence::{preceded, tuple},
    IResult,
};

use crate::parser::core::atom;
use crate::types::*;

// The ENABLED response lists capabilities that were enabled in response
// to a ENABLE command.
// [RFC5161 - 3.2 The ENABLED Response](https://tools.ietf.org/html/rfc5161#section-3.2)
pub(crate) fn resp_enabled(i: &[u8]) -> IResult<&[u8], Response> {
    map(enabled_data, Response::Capabilities)(i)
}

fn enabled_data(i: &[u8]) -> IResult<&[u8], Vec<Capability>> {
    let (i, (_, capabilities)) = tuple((
        tag_no_case("ENABLED"),
        many0(preceded(char(' '), capability)),
    ))(i)?;
    Ok((i, capabilities))
}

fn capability(i: &[u8]) -> IResult<&[u8], Capability> {
    map(atom, Capability::Atom)(i)
}
<|endoftext|>


<commit_before>use serenity::client::{Context, EventHandler};
use serenity::model::id::GuildId;
use serenity::model::gateway::Ready;
use serenity::model::guild::GuildStatus;

/// Extra functionality for big boi guilds.
///
/// When big boi guilds are sent in the Ready event, only their online members are sent. This makes
/// the bot request offline members, as well, or else the bot will never know their join times,
/// breaking features of the bot.
pub struct GuildsExt;

impl EventHandler for GuildsExt {
  fn ready(&self, ctx: Context, rdy: Ready) {
    let ids: Vec<GuildId> = rdy.guilds
      .into_iter()
      .filter_map(|g| match g {
        GuildStatus::OnlinePartialGuild(partial) => Some(partial),
        _ => None
      })
      .map(|partial| partial.id)
      .collect();
    info!("Asking for more information about {} guild{}",
      ids.len(),
      if ids.len() == 1 { "" } else { "s" }
    );
    ctx.shard.chunk_guilds(ids, None, None);
  }
}
<commit_msg>fix: request more information at the correct time<commit_after>use serenity::client::{Context, EventHandler};
use serenity::model::guild::Guild;

/// Extra functionality for big boi guilds.
///
/// When big boi guilds are sent in the Ready event, only their online members are sent. This makes
/// the bot request offline members, as well, or else the bot will never know their join times,
/// breaking features of the bot.
pub struct GuildsExt;

impl EventHandler for GuildsExt {
  fn guild_create(&self, ctx: Context, guild: Guild, new: bool) {
    if new {
      return;
    }
    if !guild.is_large() {
      return;
    }

    info!("Asking for offline users of {} ({})", guild.name, guild.id);
    ctx.shard.chunk_guilds(vec![guild.id], None, None);
  }
}
<|endoftext|>


<commit_before>// Copyright 2017-2021 Lukas Pustina <lukas@pustina.de>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use crate::app::modules::get_server_lists::config::DownloadServerListConfig;
use crate::app::modules::PartialResultExt;
use crate::app::AppConfig;
use crate::app::ExitStatus;

use anyhow::Result;
use clap::ArgMatches;
use std::convert::TryInto;
use tracing::info;

pub mod config;
#[allow(clippy::module_inception)]
mod get_server_lists;

use get_server_lists::GetServerLists;

pub async fn run(args: &ArgMatches<'_>, app_config: &AppConfig) -> Result<ExitStatus> {
    info!("get-server-lists module selected.");
    let args = args.subcommand_matches("get-server-lists").unwrap();
    let config: DownloadServerListConfig = args.try_into()?;

    GetServerLists::init(app_config, &config)?
        .download_server_lists()
        .await?
        .write_servers_to_file()
        .await
        .into_result()
}
<commit_msg>Fix CLI parsing for server-lists module after renaming<commit_after>// Copyright 2017-2021 Lukas Pustina <lukas@pustina.de>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

use crate::app::modules::get_server_lists::config::DownloadServerListConfig;
use crate::app::modules::PartialResultExt;
use crate::app::AppConfig;
use crate::app::ExitStatus;

use anyhow::Result;
use clap::ArgMatches;
use std::convert::TryInto;
use tracing::info;

pub mod config;
#[allow(clippy::module_inception)]
mod get_server_lists;

use get_server_lists::GetServerLists;

pub async fn run(args: &ArgMatches<'_>, app_config: &AppConfig) -> Result<ExitStatus> {
    info!("server-lists module selected.");
    let args = args.subcommand_matches("server-lists").unwrap();
    let config: DownloadServerListConfig = args.try_into()?;

    GetServerLists::init(app_config, &config)?
        .download_server_lists()
        .await?
        .write_servers_to_file()
        .await
        .into_result()
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::marker;

use Message;

use descriptor::DescriptorProto;
use descriptor::FileDescriptorProto;

use descriptorx::find_message_by_rust_name;

use reflect::accessor::FieldAccessor;
use reflect::reflect_deep_eq::ReflectDeepEq;
use reflect::FieldDescriptor;

use descriptorx::MessageWithScope;
use descriptorx::WithScope;
use json;

trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<Message>;
    fn default_instance(&self) -> &Message;
    fn clone(&self, message: &Message) -> Box<Message>;
    fn eq(&self, a: &Message, b: &Message) -> bool;
}

struct MessageFactoryImpl<M>(marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + Message + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<Message> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &Message {
        M::default_instance() as &Message
    }

    fn clone(&self, message: &Message) -> Box<Message> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &Message, b: &Message) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

pub struct MessageDescriptor {
    full_name: String,
    file_descriptor_proto: &'static FileDescriptorProto,
    proto: &'static DescriptorProto,
    factory: &'static MessageFactory,
    fields: Vec<FieldDescriptor>,

    index_by_name: HashMap<String, usize>,
    index_by_name_or_json_name: HashMap<String, usize>,
    index_by_number: HashMap<u32, usize>,
}

impl MessageDescriptor {
    pub fn for_type<M: Message>() -> &'static MessageDescriptor {
        M::descriptor_static()
    }

    fn compute_full_name(proto: &MessageWithScope) -> String {
        let mut full_name = proto.get_file_descriptor().get_package().to_string();
        if full_name.len() > 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.message.get_name());
        full_name
    }

    // Non-generic part of `new` is a separate function
    // to reduce code bloat from multiple instantiations.
    fn new_non_generic(
        rust_name: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
        factory: &'static MessageFactory,
    ) -> MessageDescriptor {
        let proto = find_message_by_rust_name(file_descriptor_proto, rust_name);

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.message.field {
            field_proto_by_name.insert(field_proto.get_name(), field_proto);
        }

        let mut index_by_name = HashMap::new();
        let mut index_by_name_or_json_name = HashMap::new();
        let mut index_by_number = HashMap::new();
        for (i, f) in proto.message.field.iter().enumerate() {
            assert!(index_by_number.insert(f.get_number() as u32, i).is_none());
            assert!(index_by_name.insert(f.get_name().to_owned(), i).is_none());
            assert!(
                index_by_name_or_json_name
                    .insert(f.get_name().to_owned(), i)
                    .is_none()
            );

            let json_name = json::json_name(f.get_name());

            if !f.get_json_name().is_empty() {
                assert_eq!(json_name, f.get_json_name());
            }

            if json_name != f.get_name() {
                assert!(index_by_name_or_json_name.insert(json_name, i).is_none());
            }
        }

        MessageDescriptor {
            full_name: MessageDescriptor::compute_full_name(&proto),
            proto: proto.message,
            factory,
            fields: fields
                .into_iter()
                .map(|f| {
                    let proto = *field_proto_by_name.get(f.name).unwrap();
                    FieldDescriptor::new(f, proto)
                }).collect(),
            index_by_name,
            index_by_name_or_json_name,
            index_by_number,
            file_descriptor_proto,
        }
    }

    pub fn new<M: 'static + Message + Default + Clone + PartialEq>(
        rust_name: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> MessageDescriptor {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        MessageDescriptor::new_non_generic(rust_name, fields, file_descriptor_proto, factory)
    }

    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor_proto
    }

    /// New empty message
    pub fn new_instance(&self) -> Box<Message> {
        self.factory.new_instance()
    }

    /// Shared immutable empty message
    pub fn default_instance(&self) -> &Message {
        self.factory.default_instance()
    }

    /// Clone a message
    pub fn clone(&self, message: &Message) -> Box<Message> {
        self.factory.clone(message)
    }

    /// Check if two messages equal.
    ///
    /// Panic is any message has different type than this descriptor.
    pub fn eq(&self, a: &Message, b: &Message) -> bool {
        self.factory.eq(a, b)
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// Panics is any message has different type than this descriptor.
    pub fn deep_eq(&self, a: &Message, b: &Message) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(
            self as *const MessageDescriptor,
            a.descriptor() as *const MessageDescriptor
        );
        assert_eq!(
            self as *const MessageDescriptor,
            b.descriptor() as *const MessageDescriptor
        );

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_deep_eq(&bf) {
                return false;
            }
        }
        true
    }

    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    pub fn fields<'a>(&'a self) -> &'a [FieldDescriptor] {
        &self.fields
    }

    /// Find message field by field name
    pub fn field_by_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name_or_json_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name
    pub fn field_by_number<'a>(&'a self, number: u32) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.fields[index])
    }

    pub fn cast<M: 'static>(&self, message: Box<Message>) -> Result<M, Box<Message>> {
        message.downcast_box::<M>().map(|m| *m)
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for MessageDescriptor {
    fn eq(&self, other: &MessageDescriptor) -> bool {
        self as *const MessageDescriptor == other as *const MessageDescriptor
    }
}
<commit_msg>MessageDescriptor::get_proto: expose underlying proto object<commit_after>use std::collections::HashMap;
use std::marker;

use Message;

use descriptor::DescriptorProto;
use descriptor::FileDescriptorProto;

use descriptorx::find_message_by_rust_name;

use reflect::accessor::FieldAccessor;
use reflect::reflect_deep_eq::ReflectDeepEq;
use reflect::FieldDescriptor;

use descriptorx::MessageWithScope;
use descriptorx::WithScope;
use json;

trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<Message>;
    fn default_instance(&self) -> &Message;
    fn clone(&self, message: &Message) -> Box<Message>;
    fn eq(&self, a: &Message, b: &Message) -> bool;
}

struct MessageFactoryImpl<M>(marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + Message + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<Message> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &Message {
        M::default_instance() as &Message
    }

    fn clone(&self, message: &Message) -> Box<Message> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &Message, b: &Message) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

pub struct MessageDescriptor {
    full_name: String,
    file_descriptor_proto: &'static FileDescriptorProto,
    proto: &'static DescriptorProto,
    factory: &'static MessageFactory,
    fields: Vec<FieldDescriptor>,

    index_by_name: HashMap<String, usize>,
    index_by_name_or_json_name: HashMap<String, usize>,
    index_by_number: HashMap<u32, usize>,
}

impl MessageDescriptor {
    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.proto
    }

    pub fn for_type<M: Message>() -> &'static MessageDescriptor {
        M::descriptor_static()
    }

    fn compute_full_name(proto: &MessageWithScope) -> String {
        let mut full_name = proto.get_file_descriptor().get_package().to_string();
        if full_name.len() > 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.message.get_name());
        full_name
    }

    // Non-generic part of `new` is a separate function
    // to reduce code bloat from multiple instantiations.
    fn new_non_generic(
        rust_name: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
        factory: &'static MessageFactory,
    ) -> MessageDescriptor {
        let proto = find_message_by_rust_name(file_descriptor_proto, rust_name);

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.message.field {
            field_proto_by_name.insert(field_proto.get_name(), field_proto);
        }

        let mut index_by_name = HashMap::new();
        let mut index_by_name_or_json_name = HashMap::new();
        let mut index_by_number = HashMap::new();
        for (i, f) in proto.message.field.iter().enumerate() {
            assert!(index_by_number.insert(f.get_number() as u32, i).is_none());
            assert!(index_by_name.insert(f.get_name().to_owned(), i).is_none());
            assert!(
                index_by_name_or_json_name
                    .insert(f.get_name().to_owned(), i)
                    .is_none()
            );

            let json_name = json::json_name(f.get_name());

            if !f.get_json_name().is_empty() {
                assert_eq!(json_name, f.get_json_name());
            }

            if json_name != f.get_name() {
                assert!(index_by_name_or_json_name.insert(json_name, i).is_none());
            }
        }

        MessageDescriptor {
            full_name: MessageDescriptor::compute_full_name(&proto),
            proto: proto.message,
            factory,
            fields: fields
                .into_iter()
                .map(|f| {
                    let proto = *field_proto_by_name.get(f.name).unwrap();
                    FieldDescriptor::new(f, proto)
                }).collect(),
            index_by_name,
            index_by_name_or_json_name,
            index_by_number,
            file_descriptor_proto,
        }
    }

    pub fn new<M: 'static + Message + Default + Clone + PartialEq>(
        rust_name: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> MessageDescriptor {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        MessageDescriptor::new_non_generic(rust_name, fields, file_descriptor_proto, factory)
    }

    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor_proto
    }

    /// New empty message
    pub fn new_instance(&self) -> Box<Message> {
        self.factory.new_instance()
    }

    /// Shared immutable empty message
    pub fn default_instance(&self) -> &Message {
        self.factory.default_instance()
    }

    /// Clone a message
    pub fn clone(&self, message: &Message) -> Box<Message> {
        self.factory.clone(message)
    }

    /// Check if two messages equal.
    ///
    /// Panic is any message has different type than this descriptor.
    pub fn eq(&self, a: &Message, b: &Message) -> bool {
        self.factory.eq(a, b)
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// Panics is any message has different type than this descriptor.
    pub fn deep_eq(&self, a: &Message, b: &Message) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(
            self as *const MessageDescriptor,
            a.descriptor() as *const MessageDescriptor
        );
        assert_eq!(
            self as *const MessageDescriptor,
            b.descriptor() as *const MessageDescriptor
        );

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_deep_eq(&bf) {
                return false;
            }
        }
        true
    }

    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    pub fn fields<'a>(&'a self) -> &'a [FieldDescriptor] {
        &self.fields
    }

    /// Find message field by field name
    pub fn field_by_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name_or_json_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name
    pub fn field_by_number<'a>(&'a self, number: u32) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.fields[index])
    }

    pub fn cast<M: 'static>(&self, message: Box<Message>) -> Result<M, Box<Message>> {
        message.downcast_box::<M>().map(|m| *m)
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for MessageDescriptor {
    fn eq(&self, other: &MessageDescriptor) -> bool {
        self as *const MessageDescriptor == other as *const MessageDescriptor
    }
}
<|endoftext|>