<commit_before>//! The parser facility for parsing `.cnf` and `.sat` files as specified in the
//! [DIMACS format specification](http://www.domagoj-babic.com/uploads/ResearchProjects/Spear/dimacs-cnf.pdf).
//!
//! The DIMACS format was specified for the DIMACS SAT solver competitions as input file format.
//! Many other DIMACS file formats exist for other competitions, however, this crate currently only
//! supports the formats that are relevant for SAT solvers.
//!
//! In `.cnf` the entire SAT formula is encoded as a conjunction of disjunctions and so mainly stores
//! a list of clauses consisting of literals.
//!
//! The `.sat` format is slightly more difficult as the formula can be of a different shape and thus
//! a `.sat` file internally looks similar to a Lisp file.

#![cfg_attr(all(feature = "bench", test), feature(test))]

#![deny(missing_docs)]

#[cfg(all(feature = "bench", test))]
extern crate test;

#[macro_use]
extern crate bitflags;

pub mod items;
pub mod errors;
mod lexer;
pub mod parser;
<commit_msg>improved API for working with dimacs-parser<commit_after>//! The parser facility for parsing `.cnf` and `.sat` files as specified in the
//! [DIMACS format specification](http://www.domagoj-babic.com/uploads/ResearchProjects/Spear/dimacs-cnf.pdf).
//!
//! The DIMACS format was specified for the DIMACS SAT solver competitions as input file format.
//! Many other DIMACS file formats exist for other competitions, however, this crate currently only
//! supports the formats that are relevant for SAT solvers.
//!
//! In `.cnf` the entire SAT formula is encoded as a conjunction of disjunctions and so mainly stores
//! a list of clauses consisting of literals.
//!
//! The `.sat` format is slightly more difficult as the formula can be of a different shape and thus
//! a `.sat` file internally looks similar to a Lisp file.

#![cfg_attr(all(feature = "bench", test), feature(test))]

#![deny(missing_docs)]

#[cfg(all(feature = "bench", test))]
extern crate test;

#[macro_use]
extern crate bitflags;

mod items;
mod errors;
mod lexer;
mod parser;

pub use items::{
	Clause,
	Extensions,
	Lit,
	Var,

	Formula,
	Instance,
	Sign,

	FormulaBox,
	FormulaList
};
pub use errors::{
	Loc,
	ParseError,
	ErrorKind,
	Result
};
pub use parser::parse_dimacs;
<|endoftext|>


<commit_before>#![feature(io, path)]
use std::old_io::{self, File};
use std::iter;

/// Main bitmap structure
pub struct Bitmap {
    width: i32,
    height: i32,
    pixels: Vec<u8>,
}

impl Bitmap {
    /// Create a new blank (white) bitmap of a specified size.
    pub fn new(width: i32, height: i32) -> Bitmap {
        Bitmap {
            width: width,
            height: height,
            // Create a vector to store the pixels in, ensuring that it is padded to a multiple of 4
            // bytes of each row.
            pixels: iter::repeat(0xFF).take((height * (width * 3 + width % 4)) as usize).collect(),
        }
    }

    /// Set a pixel at (x, y) to a specified color (r, g, b).
    pub fn set_pixel(&mut self, x: i32, y: i32, color: (u8, u8, u8)) {
        // Calculate the byte offset for x
        let i = ((self.height - y - 1) * (self.width * 3) + x * 3) as usize;

        let (r, g, b) = color;
        // Note: Pixel order for bitmaps is (blue, green, red)
        self.pixels[i + 0] = b;
        self.pixels[i + 1] = g;
        self.pixels[i + 2] = r;
    }

    /// Write the stored data to a file with given filename.
    pub fn write_to_file(&self, filename: &str) -> old_io::IoResult<()> {
        const FILE_HEADER_SIZE: usize = 14;
        const BMP_INFO_SIZE: usize = 40;
        const TOTAL_HEADER_SIZE: usize = FILE_HEADER_SIZE + BMP_INFO_SIZE;

        let image_size = (self.height * self.width*3 + self.height * (self.width % 4)) as usize;
        let file_size = image_size + TOTAL_HEADER_SIZE;

        // Bitmap file header
        let file_header: [u8; FILE_HEADER_SIZE] = [
            'B' as u8, 'M' as u8,
            file_size as u8, (file_size>>8) as u8, (file_size>>16) as u8, (file_size>>24) as u8,
            0, 0,
            0, 0,
            TOTAL_HEADER_SIZE as u8, 0, 0, 0
        ];
        // Bitmap information header
        let info_header: [u8; BMP_INFO_SIZE] = [
            BMP_INFO_SIZE as u8, 0, 0, 0,
            self.width as u8, (self.width>>8) as u8, (self.width>>16) as u8, (self.width>>24) as u8,
            self.height as u8, (self.height>>8) as u8, (self.height>>16) as u8, (self.height>>24) as u8,
            1, 0,
            24, 0,
            0, 0, 0, 0,
            image_size as u8, (image_size>>8) as u8, (image_size>>16) as u8, (image_size>>24) as u8,
            72, 0, 0, 0,
            72, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0
        ];

        // Set up the file writer
        let mut file = File::create(&Path::new(filename));

        // Write the bitmap headers to file
        try!(file.write_all(&file_header));
        try!(file.write_all(&info_header));

        // Write data to file
        file.write_all(&*self.pixels)
    }

    /// Get the width of the bitmap.
    pub fn width(&self) -> i32 {
        self.width
    }

    /// Get the height of the bitmap.
    pub fn height(&self) -> i32 {
        self.height
    }
}
<commit_msg>Use new deref coercions<commit_after>#![feature(io, path)]
use std::old_io::{self, File};
use std::iter;

/// Main bitmap structure
pub struct Bitmap {
    width: i32,
    height: i32,
    pixels: Vec<u8>,
}

impl Bitmap {
    /// Create a new blank (white) bitmap of a specified size.
    pub fn new(width: i32, height: i32) -> Bitmap {
        Bitmap {
            width: width,
            height: height,
            // Create a vector to store the pixels in, ensuring that it is padded to a multiple of 4
            // bytes of each row.
            pixels: iter::repeat(0xFF).take((height * (width * 3 + width % 4)) as usize).collect(),
        }
    }

    /// Set a pixel at (x, y) to a specified color (r, g, b).
    pub fn set_pixel(&mut self, x: i32, y: i32, color: (u8, u8, u8)) {
        // Calculate the byte offset for x
        let i = ((self.height - y - 1) * (self.width * 3) + x * 3) as usize;

        let (r, g, b) = color;
        // Note: Pixel order for bitmaps is (blue, green, red)
        self.pixels[i + 0] = b;
        self.pixels[i + 1] = g;
        self.pixels[i + 2] = r;
    }

    /// Write the stored data to a file with given filename.
    pub fn write_to_file(&self, filename: &str) -> old_io::IoResult<()> {
        const FILE_HEADER_SIZE: usize = 14;
        const BMP_INFO_SIZE: usize = 40;
        const TOTAL_HEADER_SIZE: usize = FILE_HEADER_SIZE + BMP_INFO_SIZE;

        let image_size = (self.height * self.width*3 + self.height * (self.width % 4)) as usize;
        let file_size = image_size + TOTAL_HEADER_SIZE;

        // Bitmap file header
        let file_header: [u8; FILE_HEADER_SIZE] = [
            'B' as u8, 'M' as u8,
            file_size as u8, (file_size>>8) as u8, (file_size>>16) as u8, (file_size>>24) as u8,
            0, 0,
            0, 0,
            TOTAL_HEADER_SIZE as u8, 0, 0, 0
        ];
        // Bitmap information header
        let info_header: [u8; BMP_INFO_SIZE] = [
            BMP_INFO_SIZE as u8, 0, 0, 0,
            self.width as u8, (self.width>>8) as u8, (self.width>>16) as u8, (self.width>>24) as u8,
            self.height as u8, (self.height>>8) as u8, (self.height>>16) as u8, (self.height>>24) as u8,
            1, 0,
            24, 0,
            0, 0, 0, 0,
            image_size as u8, (image_size>>8) as u8, (image_size>>16) as u8, (image_size>>24) as u8,
            72, 0, 0, 0,
            72, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0
        ];

        // Set up the file writer
        let mut file = File::create(&Path::new(filename));

        // Write the bitmap headers to file
        try!(file.write_all(&file_header));
        try!(file.write_all(&info_header));

        // Write data to file
        file.write_all(&self.pixels)
    }

    /// Get the width of the bitmap.
    pub fn width(&self) -> i32 {
        self.width
    }

    /// Get the height of the bitmap.
    pub fn height(&self) -> i32 {
        self.height
    }
}
<|endoftext|>


<commit_before>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

#![allow(dead_code)]

//----------------------------------------------------------------------------
// Dependencies

// For binary file I/O
extern crate byteorder;

//----------------------------------------------------------------------------
// Module imports

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

use std::io::{Read, Seek};

//----------------------------------------------------------------------------
// Reexports

pub use reader::TIFFReader;

pub mod reader;
//mod writer;

//----------------------------------------------------------------------------
// Types

pub type BYTE = u8;
pub type SHORT = u16;
pub type LONG = u32;
// pub type ASCII = &[u8];
pub type RATIONAL = (u32, u32);
pub type SBYTE = i8;
pub type SSHORT = i16;
pub type SLONG = i32;
pub type SRATIONAL = (i32, i32);
pub type FLOAT = f32;
pub type DOUBLE = f64;

//----------------------------------------------------------------------------
// Enums

#[repr(u16)]
#[derive(Debug)]
pub enum TIFFByteOrder {
    LittleEndian = 0x4949,
    BigEndian = 0x4d4d,
}

#[repr(u16)]
#[derive(Debug)]
pub enum HeaderMagic {
    LittleEndian = 0x002a,
    BigEndian = 0x2a00,
}

#[repr(u16)]
#[derive(Debug)]
pub enum TagType {
    ByteTag = 1,
    ASCIITag = 2,
    ShortTag = 3,
    LongTag = 4,
    RationalTag = 5,
    SByteTag = 6,
    UndefinedTag = 7,
    SShortTag = 8,
    SLongTag = 9,
    SRationalTag = 10,
    FLoatTag = 11,
    DoubleTag = 12,
}

#[repr(u16)]
#[derive(Debug)]
pub enum PhotometricInterpretation {
    WhiteIsZero = 0,
    BlackIsZero = 1,
}

#[repr(u16)]
#[derive(Debug)]
pub enum Compression {
    None = 1,
    Huffman = 2,
    PackBits = 32773,
}

#[repr(u16)]
#[derive(Debug)]
pub enum ResolutionUnit {
    None = 1,
    Inch = 2,
    Centimetre = 3,
}

//----------------------------------------------------------------------------
// Structs

#[derive(Debug)]
pub struct TIFFHeader {
    pub byte_order: TIFFByteOrder,
    pub magic: HeaderMagic,
    pub ifd_offset: LONG,
}

pub struct IFDEntry {
    tag: TIFFTag,
    typ: TagType,
    count: LONG,
    value_offset: LONG,
}

pub struct IFD {
    count: u16,
    entries: Vec<IFDEntry>,
}

//----------------------------------------------------------------------------
// Baseline Tags

#[repr(u16)]
#[derive(Debug)]
pub enum TIFFTag {

    // Baseline Tags

    ArtistTag = 0x013b,
    BitsPerSampleTag = 0x0102,
    CellLengthTag = 0x0109,
    CellWidthTag = 0x0108,
    ColorMapTag = 0x0140,
    CompressionTag = 0x0103,
    CopyrightTag = 0x8298,
    DateTimeTag = 0x0132,
    ExtraSamplesTag = 0x0152,
    FillOrderTag = 0x010a,
    FreeByteCountsTag = 0x0121,
    FreeOffsetsTag = 0x0120,
    GrayResponseCurveTag = 0x0123,
    GrayResponseUnitTag = 0x0122,
    HostComputerTag = 0x013c,
    ImageDescriptionTag = 0x010e,
    ImageLengthTag = 0x0101,
    ImageWidthTag = 0x0100,
    MakeTag = 0x010f,
    MaxSampleValueTag = 0x0119,
    MinSampleValueTag = 0x0118,
    ModelTag = 0x0110,
    NewSubfileTypeTag = 0x00fe,
    OrientationTag = 0x0112,
    PhotometricInterpretationTag = 0x0106,
    PlanarConfigurationTag = 0x011c,
    ResolutionUnitTag = 0x0128,
    RowsPerStripTag = 0x0116,
    SamplesPerPixel = 0x0115,
    SoftwareTag = 0x0131,
    StripByteCountsTag = 0x0117,
    StripOffsetsTag = 0x0111,
    SubfileTypeTag = 0x00ff,
    ThresholdingTag = 0x0107,
    XResolutionTag = 0x011a,
    YResolutionTag = 0x011b,

    // TIFF/EP Tags

    SubIFDsTag = 0x014a,
    JPEGTablesTag = 0x015b,
    CFARepeatPatternDimTag = 0x828d,
    BatteryLevelTag = 0x828f,
    IPTCTag = 0x83BB,
    InterColorProfileTag = 0x8773,
    InterlaceTag = 0x8829,
    TimeZoneOffsetTag = 0x882a,
    SelfTimerModeTag = 0x882b,
    NoiseTag = 0x920d,
    ImageNumberTag = 0x9211,
    SecurityClassificationTag = 0x9212,
    ImageHistoryTag = 0x9213,
    EPStandardIdTag = 0x9216,

    // Extension TIFF Tags
    // See http://www.awaresystems.be/imaging/tiff/tifftags/extension.html
    XMPTag = 0x02bc,

    // Private Tags
    PhotoshopTag = 0x8649,
    EXIFTag = 0x8769,
}

//----------------------------------------------------------------------------
// Default Values

static PHOTOMETRIC_INTERPRETATION_SHORT_DEFAULT: SHORT = 1;
static PHOTOMETRIC_INTERPRETATION_LONG_DEFAULT: LONG = 1;

//----------------------------------------------------------------------------

// Section 6: Required Fields for RGB Images

fn validate_rgb_image() {
    // ImageWidth
    // ImageLength
    // BitsPerSample
    // Compression
    // PhotometricInterpretation
    // StripOffsets
    // SamplesPerPixel
    // RowsPerStrip
    // StripByteCounts
    // XResolution
    // YResolution
    // ResolutionUnit
}

//----------------------------------------------------------------------------

pub trait SeekableReader: Seek + Read {}
impl<T: Seek + Read> SeekableReader for T {}

pub fn decode_tag(value: u16) -> Option<TIFFTag> {
    match value {
        0x013b => Some(TIFFTag::ArtistTag),
        0x0102 => Some(TIFFTag::BitsPerSampleTag),
        0x0109 => Some(TIFFTag::CellLengthTag),
        0x0108 => Some(TIFFTag::CellWidthTag),
        0x0140 => Some(TIFFTag::ColorMapTag),
        0x0103 => Some(TIFFTag::CompressionTag),
        0x8298 => Some(TIFFTag::CopyrightTag),
        0x0132 => Some(TIFFTag::DateTimeTag),
        0x0152 => Some(TIFFTag::ExtraSamplesTag),
        0x010a => Some(TIFFTag::FillOrderTag),
        0x0121 => Some(TIFFTag::FreeByteCountsTag),
        0x0120 => Some(TIFFTag::FreeOffsetsTag),
        0x0123 => Some(TIFFTag::GrayResponseCurveTag),
        0x0122 => Some(TIFFTag::GrayResponseUnitTag),
        0x013c => Some(TIFFTag::HostComputerTag),
        0x010e => Some(TIFFTag::ImageDescriptionTag),
        0x0101 => Some(TIFFTag::ImageLengthTag),
        0x0100 => Some(TIFFTag::ImageWidthTag),
        0x010f => Some(TIFFTag::MakeTag),
        0x0119 => Some(TIFFTag::MaxSampleValueTag),
        0x0118 => Some(TIFFTag::MinSampleValueTag),
        0x0110 => Some(TIFFTag::ModelTag),
        0x00fe => Some(TIFFTag::NewSubfileTypeTag),
        0x0112 => Some(TIFFTag::OrientationTag),
        0x0106 => Some(TIFFTag::PhotometricInterpretationTag),
        0x011c => Some(TIFFTag::PlanarConfigurationTag),
        0x0128 => Some(TIFFTag::ResolutionUnitTag),
        0x0116 => Some(TIFFTag::RowsPerStripTag),
        0x0115 => Some(TIFFTag::SamplesPerPixel),
        0x0131 => Some(TIFFTag::SoftwareTag),
        0x0117 => Some(TIFFTag::StripByteCountsTag),
        0x0111 => Some(TIFFTag::StripOffsetsTag),
        0x00ff => Some(TIFFTag::SubfileTypeTag),
        0x0107 => Some(TIFFTag::ThresholdingTag),
        0x011a => Some(TIFFTag::XResolutionTag),
        0x011b => Some(TIFFTag::YResolutionTag),

        0x014a => Some(TIFFTag::SubIFDsTag),
        0x015b => Some(TIFFTag::JPEGTablesTag),
        0x828d => Some(TIFFTag::CFARepeatPatternDimTag),
        0x828f => Some(TIFFTag::BatteryLevelTag),
        0x83BB => Some(TIFFTag::IPTCTag),
        0x8773 => Some(TIFFTag::InterColorProfileTag),
        0x8829 => Some(TIFFTag::InterlaceTag),
        0x882a => Some(TIFFTag::TimeZoneOffsetTag),
        0x882b => Some(TIFFTag::SelfTimerModeTag),
        0x920d => Some(TIFFTag::NoiseTag),
        0x9211 => Some(TIFFTag::ImageNumberTag),
        0x9212 => Some(TIFFTag::SecurityClassificationTag),
        0x9213 => Some(TIFFTag::ImageHistoryTag),
        0x9216 => Some(TIFFTag::EPStandardIdTag),

        0x02bc => Some(TIFFTag::XMPTag),
        0x8649 => Some(TIFFTag::PhotoshopTag),
        0x8769 => Some(TIFFTag::EXIFTag),
        _ => None,
    }
}

pub fn decode_tag_type(typ: u16) -> Option<TagType> {

    match typ {
        1 => Some(TagType::ByteTag),
        2 => Some(TagType::ASCIITag),
        3 => Some(TagType::ShortTag),
        4 => Some(TagType::LongTag),
        5 => Some(TagType::RationalTag),
        6 => Some(TagType::SByteTag),
        7 => Some(TagType::UndefinedTag),
        8 => Some(TagType::SShortTag),
        9 => Some(TagType::SLongTag),
        10 => Some(TagType::SRationalTag),
        11 => Some(TagType::FLoatTag),
        12 => Some(TagType::DoubleTag),
        _ => None,
    }
}
<commit_msg>Tidy types, common stuff, add baseline tag reqs<commit_after>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

#![allow(dead_code)]

//----------------------------------------------------------------------------
// Dependencies

// For binary file I/O
extern crate byteorder;

//----------------------------------------------------------------------------
// Module imports

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

use std::io::{Read, Seek};

//----------------------------------------------------------------------------
// Reexports

pub use reader::TIFFReader;

pub mod reader;
//mod writer;

//----------------------------------------------------------------------------
// Types

pub type BYTE = u8;
pub type SHORT = u16;
pub type LONG = u32;
pub type ASCII = String;
pub type RATIONAL = (u32, u32);
pub type SBYTE = i8;
pub type SSHORT = i16;
pub type SLONG = i32;
pub type SRATIONAL = (i32, i32);
pub type FLOAT = f32;
pub type DOUBLE = f64;

//----------------------------------------------------------------------------
// Enums

#[repr(u16)]
#[derive(Debug)]
pub enum TIFFByteOrder {
    LittleEndian = 0x4949,
    BigEndian = 0x4d4d,
}

#[repr(u16)]
#[derive(Debug)]
pub enum HeaderMagic {
    LittleEndian = 0x002a,
    BigEndian = 0x2a00,
}

#[repr(u16)]
#[derive(Debug)]
pub enum TagType {
    ByteTag = 1,
    ASCIITag = 2,
    ShortTag = 3,
    LongTag = 4,
    RationalTag = 5,
    SignedByteTag = 6,
    UndefinedTag = 7,
    SignedShortTag = 8,
    SignedLongTag = 9,
    SignedRationalTag = 10,
    FloatTag = 11,
    DoubleTag = 12,
}

#[repr(u16)]
#[derive(Debug)]
pub enum PhotometricInterpretation {
    WhiteIsZero = 0,
    BlackIsZero = 1,
}

#[repr(u16)]
#[derive(Debug)]
pub enum Compression {
    None = 1,
    Huffman = 2,
    PackBits = 32773,
}

#[repr(u16)]
#[derive(Debug)]
pub enum ResolutionUnit {
    None = 1,
    Inch = 2,
    Centimetre = 3,
}

//----------------------------------------------------------------------------
// Structs

#[derive(Debug)]
pub struct TIFFHeader {
    pub byte_order: TIFFByteOrder,
    pub magic: HeaderMagic,
    pub ifd_offset: LONG,
}

pub struct IFDEntry {
    tag: TIFFTag,
    typ: TagType,
    count: LONG,
    value_offset: LONG,
}

pub struct IFD {
    count: u16,
    entries: Vec<IFDEntry>,
}

//----------------------------------------------------------------------------
// Baseline Tags

#[repr(u16)]
#[derive(Debug)]
pub enum TIFFTag {

    // Baseline Tags

    ArtistTag = 0x013b,
    BitsPerSampleTag = 0x0102,
    CellLengthTag = 0x0109,
    CellWidthTag = 0x0108,
    ColorMapTag = 0x0140,
    CompressionTag = 0x0103,
    CopyrightTag = 0x8298,
    DateTimeTag = 0x0132,
    ExtraSamplesTag = 0x0152,
    FillOrderTag = 0x010a,
    FreeByteCountsTag = 0x0121,
    FreeOffsetsTag = 0x0120,
    GrayResponseCurveTag = 0x0123,
    GrayResponseUnitTag = 0x0122,
    HostComputerTag = 0x013c,
    ImageDescriptionTag = 0x010e,
    ImageLengthTag = 0x0101,
    ImageWidthTag = 0x0100,
    MakeTag = 0x010f,
    MaxSampleValueTag = 0x0119,
    MinSampleValueTag = 0x0118,
    ModelTag = 0x0110,
    NewSubfileTypeTag = 0x00fe,
    OrientationTag = 0x0112,
    PhotometricInterpretationTag = 0x0106,
    PlanarConfigurationTag = 0x011c,
    ResolutionUnitTag = 0x0128,
    RowsPerStripTag = 0x0116,
    SamplesPerPixel = 0x0115,
    SoftwareTag = 0x0131,
    StripByteCountsTag = 0x0117,
    StripOffsetsTag = 0x0111,
    SubfileTypeTag = 0x00ff,
    ThresholdingTag = 0x0107,
    XResolutionTag = 0x011a,
    YResolutionTag = 0x011b,

    // TIFF/EP Tags

    SubIFDsTag = 0x014a,
    JPEGTablesTag = 0x015b,
    CFARepeatPatternDimTag = 0x828d,
    BatteryLevelTag = 0x828f,
    IPTCTag = 0x83BB,
    InterColorProfileTag = 0x8773,
    InterlaceTag = 0x8829,
    TimeZoneOffsetTag = 0x882a,
    SelfTimerModeTag = 0x882b,
    NoiseTag = 0x920d,
    ImageNumberTag = 0x9211,
    SecurityClassificationTag = 0x9212,
    ImageHistoryTag = 0x9213,
    EPStandardIdTag = 0x9216,

    // Extension TIFF Tags
    // See http://www.awaresystems.be/imaging/tiff/tifftags/extension.html
    XMPTag = 0x02bc,

    // Private Tags
    PhotoshopTag = 0x8649,
    EXIFTag = 0x8769,
}

//----------------------------------------------------------------------------
// Default Values

static PHOTOMETRIC_INTERPRETATION_SHORT_DEFAULT: SHORT = 1;
static PHOTOMETRIC_INTERPRETATION_LONG_DEFAULT: LONG = 1;

//----------------------------------------------------------------------------

// Section 6: Required Fields for RGB Images

fn validate_rgb_image() {
    // ImageWidth
    // ImageLength
    // BitsPerSample
    // Compression
    // PhotometricInterpretation
    // StripOffsets
    // SamplesPerPixel
    // RowsPerStrip
    // StripByteCounts
    // XResolution
    // YResolution
    // ResolutionUnit
}

//----------------------------------------------------------------------------

pub trait SeekableReader: Seek + Read {}
impl<T: Seek + Read> SeekableReader for T {}

pub fn decode_tag(value: u16) -> Option<TIFFTag> {
    match value {
        0x013b => Some(TIFFTag::ArtistTag),
        0x0102 => Some(TIFFTag::BitsPerSampleTag),
        0x0109 => Some(TIFFTag::CellLengthTag),
        0x0108 => Some(TIFFTag::CellWidthTag),
        0x0140 => Some(TIFFTag::ColorMapTag),
        0x0103 => Some(TIFFTag::CompressionTag),
        0x8298 => Some(TIFFTag::CopyrightTag),
        0x0132 => Some(TIFFTag::DateTimeTag),
        0x0152 => Some(TIFFTag::ExtraSamplesTag),
        0x010a => Some(TIFFTag::FillOrderTag),
        0x0121 => Some(TIFFTag::FreeByteCountsTag),
        0x0120 => Some(TIFFTag::FreeOffsetsTag),
        0x0123 => Some(TIFFTag::GrayResponseCurveTag),
        0x0122 => Some(TIFFTag::GrayResponseUnitTag),
        0x013c => Some(TIFFTag::HostComputerTag),
        0x010e => Some(TIFFTag::ImageDescriptionTag),
        0x0101 => Some(TIFFTag::ImageLengthTag),
        0x0100 => Some(TIFFTag::ImageWidthTag),
        0x010f => Some(TIFFTag::MakeTag),
        0x0119 => Some(TIFFTag::MaxSampleValueTag),
        0x0118 => Some(TIFFTag::MinSampleValueTag),
        0x0110 => Some(TIFFTag::ModelTag),
        0x00fe => Some(TIFFTag::NewSubfileTypeTag),
        0x0112 => Some(TIFFTag::OrientationTag),
        0x0106 => Some(TIFFTag::PhotometricInterpretationTag),
        0x011c => Some(TIFFTag::PlanarConfigurationTag),
        0x0128 => Some(TIFFTag::ResolutionUnitTag),
        0x0116 => Some(TIFFTag::RowsPerStripTag),
        0x0115 => Some(TIFFTag::SamplesPerPixel),
        0x0131 => Some(TIFFTag::SoftwareTag),
        0x0117 => Some(TIFFTag::StripByteCountsTag),
        0x0111 => Some(TIFFTag::StripOffsetsTag),
        0x00ff => Some(TIFFTag::SubfileTypeTag),
        0x0107 => Some(TIFFTag::ThresholdingTag),
        0x011a => Some(TIFFTag::XResolutionTag),
        0x011b => Some(TIFFTag::YResolutionTag),

        0x014a => Some(TIFFTag::SubIFDsTag),
        0x015b => Some(TIFFTag::JPEGTablesTag),
        0x828d => Some(TIFFTag::CFARepeatPatternDimTag),
        0x828f => Some(TIFFTag::BatteryLevelTag),
        0x83BB => Some(TIFFTag::IPTCTag),
        0x8773 => Some(TIFFTag::InterColorProfileTag),
        0x8829 => Some(TIFFTag::InterlaceTag),
        0x882a => Some(TIFFTag::TimeZoneOffsetTag),
        0x882b => Some(TIFFTag::SelfTimerModeTag),
        0x920d => Some(TIFFTag::NoiseTag),
        0x9211 => Some(TIFFTag::ImageNumberTag),
        0x9212 => Some(TIFFTag::SecurityClassificationTag),
        0x9213 => Some(TIFFTag::ImageHistoryTag),
        0x9216 => Some(TIFFTag::EPStandardIdTag),

        0x02bc => Some(TIFFTag::XMPTag),
        0x8649 => Some(TIFFTag::PhotoshopTag),
        0x8769 => Some(TIFFTag::EXIFTag),
        _ => None,
    }
}

pub fn decode_tag_type(typ: u16) -> Option<TagType> {

    match typ {
        1 => Some(TagType::ByteTag),
        2 => Some(TagType::ASCIITag),
        3 => Some(TagType::ShortTag),
        4 => Some(TagType::LongTag),
        5 => Some(TagType::RationalTag),
        6 => Some(TagType::SignedByteTag),
        7 => Some(TagType::UndefinedTag),
        8 => Some(TagType::SignedShortTag),
        9 => Some(TagType::SignedLongTag),
        10 => Some(TagType::SignedRationalTag),
        11 => Some(TagType::FloatTag),
        12 => Some(TagType::DoubleTag),
        _ => None,
    }
}

/*
    Required Fields for Bilevel Images

    - ImageWidth
    - ImageLength
    - Compression
    - PhotometricInterpretation
    - StripOffsets
    - RowsPerStrip
    - StripByteCounts
    - XResolution
    - YResolution
    - ResolutionUnit
 */

/*
    Required Fields for Grayscale Images

    - ImageWidth
    - ImageLength
    - BitsPerSample
    - Compression
    - PhotometricInterpretation
    - StripOffsets
    - RowsPerStrip
    - StripByteCounts
    - XResolution
    - YResolution
    - ResolutionUnit
 */

/*
    Required Fields for Palette Colour Images

    - ImageWidth
    - ImageLength
    - BitsPerSample
    - Compression
    - PhotometricInterpretation
    - StripOffsets
    - RowsPerStrip
    - StripByteCounts
    - XResolution
    - YResolution
    - ResolutionUnit
    - ColorMap
 */

/*
    Required Fields for RGB Images

    - ImageWidth
    - ImageLength
    - BitsPerSample
    - Compression
    - PhotometricInterpretation
    - StripOffsets
    - SamplesPerPixel
    - RowsPerStrip
    - StripByteCounts
    - XResolution
    - YResolution
    - ResolutionUnit
 */
<|endoftext|>


<commit_before>//#![feature(step_trait)]

extern crate bit_vec ;
extern crate itertools ;
extern crate core ;

use bit_vec::BitVec;
use std::cmp ;
use itertools::Itertools ;
//use core::iter::Step ;

const SIGNBIT : i32 = 1<<31;

pub fn modneg( x : i64, y : usize) -> usize {
	(( x % y as i64) + y as i64) as usize % y
	}

pub fn int_sqrt(n :usize) -> usize {
	((n as f64).sqrt()).floor() as usize
}

#[inline]
pub fn cnt_query(mut pos : usize, counter : &[i32]) -> u32 {
	let mut acc = counter[pos] & !SIGNBIT  ;
	pos += 1 ;
	pos &= pos - 1 ;
	while pos  != 0 {
		acc += counter[pos - 1] & !SIGNBIT;
		pos &= pos - 1;
	}
acc as u32
}

#[inline]
pub fn cnt_update(mut pos : usize, counter : &mut[i32], interval_length : usize ) {
    counter[pos] |= SIGNBIT;
    loop {
      counter[pos] -= 1;
      pos |= pos + 1;
      if pos >=interval_length {break;}
    }
    }

#[inline]
pub fn interval_clear(index : usize , offsets : &mut[usize],  counter : &mut[i32], interval_length : usize, prime : usize) {
//   (offsets[index]..interval_length).step(prime).foreach(|j| {    	if counter[j] > 0 { cnt_update( j, counter, interval_length ) ; } }) ; much slower

   let mut j  = offsets[index] ;
   while j < interval_length {
   	if counter[j] > 0 { cnt_update( j, counter, interval_length ) ; }
   	j += prime ;
   	}
   offsets[index] = modneg( offsets[index] as i64 - interval_length as i64 , prime );
   }

 pub fn initialize_arrays(ll : usize, mu : &mut[isize], pi : &mut [usize],  primes : &mut [usize]) -> usize {
 	 	for j in  2..mu.len() {
 		if mu[j] == 1 {
 			let mut i = j ; while i <= ll  {
 			 mu[i] = match mu[i] {
 				1 => 1 - 2 * j as isize,
 				_ => -mu[i] ,
 			} ;
 		i += 2 * j - 1 ;	}
 		}
 	}
 	let mut j = 2 ; while j * j <= ll << 1 {
 		if mu[j] == 1- 2*j as isize {
 			let mut i = 2 * j * j - 2 * j + 1 ;
 			while i <= ll  {
 			mu[i] = 0 ;
 			i += 4 * j * j - 4 * j + 1 ;
 			}
 		}
 		j += 1 ;
 	}
primes[1] = 2 ;
let mut pix = 1 ;
for (i , elem) in mu.iter().enumerate().dropping(2) {
if *elem == 1 - 2 * i as isize {
 	pix += 1;
 	primes[pix] = 2 * i as usize -1 ;
}
pi[i as usize]=pix;
 }
//println!("{:?}",mu) ;
 pix
 }

/*
 pub fn ordinary_leaves(n : usize, count : &mut i64, mu : &[isize], m : u64) {
  for i in (1..n + 1).step(2) {
  	let term = (mu[(i+1) >> 1]).signum() as i64;
  	*count +=  term * (m as i64/ i as i64) ;
 }
for i in (2..n + 1).step(4) {
	let term = (mu[((i >> 1)  + 1) >> 1]).signum() as i64 ;
	*count -= term * (m as i64 / i as i64) ;
}
}
 */
  pub fn ordinary_leaves(n : usize, mu : &[isize], m : u64) -> i64 {
let mut result = 0 ;
let mut it = (1..n+1).filter(|&i| i % 4 != 0) ;
it.foreach(|i| {if i % 2 == 1
		{let term = (mu[(i+1) >> 1]).signum() as i64;
  	result +=  term * (m as i64 / i as i64) ;}
		 else { let term = (mu[((i >> 1)  + 1) >> 1]).signum() as i64 ;
	result -= term * (m as i64 / i as i64) ;} }) ;
result
}

 pub fn rphi(term: i64,  mut a : usize, bit : i8 , primes: &[usize],  total : &mut i64 )  {
	loop {
		if a == 1 {
			*total +=  bit as i64 * term ;
			break;
			}
		else if term < primes[a] as i64 {
			*total += bit as i64 ;
			break;
				}
		else {
			a -= 1;
			rphi(term / (primes[a] as i64), a, -bit, primes, total) ;
					}
				}
		}

pub fn special_leaves_type_1_substitute(b : usize, primes : &[usize], n : usize, mu : &[isize], m : u64) -> i64 {
let pp = primes[b + 1]    ; let mut acc = 0 ;
let mut j = cmp::max((n / pp) , pp ) as usize + 1 ;
if j % 2 == 0 { j += 1;}
let mut i = j ; while i <= n {
//for i in (j..(n+1)).step_by(2) {
let muval1 = (mu[ ( i+1) >> 1 ] ).signum() ;
if (mu[(i + 1) >> 1]).abs() > pp as isize && muval1 != 0 {
let term = (m / (i * pp) as u64) as i64;
let mut total : i64 = 0;
rphi(term, b + 1, 1, primes, &mut total)  ;
acc += muval1 as i64 * total ;
}
i+=2 ; }
acc
}

#[inline]
pub fn special_leaves_type_1( b : usize , interval : usize ,  m1 : &mut [usize] , n : usize, pp : usize , m : u64 ,
 	 interval_boundaries : &[usize], mu : &[isize], count : &mut i64, phi : &[u64], counter : &[i32]) {
if m1[b] % 2 == 0 { m1[b] -= 1;}
let criterion = n / pp ;
while m1[b] > criterion {
   let y  = (m / (m1[b] as u64 * pp as u64 )) as usize  ; //print!("y = {} ",y) ;
   if y > interval_boundaries[interval + 1] - 2 { return ;}
   let   muvalue = mu[((m1[b]+1) >> 1)];
   if muvalue.abs() > pp as isize { *count -=  muvalue.signum() as i64 * (phi[b] as i64 + cnt_query((y + 1 - interval_boundaries[interval]), counter) as i64);}
   m1[b] -= 2 ;
      }
  }

 #[inline]
pub fn special_leaves_type_2_initialize( b : usize, pb : usize, m : u64, t : &mut[usize], n : usize, pi : &[usize], a : usize, d2 : &mut[usize], count : &mut i64 )  {
let    term = (m / (pb as u64 * pb as u64)) as usize;
t[b] = match  term {
   term if term <= pb =>  b + 2,
   term if term < n =>  pi[(term + 1) >> 1] + 1,
   _ => a + 1,
       };
d2[b] = t[b] - 1 ;
*count += (a - d2[b]) as i64 ;
}
#[inline]
pub fn hard(b :  usize , interval : usize, y : usize, interval_boundaries : &[usize], count : &mut i64, counter : &[i32], d2 : &mut [usize]) -> ( bool, u32) {
    if y + 1 >= interval_boundaries[interval+1] {return (true,0); }
    *count+= cnt_query((y + 1 - interval_boundaries[interval]),counter) as i64;
    d2[b] -= 1;
   ( false, 1 )
    }

 #[inline]
pub fn easy_sparse(b :  usize , interval : usize, y : usize, n : usize, tt : &mut[u8], switch : &mut [bool],interval_boundaries : &[usize],
	 count : &mut i64, counter : &[i32], d2 : &mut [usize], pi : &[usize] ) -> bool  {
      if y >= n {
         if !switch[b] { switch[b]=true; return true; } else { tt[b] = 2 ; hard(b,interval,y,interval_boundaries,count,counter,d2); }
      }
      else {
         let l = pi[((y + 1) >> 1)] - b + 1;
         *count += l as i64;
         d2[b] -= 1;
      }
    false
    }

#[inline]
pub fn easy_clustered(b :  usize , interval : usize, y : usize, n : usize, tt: &mut[u8], switch : &mut [bool], interval_boundaries : &[usize],
	 count : &mut i64, counter : &[i32], d2 : &mut [usize], m : u64, pi : &[usize], p : &[usize] ) -> bool  {
     if y >= n {
        if !switch[b] { switch[b]=true; return true; } else { tt[b] = 2 ; hard(b,interval,y,interval_boundaries,count,counter,d2); }
      }
     else
      {
     let   l = pi[((y + 1) >> 1)] - b + 1;
     let  term = m / (p[b + 1] as u64 * p[b + l] as u64);
     let  dprime = pi[((term + 1) >> 1) as usize];
     if p[dprime + 1] <= int_sqrt((m / p[b + 1] as u64) as usize) || dprime <= b  {
         tt[b] = 1;
         *count += l as i64;
         d2[b] -= 1 ;
        }
      else
    {
      *count +=  (l as u32 * (d2[b] - dprime) as u32) as i64 ;
      d2[b] = dprime;
      }
    }
    false
      }

  #[inline]
    pub fn special_leaves_type_2(b: usize, interval : usize, d2 : &mut[usize], m : u64, p : &[usize], tt : &mut[u8],
    	 n : usize, switch : &mut[bool], interval_boundaries : &[usize], count : &mut i64, counter : &[i32], pi : &[usize] )  -> u32 {
    let mut s2bprimes= 0;
     loop {
      if d2[b] == b + 1 {return s2bprimes; }
      else
      {
       let y = (m / (p[b + 1] as u64 * p[d2[b]] as u64)) as usize;
       match tt[b] {
          0 => { if easy_clustered(b, interval,y,n,tt,switch,interval_boundaries,count,counter,d2,m,pi,p) { return s2bprimes;} continue ; } ,
          1 => { if easy_sparse(b,interval,y,n,tt,switch,interval_boundaries,count,counter,d2,pi) { return s2bprimes; }  continue ; } ,
          _ => { let h = hard(b,interval,y,interval_boundaries,count,counter,d2) ;
                 if (interval > 0 || counter[1] > 0) && h.0 { return s2bprimes;} s2bprimes += h.1 ; continue ; } ,
}
      }
      }
     }

  #[inline]
 pub fn sieve2( x : usize, y : usize,   p : &[usize],  block : &mut BitVec )
  {
block.clear();
   let mut i  = 1 ;
    while p[i] * p[i] <= y {
    let mut offset = modneg(1-x as i64,p[i]);
//    (offset..2+y-x).step(p[i]).foreach(|j| block.set(j,true) ) ; much slower
       while offset <= 1+(y-x)  {
    	 block.set(offset,true);
         offset += p[i];
        }
       i += 1 ;
    }
}

 #[inline]
 pub fn p2(interval : usize, u : &mut usize, v :  &mut usize, n : usize, w : &mut usize,
   block : &mut BitVec , p : &[usize], m : u64 , interval_boundaries : &[usize], phi2 : &mut i64, counter : &[i32], a : usize  ) -> u32
      {
  let mut p2primes = 0;
loop {
    if *u <= n { *phi2 -= (*v as i64 * (*v - 1) as i64) >> 1 ; return p2primes;}
   	if *u  < *w  {
   		*w = cmp::max(2,*u -n);
   		sieve2(*w,*u+1,p,block) ;
   		    }
	let index = *u-*w+1;
    if !block[index] {
    let y  = (m / (*u as u64)) as usize;
    if y +1 >= interval_boundaries[interval + 1] { return p2primes; }
    *phi2 += (cnt_query((y + 1 - interval_boundaries[interval]), counter) as usize + a) as i64 - 1;
    p2primes += 1;
    *v += 1;
    }
    *u -= 2;
}
}

<commit_msg>removed unnecessary use of tuples in hard<commit_after>//#![feature(step_trait)]

extern crate bit_vec ;
extern crate itertools ;
extern crate core ;

use bit_vec::BitVec;
use std::cmp ;
use itertools::Itertools ;
//use core::iter::Step ;

const SIGNBIT : i32 = 1<<31;

pub fn modneg( x : i64, y : usize) -> usize {
	(( x % y as i64) + y as i64) as usize % y
	}

pub fn int_sqrt(n :usize) -> usize {
	((n as f64).sqrt()).floor() as usize
}

#[inline]
pub fn cnt_query(mut pos : usize, counter : &[i32]) -> u32 {
	let mut acc = counter[pos] & !SIGNBIT  ;
	pos += 1 ;
	pos &= pos - 1 ;
	while pos  != 0 {
		acc += counter[pos - 1] & !SIGNBIT;
		pos &= pos - 1;
	}
acc as u32
}

#[inline]
pub fn cnt_update(mut pos : usize, counter : &mut[i32], interval_length : usize ) {
    counter[pos] |= SIGNBIT;
    loop {
      counter[pos] -= 1;
      pos |= pos + 1;
      if pos >=interval_length {break;}
    }
    }

#[inline]
pub fn interval_clear(index : usize , offsets : &mut[usize],  counter : &mut[i32], interval_length : usize, prime : usize) {
//   (offsets[index]..interval_length).step(prime).foreach(|j| {    	if counter[j] > 0 { cnt_update( j, counter, interval_length ) ; } }) ; much slower

   let mut j  = offsets[index] ;
   while j < interval_length {
   	if counter[j] > 0 { cnt_update( j, counter, interval_length ) ; }
   	j += prime ;
   	}
   offsets[index] = modneg( offsets[index] as i64 - interval_length as i64 , prime );
   }

 pub fn initialize_arrays(ll : usize, mu : &mut[isize], pi : &mut [usize],  primes : &mut [usize]) -> usize {
 	 	for j in  2..mu.len() {
 		if mu[j] == 1 {
 			let mut i = j ; while i <= ll  {
 			 mu[i] = match mu[i] {
 				1 => 1 - 2 * j as isize,
 				_ => -mu[i] ,
 			} ;
 		i += 2 * j - 1 ;	}
 		}
 	}
 	let mut j = 2 ; while j * j <= ll << 1 {
 		if mu[j] == 1- 2*j as isize {
 			let mut i = 2 * j * j - 2 * j + 1 ;
 			while i <= ll  {
 			mu[i] = 0 ;
 			i += 4 * j * j - 4 * j + 1 ;
 			}
 		}
 		j += 1 ;
 	}
primes[1] = 2 ;
let mut pix = 1 ;
for (i , elem) in mu.iter().enumerate().dropping(2) {
if *elem == 1 - 2 * i as isize {
 	pix += 1;
 	primes[pix] = 2 * i as usize -1 ;
}
pi[i as usize]=pix;
 }
//println!("{:?}",mu) ;
 pix
 }

pub fn ordinary_leaves(n : usize, mu : &[isize], m : u64) -> i64 {
let mut result = 0 ;
let mut it = (1..n+1).filter(|&i| i % 4 != 0) ;
it.foreach(|i| {if i % 2 == 1
		{let term = (mu[(i+1) >> 1]).signum() as i64;
  	result +=  term * (m as i64 / i as i64) ;}
		 else { let term = (mu[((i >> 1)  + 1) >> 1]).signum() as i64 ;
	result -= term * (m as i64 / i as i64) ;} }) ;
result
}

 pub fn rphi(term: i64,  mut a : usize, bit : i8 , primes: &[usize],  total : &mut i64 )  {
	loop {
		if a == 1 {
			*total +=  bit as i64 * term ;
			break;
			}
		else if term < primes[a] as i64 {
			*total += bit as i64 ;
			break;
				}
		else {
			a -= 1;
			rphi(term / (primes[a] as i64), a, -bit, primes, total) ;
					}
				}
		}

pub fn special_leaves_type_1_substitute(b : usize, primes : &[usize], n : usize, mu : &[isize], m : u64) -> i64 {
let pp = primes[b + 1]    ; let mut acc = 0 ;
let mut j = cmp::max((n / pp) , pp ) as usize + 1 ;
if j % 2 == 0 { j += 1;}
let mut i = j ; while i <= n {
//for i in (j..(n+1)).step_by(2) {
let muval1 = (mu[ ( i+1) >> 1 ] ).signum() ;
if (mu[(i + 1) >> 1]).abs() > pp as isize && muval1 != 0 {
let term = (m / (i * pp) as u64) as i64;
let mut total : i64 = 0;
rphi(term, b + 1, 1, primes, &mut total)  ;
acc += muval1 as i64 * total ;
}
i+=2 ; }
acc
}

#[inline]
pub fn special_leaves_type_1( b : usize , interval : usize ,  m1 : &mut [usize] , n : usize, pp : usize , m : u64 ,
 	 interval_boundaries : &[usize], mu : &[isize], count : &mut i64, phi : &[u64], counter : &[i32]) {
if m1[b] % 2 == 0 { m1[b] -= 1;}
let criterion = n / pp ;
while m1[b] > criterion {
   let y  = (m / (m1[b] as u64 * pp as u64 )) as usize  ; //print!("y = {} ",y) ;
   if y > interval_boundaries[interval + 1] - 2 { return ;}
   let   muvalue = mu[((m1[b]+1) >> 1)];
   if muvalue.abs() > pp as isize { *count -=  muvalue.signum() as i64 * (phi[b] as i64 + cnt_query((y + 1 - interval_boundaries[interval]), counter) as i64);}
   m1[b] -= 2 ;
      }
  }

 #[inline]
pub fn special_leaves_type_2_initialize( b : usize, pb : usize, m : u64, t : &mut[usize], n : usize, pi : &[usize], a : usize, d2 : &mut[usize], count : &mut i64 )  {
let    term = (m / (pb as u64 * pb as u64)) as usize;
t[b] = match  term {
   term if term <= pb =>  b + 2,
   term if term < n =>  pi[(term + 1) >> 1] + 1,
   _ => a + 1,
       };
d2[b] = t[b] - 1 ;
*count += (a - d2[b]) as i64 ;
}
#[inline]
pub fn hard(b :  usize , interval : usize, y : usize, interval_boundaries : &[usize], count : &mut i64, counter : &[i32], d2 : &mut [usize]) -> bool {
    if y + 1 >= interval_boundaries[interval+1] {return true ; }
    *count+= cnt_query((y + 1 - interval_boundaries[interval]),counter) as i64;
    d2[b] -= 1;
   false
    }

 #[inline]
pub fn easy_sparse(b :  usize , interval : usize, y : usize, n : usize, tt : &mut[u8], switch : &mut [bool],interval_boundaries : &[usize],
	 count : &mut i64, counter : &[i32], d2 : &mut [usize], pi : &[usize] ) -> bool  {
      if y >= n {
         if !switch[b] { switch[b]=true; return true; } else { tt[b] = 2 ; hard(b,interval,y,interval_boundaries,count,counter,d2); }
      }
      else {
         let l = pi[((y + 1) >> 1)] - b + 1;
         *count += l as i64;
         d2[b] -= 1;
      }
    false
    }

#[inline]
pub fn easy_clustered(b :  usize , interval : usize, y : usize, n : usize, tt: &mut[u8], switch : &mut [bool], interval_boundaries : &[usize],
	 count : &mut i64, counter : &[i32], d2 : &mut [usize], m : u64, pi : &[usize], p : &[usize] ) -> bool  {
     if y >= n {
        if !switch[b] { switch[b]=true; return true; } else { tt[b] = 2 ; hard(b,interval,y,interval_boundaries,count,counter,d2); }
      }
     else
      {
     let   l = pi[((y + 1) >> 1)] - b + 1;
     let  term = m / (p[b + 1] as u64 * p[b + l] as u64);
     let  dprime = pi[((term + 1) >> 1) as usize];
     if p[dprime + 1] <= int_sqrt((m / p[b + 1] as u64) as usize) || dprime <= b  {
         tt[b] = 1;
         *count += l as i64;
         d2[b] -= 1 ;
        }
      else
    {
      *count +=  (l as u32 * (d2[b] - dprime) as u32) as i64 ;
      d2[b] = dprime;
      }
    }
    false
      }

  #[inline]
    pub fn special_leaves_type_2(b: usize, interval : usize, d2 : &mut[usize], m : u64, p : &[usize], tt : &mut[u8],
    	 n : usize, switch : &mut[bool], interval_boundaries : &[usize], count : &mut i64, counter : &[i32], pi : &[usize] )  -> u32 {
    let mut s2bprimes= 0;
     loop {
      if d2[b] == b + 1 {return s2bprimes; }
      else
      {
       let y = (m / (p[b + 1] as u64 * p[d2[b]] as u64)) as usize;
       match tt[b] {
          0 => { if easy_clustered(b, interval, y, n, tt, switch, interval_boundaries, count, counter, d2, m, pi, p) { return s2bprimes;} continue ; } ,
          1 => { if easy_sparse(b,interval,y,n,tt,switch,interval_boundaries,count,counter,d2,pi) { return s2bprimes; }  continue ; } ,
          _ => { if (interval > 0 || counter[1] > 0) &&  hard(b,interval,y,interval_boundaries,count,counter,d2)  { return s2bprimes;} s2bprimes += 1 ; continue ; } ,
}
      }
      }
     }

  #[inline]
 pub fn sieve2( x : usize, y : usize,   p : &[usize],  block : &mut BitVec )
  {
block.clear();
   let mut i  = 1 ;
    while p[i] * p[i] <= y {
    let  mut offset = modneg(1 - x as i64, p[i]);
//    (offset..2+y-x).step(p[i]).foreach(|j| block.set(j,true) ) ;// more than twice the time - map/collect makes no difference
       while offset <= 1 + (y - x)  {
    	 block.set(offset,true);
         offset += p[i];
        }
       i += 1 ;
    }
}

 #[inline]
 pub fn p2(interval : usize, u : &mut usize, v :  &mut usize, n : usize, w : &mut usize,
   block : &mut BitVec , p : &[usize], m : u64 , interval_boundaries : &[usize], phi2 : &mut i64, counter : &[i32], a : usize  ) -> u32
      {
  let mut p2primes = 0;
loop {
    if *u <= n { *phi2 -= (*v as i64 * (*v - 1) as i64) >> 1 ; return p2primes;}
   	if *u  < *w  {
   		*w = cmp::max(2,*u -n);
   		sieve2(*w,*u+1,p,block) ;
   		    }
	let index = *u-*w+1;
    if !block[index] {
    let y  = (m / (*u as u64)) as usize;
    if y +1 >= interval_boundaries[interval + 1] { return p2primes; }
    *phi2 += (cnt_query((y + 1 - interval_boundaries[interval]), counter) as usize + a) as i64 - 1;
    p2primes += 1;
    *v += 1;
    }
    *u -= 2;
}
}

<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Aaron Loucks <aloucks+github@cofront.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::slice::Iter;
use std::hash::Hash;
use std::hash::Hasher;
use std::fmt::{self, Debug};
use std::ops::Index;

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Entity(u64);

const INVALID_ID: u64 = std::u64::MAX;
const INVALID_INDEX: usize = std::u32::MAX as usize;

impl Default for Entity {
    #[inline(always)]
    fn default() -> Entity {
        Entity(INVALID_ID)
    }
}

impl Debug for Entity {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Entity({{id: {}, key: {}, gen: {}}})", self.0, self.key(), self.gen())
    }
}

impl Hash for Entity {
    #[inline(always)]
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u64(self.0)
    }
}

impl Entity {
    #[inline(always)]
    fn from_key_and_gen(key: u32, gen: u32) -> Entity {
        Entity(((key as u64) << 32) | (gen as u64))
    }

    #[inline(always)]
    pub fn id(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn key(&self) -> u32 {
        (self.0 >> 32) as u32
    }

    #[inline(always)]
    pub fn gen(&self) -> u32 {
        (self.0 & 0xFFFFFFFF) as u32
    }
}

#[derive(Debug, Clone)]
pub struct EntityPool {
    entities: Vec<Entity>,
    entities_free: Vec<Entity>,
    entity_index: Vec<usize>, // entity_index[entity.key] => index; entities[index as usize]
    next_entity_key: u32,
}

impl Default for EntityPool {
    #[inline(always)]
    fn default() -> EntityPool {
        EntityPool::new()
    }
}

impl EntityPool {

    /// Creates a new, empty `EntityPool`.
    ///
    /// The `EntityPool` will not allocate until entities are created.
    ///
    pub fn new() -> EntityPool {
        EntityPool::with_capacity(0, 0)
    }

    /// Creates a new, empty `EntityPool` with the specified capacities.
    ///
    /// The `EntityPool` will able to create `create_capacity` and return `return_capacity`
    /// entities without reallocating. If either capacity is 0, their respective storage
    /// vectors will not allocate.
    pub fn with_capacity(create_capacity: usize, return_capacity: usize) -> EntityPool {
        EntityPool {
            entities: Vec::with_capacity(create_capacity),
            entities_free: Vec::with_capacity(return_capacity),
            entity_index: Vec::with_capacity(create_capacity),
            next_entity_key: 0
        }
    }

    /// Creates a unique entity.
    ///
    /// Returns the `Entity` and it's current `index`. The index is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    pub fn create_entity(&mut self) -> (usize, Entity) {
        let (key, gen) = match self.entities_free.pop() {
            Some(entity) => {
                (entity.key(), entity.gen().wrapping_add(1))
            },
            None => {
                let key = self.next_entity_key;
                self.next_entity_key = key + 1;
                (key, 0)
            }
        };
        let entity = Entity::from_key_and_gen(key, gen);
        let index = self.entities.len();
        self.entities.push(entity);
        if key as usize != self.entity_index.len() {
            self.entity_index[key as usize] = index;
        }
        else {
            debug_assert_eq!(key as usize, self.entity_index.len());
            self.entity_index.push(index);
        }
        (index, entity)
    }

    /// Release ownership of the `entity`, allowing for it to be recycled. A recycled entity will
    /// have it's internal generation incremented, yielding a new, unique entity.
    ///
    /// Entities are stored in contiguous memory. When an entity is returned, the last entity is
    /// swaped into the returned entity's slot; thus indexes retrieved prior to returning an
    /// entity are potentially invalidated.
    ///
    /// # Panics
    ///
    /// Returning an entity more than once, or an entity created from another pool, results in
    /// undefined behavior.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (_, e1) = pool.create_entity();
    /// pool.return_entity(e1);
    /// let (_, e2) = pool.create_entity();
    /// assert!(e1 != e2);
    /// ```
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (i1, e1) = pool.create_entity();
    /// let (i2, e2) = pool.create_entity();
    /// let (i3, e3) = pool.create_entity();
    /// assert_eq!(0, i1);
    /// assert_eq!(1, i2);
    /// assert_eq!(2, i3);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e2));
    /// assert_eq!(2, pool.index_of(e3));
    /// pool.return_entity(e2);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e3));
    /// ```
    pub fn return_entity(&mut self, entity: Entity) {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        self.entities_free.push(entity);
        self.entities.swap_remove(index);
        self.entity_index[key as usize] = INVALID_INDEX;
        match self.entities.get(index) {
            Some(e) => self.entity_index[e.key() as usize] = index,
            None    => {}
        };
    }

    /// Returns the current `index` of the given `entity`, which is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    #[inline(always)]
    pub fn index_of(&self, entity: Entity) -> usize {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize] as usize;
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        index
    }

    /// Returns the current `entity` at the given `index`.
    ///
    /// # Panics
    ///
    /// Panics if the index is greater or equal to the number of live entities in this pool.
    #[inline(always)]
    pub fn entity_at(&self, index: usize) -> Entity {
        self.entities[index]
    }

    /// Returns `true` if this entity has not been returned.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    pub fn is_alive(&self, entity: Entity) -> bool {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        if index != INVALID_INDEX {
            let other = self.entities[index];
            key == other.key() && entity.gen() == other.gen()
        }
        else {
            false
        }
    }

    /// Returns an iterator to the live entities. The `Enumerate` of the returned iterator will
    /// yield each `entity` and its current `index`.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// pool.create_entity();
    /// pool.create_entity();
    /// pool.create_entity();
    /// for (index, entity) in pool.iter().enumerate() {
    ///     assert_eq!(index, pool.index_of(*entity));
    ///     assert_eq!(*entity, pool.entity_at(index));
    /// }
    /// ```
    #[inline(always)]
    pub fn iter(&self) -> Iter<Entity> {
        self.entities.iter()
    }

    /// Resets the `EnitityPool` to its initial state, without releasing allocated capacity.
    ///
    /// All entities created prior to resetting are no longer considered members of this pool.
    pub fn reset(&mut self) {
        self.entities.clear();
        self.entities_free.clear();
        self.entity_index.clear();
        self.next_entity_key = 0;
    }

    /// Reserves capacity for at least `additional` more entities to be created without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve(&mut self, additional: usize) {
        self.entities.reserve(additional);
        self.entity_index.reserve(additional);
    }

    /// Reserves capacity for at least `additional` more entities to be returned without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve_returned(&mut self, additional: usize) {
        self.entities_free.reserve(additional);
    }

    /// Shrinks the capacity of this pool as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.entities.shrink_to_fit();
        self.entities_free.shrink_to_fit();
        self.entity_index.shrink_to_fit();
    }

    /// Returns the number of live entities in this pool.
    #[inline(always)]
    pub fn len(&self) -> usize {
        debug_assert_eq!(self.entities.len(), self.entity_index.len());
        self.entities.len()
    }

    /// Returns the number of returned entities in this pool that are ready to be recycled.
    #[inline(always)]
    pub fn len_returned(&self) -> usize {
        self.entities_free.len()
    }

    /// Returns the number of entities that this pool can create without reallocation.
    #[inline(always)]
    pub fn capacity(&self) -> usize {
        debug_assert_eq!(self.entities.capacity(), self.entity_index.capacity());
        self.entities.capacity()
    }

    /// Returns the number of entities that can be returned without reallocation.
    #[inline(always)]
    pub fn capacity_returned(&self) -> usize {
        self.entities_free.capacity()
    }
}

impl Index<usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: usize) -> &Entity {
        &self.entities[index]
    }
}

impl Index<Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

impl<'a> Index<&'a Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: &Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

impl<'a> Index<&'a usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: &usize) -> &Entity {
        &self.entities[*index]
    }
}

#[test]
fn it_works() {
    let mut pool = EntityPool::new();
    let mut entities = Vec::<Entity>::new();
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut alive = 5;
    for e in entities.iter() {
        pool.return_entity(*e);
        assert!(!pool.is_alive(*e));
        alive -= 1;
        let mut expected_alive = 0;
        for (i_alive, e_alive) in pool.iter().enumerate() {
            assert!(pool.is_alive(*e_alive));
            assert_eq!(i_alive, pool.index_of(*e_alive));
            assert_eq!(i_alive, pool[*e_alive]);
            assert_eq!(i_alive, pool[e_alive]);
            assert_eq!(*e_alive, pool.entity_at(i_alive));
            assert_eq!(*e_alive, pool[i_alive]);
            assert_eq!(*e_alive, pool[&i_alive]);
            expected_alive += 1;
        }
        assert_eq!(expected_alive, alive);
    }
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut count = 0;
    for (index, e) in pool.iter().enumerate() {
        assert_eq!(index, pool.index_of(*e));
        assert_eq!(index, pool[e]);
        assert_eq!(*e, pool.entity_at(index));
        assert_eq!(*e, pool[index]);
        assert!(pool.is_alive(*e));
        count += 1;
    }
    assert_eq!(5, count);
}
<commit_msg>Moving Index impl block<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Aaron Loucks <aloucks+github@cofront.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::slice::Iter;
use std::hash::Hash;
use std::hash::Hasher;
use std::fmt::{self, Debug};
use std::ops::Index;

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Entity(u64);

const INVALID_ID: u64 = std::u64::MAX;
const INVALID_INDEX: usize = std::u32::MAX as usize;

impl Default for Entity {
    #[inline(always)]
    fn default() -> Entity {
        Entity(INVALID_ID)
    }
}

impl Debug for Entity {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Entity({{id: {}, key: {}, gen: {}}})", self.0, self.key(), self.gen())
    }
}

impl Hash for Entity {
    #[inline(always)]
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u64(self.0)
    }
}

impl Entity {
    #[inline(always)]
    fn from_key_and_gen(key: u32, gen: u32) -> Entity {
        Entity(((key as u64) << 32) | (gen as u64))
    }

    #[inline(always)]
    pub fn id(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn key(&self) -> u32 {
        (self.0 >> 32) as u32
    }

    #[inline(always)]
    pub fn gen(&self) -> u32 {
        (self.0 & 0xFFFFFFFF) as u32
    }
}

#[derive(Debug, Clone)]
pub struct EntityPool {
    entities: Vec<Entity>,
    entities_free: Vec<Entity>,
    entity_index: Vec<usize>, // entity_index[entity.key] => index; entities[index as usize]
    next_entity_key: u32,
}

impl Default for EntityPool {
    #[inline(always)]
    fn default() -> EntityPool {
        EntityPool::new()
    }
}

impl EntityPool {

    /// Creates a new, empty `EntityPool`.
    ///
    /// The `EntityPool` will not allocate until entities are created.
    ///
    pub fn new() -> EntityPool {
        EntityPool::with_capacity(0, 0)
    }

    /// Creates a new, empty `EntityPool` with the specified capacities.
    ///
    /// The `EntityPool` will able to create `create_capacity` and return `return_capacity`
    /// entities without reallocating. If either capacity is 0, their respective storage
    /// vectors will not allocate.
    pub fn with_capacity(create_capacity: usize, return_capacity: usize) -> EntityPool {
        EntityPool {
            entities: Vec::with_capacity(create_capacity),
            entities_free: Vec::with_capacity(return_capacity),
            entity_index: Vec::with_capacity(create_capacity),
            next_entity_key: 0
        }
    }

    /// Creates a unique entity.
    ///
    /// Returns the `Entity` and it's current `index`. The index is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    pub fn create_entity(&mut self) -> (usize, Entity) {
        let (key, gen) = match self.entities_free.pop() {
            Some(entity) => {
                (entity.key(), entity.gen().wrapping_add(1))
            },
            None => {
                let key = self.next_entity_key;
                self.next_entity_key = key + 1;
                (key, 0)
            }
        };
        let entity = Entity::from_key_and_gen(key, gen);
        let index = self.entities.len();
        self.entities.push(entity);
        if key as usize != self.entity_index.len() {
            self.entity_index[key as usize] = index;
        }
        else {
            debug_assert_eq!(key as usize, self.entity_index.len());
            self.entity_index.push(index);
        }
        (index, entity)
    }

    /// Release ownership of the `entity`, allowing for it to be recycled. A recycled entity will
    /// have it's internal generation incremented, yielding a new, unique entity.
    ///
    /// Entities are stored in contiguous memory. When an entity is returned, the last entity is
    /// swaped into the returned entity's slot; thus indexes retrieved prior to returning an
    /// entity are potentially invalidated.
    ///
    /// # Panics
    ///
    /// Returning an entity more than once, or an entity created from another pool, results in
    /// undefined behavior.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (_, e1) = pool.create_entity();
    /// pool.return_entity(e1);
    /// let (_, e2) = pool.create_entity();
    /// assert!(e1 != e2);
    /// ```
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (i1, e1) = pool.create_entity();
    /// let (i2, e2) = pool.create_entity();
    /// let (i3, e3) = pool.create_entity();
    /// assert_eq!(0, i1);
    /// assert_eq!(1, i2);
    /// assert_eq!(2, i3);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e2));
    /// assert_eq!(2, pool.index_of(e3));
    /// pool.return_entity(e2);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e3));
    /// ```
    pub fn return_entity(&mut self, entity: Entity) {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        self.entities_free.push(entity);
        self.entities.swap_remove(index);
        self.entity_index[key as usize] = INVALID_INDEX;
        match self.entities.get(index) {
            Some(e) => self.entity_index[e.key() as usize] = index,
            None    => {}
        };
    }

    /// Returns the current `index` of the given `entity`, which is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    #[inline(always)]
    pub fn index_of(&self, entity: Entity) -> usize {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize] as usize;
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        index
    }

    /// Returns the current `entity` at the given `index`.
    ///
    /// # Panics
    ///
    /// Panics if the index is greater or equal to the number of live entities in this pool.
    #[inline(always)]
    pub fn entity_at(&self, index: usize) -> Entity {
        self.entities[index]
    }

    /// Returns `true` if this entity has not been returned.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    pub fn is_alive(&self, entity: Entity) -> bool {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        if index != INVALID_INDEX {
            let other = self.entities[index];
            key == other.key() && entity.gen() == other.gen()
        }
        else {
            false
        }
    }

    /// Returns an iterator to the live entities. The `Enumerate` of the returned iterator will
    /// yield each `entity` and its current `index`.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// pool.create_entity();
    /// pool.create_entity();
    /// pool.create_entity();
    /// for (index, entity) in pool.iter().enumerate() {
    ///     assert_eq!(index, pool.index_of(*entity));
    ///     assert_eq!(*entity, pool.entity_at(index));
    /// }
    /// ```
    #[inline(always)]
    pub fn iter(&self) -> Iter<Entity> {
        self.entities.iter()
    }

    /// Resets the `EnitityPool` to its initial state, without releasing allocated capacity.
    ///
    /// All entities created prior to resetting are no longer considered members of this pool.
    pub fn reset(&mut self) {
        self.entities.clear();
        self.entities_free.clear();
        self.entity_index.clear();
        self.next_entity_key = 0;
    }

    /// Reserves capacity for at least `additional` more entities to be created without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve(&mut self, additional: usize) {
        self.entities.reserve(additional);
        self.entity_index.reserve(additional);
    }

    /// Reserves capacity for at least `additional` more entities to be returned without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve_returned(&mut self, additional: usize) {
        self.entities_free.reserve(additional);
    }

    /// Shrinks the capacity of this pool as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.entities.shrink_to_fit();
        self.entities_free.shrink_to_fit();
        self.entity_index.shrink_to_fit();
    }

    /// Returns the number of live entities in this pool.
    #[inline(always)]
    pub fn len(&self) -> usize {
        debug_assert_eq!(self.entities.len(), self.entity_index.len());
        self.entities.len()
    }

    /// Returns the number of returned entities in this pool that are ready to be recycled.
    #[inline(always)]
    pub fn len_returned(&self) -> usize {
        self.entities_free.len()
    }

    /// Returns the number of entities that this pool can create without reallocation.
    #[inline(always)]
    pub fn capacity(&self) -> usize {
        debug_assert_eq!(self.entities.capacity(), self.entity_index.capacity());
        self.entities.capacity()
    }

    /// Returns the number of entities that can be returned without reallocation.
    #[inline(always)]
    pub fn capacity_returned(&self) -> usize {
        self.entities_free.capacity()
    }
}

impl Index<usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: usize) -> &Entity {
        &self.entities[index]
    }
}

impl Index<Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

impl<'a> Index<&'a usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: &usize) -> &Entity {
        &self.entities[*index]
    }
}

impl<'a> Index<&'a Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: &Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

#[test]
fn it_works() {
    let mut pool = EntityPool::new();
    let mut entities = Vec::<Entity>::new();
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut alive = 5;
    for e in entities.iter() {
        pool.return_entity(*e);
        assert!(!pool.is_alive(*e));
        alive -= 1;
        let mut expected_alive = 0;
        for (i_alive, e_alive) in pool.iter().enumerate() {
            assert!(pool.is_alive(*e_alive));
            assert_eq!(i_alive, pool.index_of(*e_alive));
            assert_eq!(i_alive, pool[*e_alive]);
            assert_eq!(i_alive, pool[e_alive]);
            assert_eq!(*e_alive, pool.entity_at(i_alive));
            assert_eq!(*e_alive, pool[i_alive]);
            assert_eq!(*e_alive, pool[&i_alive]);
            expected_alive += 1;
        }
        assert_eq!(expected_alive, alive);
    }
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut count = 0;
    for (index, e) in pool.iter().enumerate() {
        assert_eq!(index, pool.index_of(*e));
        assert_eq!(index, pool[e]);
        assert_eq!(*e, pool.entity_at(index));
        assert_eq!(*e, pool[index]);
        assert!(pool.is_alive(*e));
        count += 1;
    }
    assert_eq!(5, count);
}
<|endoftext|>


<commit_before>//! Hash-consing with automated release of unused values

#[macro_use]
extern crate log;

use std::ops::{Deref, Drop};
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
use std::cell::UnsafeCell;

/// Box that encapsulates a value to hash-cons, a reference to the conser, and a reference counter.
struct HashConsedBox<T>
    where T: Hash + Eq
{
    value: T,
    conser: HashConser<T>,
    refs: usize,
}

/// Unsafed reference to a hash-consed value
///
/// It is simply a pointer to the hash-consed box that encapsulate the raw value,
/// a reference to the conser and the current number of references.
///
/// **N.B.:** An unsafed hash-consed value:
///
///   * may or may not be in the conser's map,
///
///   * should be `destroy()`-ed manually,
///
///   * does not update automatically the ref count,
///
///   * inherits PartialEq, Eq, and Hash from the raw value.
struct UnsafeRef<T>(*mut UnsafeCell<HashConsedBox<T>>) where T: Hash + Eq;

impl<T> UnsafeRef<T> where T: Hash + Eq {

    /// Make an unsafed reference to a owned hash-consed box
    #[inline]
    fn make(conser: &HashConser<T>, value: T) -> Self {
        UnsafeRef(Box::into_raw(Box::new(UnsafeCell::new(HashConsedBox {
            value: value,
            conser: conser.copy(),
            refs: 0,
        }))))
    }

    /// Destroy (drop) the underlying hash-consed box
    #[inline]
    fn destroy(&self) {
        drop(unsafe { Box::from_raw(self.0) });
    }

    /// Get pointer to conser
    #[inline]
    fn conser(&mut self) -> *mut HashConser<T> {
        unsafe { &mut (*self.as_ptr()).conser as *mut HashConser<T> }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*self.as_ptr()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs += 1;
    }

    #[inline]
    fn dec_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs -= 1;
    }

    #[inline]
    fn value(&self) -> &T {
        unsafe { &(*self.as_ptr()).value }
    }

    #[inline]
    fn as_ptr(&self) -> *mut HashConsedBox<T> {
        unsafe { (*self.0).get() }
    }
}

/// Hash the underlying value
impl<T> Hash for UnsafeRef<T> where T: Hash + Eq {

    #[inline]
    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.value().hash(h);
    }

}

/// Compare the underlying values
impl<T> PartialEq<UnsafeRef<T>> for UnsafeRef<T> where T: Hash + Eq {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.value() == other.value()
    }

}

impl<T> Eq for UnsafeRef<T> where T: Hash + Eq {
}

/// Clone a new reference to the hash-consed value
impl<T> Clone for UnsafeRef<T> where T: Hash + Eq {

    #[inline]
    fn clone(&self) -> Self {
        UnsafeRef(self.0)
    }

}

impl<T> Copy for UnsafeRef<T> where T: Hash + Eq {}

/// Reference to a hash-consed value.
///
/// Built through a `HashConser`, it points to a single copy of the raw value existing in the
/// `HashConser`.
///
/// Uses fast pointer equality and hash.
pub struct HashConsed<T>(UnsafeRef<T>) where T: Hash + Eq;

impl<T> HashConsed<T> where T: Hash + Eq {
    /// Wrap an unsafe reference
    fn from_unsafe(u: &UnsafeRef<T>) -> Self {
        u.inc_refs();
        debug!("new ref {:p} ({} ref total)", u.value(), u.refs());
        HashConsed(*u)
    }

    /// Get underlying value
    #[inline]
    pub fn value(&self) -> &T {
        self.0.value()
    }

    /// Get number of references
    #[cfg(test)]
    pub fn refs(&self) -> usize {
        self.0.refs()
    }
}

/// Get reference to the raw value
impl<T> Deref for HashConsed<T> where T: Hash + Eq {
  type Target = T;
    fn deref(&self) -> &T {
        return self.value();
    }
}

/// Fast hash (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`.
impl<T> Hash for HashConsed<T> where T: Hash + Eq {
    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.0.as_ptr().hash(h);
    }
}

/// Fast comparison (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`
impl<T> PartialEq<HashConsed<T>> for HashConsed<T> where T: Hash + Eq {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.0.as_ptr() == other.0.as_ptr()
    }
}

impl<T> Eq for HashConsed<T> where T: Hash + Eq {}

impl<T> Drop for HashConsed<T> where T: Hash + Eq {
    fn drop(&mut self) {
        if self.0.refs() == 0 {
            panic!();
        } else {
            self.0.dec_refs();
            debug!("del ref {:p} ({} refs remaining)",
                   self.0.value(),
                   self.0.refs());
            if self.0.refs() == 0 {
                debug!("del val {:p}", self.value());
                let conser = unsafe { &mut *self.0.conser() };
                conser.remove(&self.0);
                self.0.destroy();
            }
        }
    }
}

impl<T> Debug for HashConsed<T> where T: Hash + Eq + Debug {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.0.value(), fmt)
    }
}

/// Get a new reference to this hash-consed value.
impl<T> Clone for HashConsed<T> where T: Hash + Eq {
    fn clone(&self) -> Self {
        self.0.inc_refs();
        debug!("new ref {:p} (clone, {} refs total)",
               self.0.value(),
               self.0.refs());
        HashConsed(self.0)
    }
}

type HM<T> where T: Hash + Eq = HashMap<UnsafeRef<T>, UnsafeRef<T>>;

/// Hash-conser, i.e. hash-consed value factory and cache.
pub struct HashConser<T>(*mut UnsafeCell<HM<T>>) where T: Hash + Eq;

impl<T> HashConser<T> where T: Hash + Eq {

    /// Create a hash-conser.
    pub fn new() -> Self {
        HashConser(Box::into_raw(Box::new(UnsafeCell::new(HashMap::new()))))
    }

    #[inline]
    fn map(&self) -> &mut HM<T> {
        unsafe { &mut (*(*self.0).get()) }
    }

    /// Make a hash-consed value from an unwrapped value
    pub fn make(&mut self, obj: T) -> HashConsed<T> {
        debug!("h-cons  {:p} in {:p}", &obj, self);
        let input = UnsafeRef::make(self, obj);
        let map = self.map();
        let safe = match map.get(&input) {
            Some(output) => {
                debug!("recycle {:p} (already {} refs)",
                       output.value(),
                       output.refs());
                input.destroy();
                HashConsed::from_unsafe(output)
            }
            None => {
                debug!("new val {:p} in {:p}", input.value(), self);
                self.map().insert(input.clone(), input);
                HashConsed::from_unsafe(&input)
            }
        };
        debug!("/h-cons");
        safe
    }

    #[inline]
    fn remove(&mut self, hc: &UnsafeRef<T>) {
        self.map().remove(hc);
    }

    /// Private: get a new reference of the conference
    ///
    /// WARNING! no reference counting
    ///
    /// *Invariant:* the number of references is the number of hash-consed values plus one if the
    /// user stills holds the ref
    #[inline]
    fn copy(&self) -> Self {
        HashConser(self.0)
    }
}

impl<T> Drop for HashConser<T> where T: Hash + Eq {
    fn drop(&mut self) {
        debug!("del ref HashConser({:p}) ({} refs remaining)",
               self.0,
               self.map().len());
        if self.map().len() == 0 {
            debug!("del val HashConser({:p})", self.0);
            let b = unsafe { Box::from_raw(self.0) };
            drop(b);
        }
    }
}

impl<T> Debug for HashConser<T> where T: Hash + Eq + Debug {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str("{"));
        for (i, k) in self.map().keys().enumerate() {
            if i != 0 {
                try!(fmt.write_str(", "));
            }
            try!(write!(fmt, "{:?} ({})", k.value(), k.refs()));
        }
        fmt.write_str("}")
    }
}

#[test]
fn it_works() {}
<commit_msg>Improve formatting<commit_after>//! Hash-consing with automated release of unused values

#[macro_use]
extern crate log;

use std::ops::{Deref, Drop};
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
use std::cell::UnsafeCell;

/// Box that encapsulates a value to hash-cons, a reference to the conser,
/// and a reference counter
struct HashConsedBox<T>
    where T: Eq + Hash
{
    value: T,
    conser: HashConser<T>,
    refs: usize,
}

/// Unsafed reference to a hash-consed value
///
/// It is simply a pointer to the hash-consed box that encapsulate the raw value,
/// a reference to the conser and the current number of references.
///
/// **N.B.:** An unsafed hash-consed value:
///
///   * may or may not be in the conser's map,
///
///   * should be `destroy()`-ed manually,
///
///   * does not update automatically the ref count,
///
///   * inherits PartialEq, Eq, and Hash from the raw value.
struct UnsafeRef<T>(*mut UnsafeCell<HashConsedBox<T>>) where T: Eq + Hash;

impl<T> UnsafeRef<T> where T: Eq + Hash {

    /// Make an unsafed reference to a owned hash-consed box
    #[inline]
    fn make(conser: &HashConser<T>, value: T) -> Self {
        UnsafeRef(Box::into_raw(Box::new(UnsafeCell::new(HashConsedBox {
            value: value,
            conser: conser.copy(),
            refs: 0,
        }))))
    }

    /// Destroy (drop) the underlying hash-consed box
    #[inline]
    fn destroy(&self) {
        drop(unsafe { Box::from_raw(self.0) });
    }

    /// Get pointer to conser
    #[inline]
    fn conser(&mut self) -> *mut HashConser<T> {
        unsafe { &mut (*self.as_ptr()).conser as *mut HashConser<T> }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*self.as_ptr()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs += 1;
    }

    #[inline]
    fn dec_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs -= 1;
    }

    #[inline]
    fn value(&self) -> &T {
        unsafe { &(*self.as_ptr()).value }
    }

    #[inline]
    fn as_ptr(&self) -> *mut HashConsedBox<T> {
        unsafe { (*self.0).get() }
    }
}

/// Hash the underlying value
impl<T> Hash for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.value().hash(h);
    }

}

/// Compare the underlying values
impl<T> PartialEq<UnsafeRef<T>> for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.value() == other.value()
    }

}

impl<T> Eq for UnsafeRef<T> where T: Eq + Hash {
}

/// Clone a new reference to the hash-consed value
impl<T> Clone for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn clone(&self) -> Self {
        UnsafeRef(self.0)
    }

}

impl<T> Copy for UnsafeRef<T> where T: Eq + Hash {}

/// Reference to a hash-consed value.
///
/// Built through a `HashConser`, it points to a single copy of the raw value existing in the
/// `HashConser`.
///
/// Uses fast pointer equality and hash.
pub struct HashConsed<T>(UnsafeRef<T>) where T: Eq + Hash;

impl<T> HashConsed<T> where T: Eq + Hash {

    /// Wrap an unsafe reference
    fn from_unsafe(u: &UnsafeRef<T>) -> Self {
        u.inc_refs();
        debug!("new ref {:p} ({} ref total)", u.value(), u.refs());
        HashConsed(*u)
    }

    /// Get underlying value
    #[inline]
    pub fn value(&self) -> &T {
        self.0.value()
    }

    /// Get number of references
    #[cfg(test)]
    pub fn refs(&self) -> usize {
        self.0.refs()
    }

}

/// Get reference to the raw value
impl<T> Deref for HashConsed<T> where T: Eq + Hash {

    type Target = T;

    fn deref(&self) -> &T {
        return self.value();
    }

}

/// Fast hash (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`.
impl<T> Hash for HashConsed<T> where T: Eq + Hash {

    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.0.as_ptr().hash(h);
    }

}

/// Fast comparison (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`
impl<T> PartialEq<HashConsed<T>> for HashConsed<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.0.as_ptr() == other.0.as_ptr()
    }

}

impl<T> Eq for HashConsed<T> where T: Eq + Hash {}

impl<T> Drop for HashConsed<T> where T: Eq + Hash {

    fn drop(&mut self) {
        self.0.dec_refs();
        debug!("del ref {:p} ({} refs remaining)",
               self.0.value(),
               self.0.refs());
        if self.0.refs() == 0 {
            debug!("del val {:p}", self.value());
            let conser = unsafe { &mut *self.0.conser() };
            conser.remove(&self.0);
            self.0.destroy();
        }
    }

}

impl<T> Debug for HashConsed<T> where T: Eq + Hash + Debug {

    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.0.value(), fmt)
    }

}

/// Get a new reference to this hash-consed value.
impl<T> Clone for HashConsed<T> where T: Eq + Hash {
    fn clone(&self) -> Self {
        self.0.inc_refs();
        debug!("new ref {:p} (clone, {} refs total)",
               self.0.value(),
               self.0.refs());
        HashConsed(self.0)
    }
}

type HM<T> where T: Eq + Hash = HashMap<UnsafeRef<T>, UnsafeRef<T>>;

/// Hash-conser, i.e. hash-consed value factory and cache.
pub struct HashConser<T>(*mut UnsafeCell<HM<T>>) where T: Eq + Hash;

impl<T> HashConser<T> where T: Eq + Hash {

    /// Create a hash-conser.
    pub fn new() -> Self {
        HashConser(Box::into_raw(Box::new(UnsafeCell::new(HashMap::new()))))
    }

    #[inline]
    fn map(&self) -> &mut HM<T> {
        unsafe { &mut (*(*self.0).get()) }
    }

    /// Make a hash-consed value from an unwrapped value
    pub fn make(&mut self, obj: T) -> HashConsed<T> {
        debug!("h-cons  {:p} in {:p}", &obj, self);
        let input = UnsafeRef::make(self, obj);
        let map = self.map();
        let safe = match map.get(&input) {
            Some(output) => {
                debug!("recycle {:p} (already {} refs)",
                       output.value(),
                       output.refs());
                input.destroy();
                HashConsed::from_unsafe(output)
            }
            None => {
                debug!("new val {:p} in {:p}", input.value(), self);
                self.map().insert(input.clone(), input);
                HashConsed::from_unsafe(&input)
            }
        };
        debug!("/h-cons");
        safe
    }

    #[inline]
    fn remove(&mut self, hc: &UnsafeRef<T>) {
        self.map().remove(hc);
    }

    /// Private: get a new reference of the conference
    ///
    /// WARNING! no reference counting
    ///
    /// *Invariant:* the number of references is the number of hash-consed values plus one if the
    /// user stills holds the ref
    #[inline]
    fn copy(&self) -> Self {
        HashConser(self.0)
    }
}

impl<T> Drop for HashConser<T> where T: Eq + Hash {
    fn drop(&mut self) {
        debug!("del ref HashConser({:p}) ({} refs remaining)",
               self.0,
               self.map().len());
        if self.map().len() == 0 {
            debug!("del val HashConser({:p})", self.0);
            let b = unsafe { Box::from_raw(self.0) };
            drop(b);
        }
    }
}

impl<T> Debug for HashConser<T> where T: Eq + Hash + Debug {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str("{"));
        for (i, k) in self.map().keys().enumerate() {
            if i != 0 {
                try!(fmt.write_str(", "));
            }
            try!(write!(fmt, "{:?} ({})", k.value(), k.refs()));
        }
        fmt.write_str("}")
    }
}

#[test]
fn it_works() {}
<|endoftext|>


<commit_before>use crate::{
    auth::{Credentials, SASLMechanism},
    Connection, ConnectionProperties, PromiseResolver,
};
use parking_lot::Mutex;
use std::{fmt, sync::Arc};

#[derive(Clone, Default)]
pub struct ConnectionStatus(Arc<Mutex<Inner>>);

impl ConnectionStatus {
    pub fn state(&self) -> ConnectionState {
        self.0.lock().state.clone()
    }

    pub(crate) fn set_state(&self, state: ConnectionState) {
        self.0.lock().state = state;
    }

    pub(crate) fn connection_step(&self) -> Option<ConnectionStep> {
        self.0.lock().connection_step.take()
    }

    pub(crate) fn set_connection_step(&self, connection_step: ConnectionStep) {
        self.0.lock().connection_step = Some(connection_step);
    }

    pub(crate) fn connection_resolver(&self) -> Option<PromiseResolver<Connection>> {
        self.0.lock().connection_resolver()
    }

    pub fn vhost(&self) -> String {
        self.0.lock().vhost.clone()
    }

    pub(crate) fn set_vhost(&self, vhost: &str) {
        self.0.lock().vhost = vhost.into();
    }

    pub fn username(&self) -> String {
        self.0.lock().username.clone()
    }

    pub(crate) fn set_username(&self, username: &str) {
        self.0.lock().username = username.into();
    }

    pub(crate) fn block(&self) {
        self.0.lock().blocked = true;
    }

    pub(crate) fn unblock(&self) {
        self.0.lock().blocked = false;
    }

    pub fn blocked(&self) -> bool {
        self.0.lock().blocked
    }

    pub fn connected(&self) -> bool {
        self.0.lock().state == ConnectionState::Connected
    }

    pub fn closing(&self) -> bool {
        self.0.lock().state == ConnectionState::Closing
    }

    pub fn closed(&self) -> bool {
        self.0.lock().state == ConnectionState::Closed
    }

    pub fn errored(&self) -> bool {
        self.0.lock().state == ConnectionState::Error
    }

    pub(crate) fn auto_close(&self) -> bool {
        [ConnectionState::Connecting, ConnectionState::Connected].contains(&self.0.lock().state)
    }
}

#[allow(clippy::large_enum_variant)]
pub(crate) enum ConnectionStep {
    ProtocolHeader(
        PromiseResolver<Connection>,
        Connection,
        Credentials,
        SASLMechanism,
        ConnectionProperties,
    ),
    StartOk(PromiseResolver<Connection>, Connection, Credentials),
    Open(PromiseResolver<Connection>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConnectionState {
    Initial,
    Connecting,
    Connected,
    Closing,
    Closed,
    Error,
}

impl Default for ConnectionState {
    fn default() -> Self {
        ConnectionState::Initial
    }
}

impl fmt::Debug for ConnectionStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut debug = f.debug_struct("ConnectionStatus");
        if let Some(inner) = self.0.try_lock() {
            debug
                .field("state", &inner.state)
                .field("vhost", &inner.vhost)
                .field("username", &inner.username)
                .field("blocked", &inner.blocked);
        }
        debug.finish()
    }
}

struct Inner {
    connection_step: Option<ConnectionStep>,
    state: ConnectionState,
    vhost: String,
    username: String,
    blocked: bool,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            connection_step: None,
            state: ConnectionState::default(),
            vhost: "/".into(),
            username: "guest".into(),
            blocked: false,
        }
    }
}

impl Inner {
    fn connection_resolver(&mut self) -> Option<PromiseResolver<Connection>> {
        if let ConnectionState::Connecting = self.state {
            self.connection_step
                .take()
                .map(|connection_step| match connection_step {
                    ConnectionStep::ProtocolHeader(resolver, ..) => resolver,
                    ConnectionStep::StartOk(resolver, ..) => resolver,
                    ConnectionStep::Open(resolver, ..) => resolver,
                })
        } else {
            None
        }
    }
}
<commit_msg>avoid deadlock when we cannot connect<commit_after>use crate::{
    auth::{Credentials, SASLMechanism},
    Connection, ConnectionProperties, PromiseResolver,
};
use parking_lot::Mutex;
use std::{fmt, sync::Arc};

#[derive(Clone, Default)]
pub struct ConnectionStatus(Arc<Mutex<Inner>>);

impl ConnectionStatus {
    pub fn state(&self) -> ConnectionState {
        self.0.lock().state.clone()
    }

    pub(crate) fn set_state(&self, state: ConnectionState) {
        self.0.lock().state = state;
    }

    pub(crate) fn connection_step(&self) -> Option<ConnectionStep> {
        self.0.lock().connection_step.take()
    }

    pub(crate) fn set_connection_step(&self, connection_step: ConnectionStep) {
        self.0.lock().connection_step = Some(connection_step);
    }

    pub(crate) fn connection_resolver(&self) -> Option<PromiseResolver<Connection>> {
        let resolver = self.0.lock().connection_resolver();
        // We carry the Connection here to drop the lock() above before dropping the Connection
        resolver.map(|(resolver, _connection)| resolver)
    }

    pub fn vhost(&self) -> String {
        self.0.lock().vhost.clone()
    }

    pub(crate) fn set_vhost(&self, vhost: &str) {
        self.0.lock().vhost = vhost.into();
    }

    pub fn username(&self) -> String {
        self.0.lock().username.clone()
    }

    pub(crate) fn set_username(&self, username: &str) {
        self.0.lock().username = username.into();
    }

    pub(crate) fn block(&self) {
        self.0.lock().blocked = true;
    }

    pub(crate) fn unblock(&self) {
        self.0.lock().blocked = false;
    }

    pub fn blocked(&self) -> bool {
        self.0.lock().blocked
    }

    pub fn connected(&self) -> bool {
        self.0.lock().state == ConnectionState::Connected
    }

    pub fn closing(&self) -> bool {
        self.0.lock().state == ConnectionState::Closing
    }

    pub fn closed(&self) -> bool {
        self.0.lock().state == ConnectionState::Closed
    }

    pub fn errored(&self) -> bool {
        self.0.lock().state == ConnectionState::Error
    }

    pub(crate) fn auto_close(&self) -> bool {
        [ConnectionState::Connecting, ConnectionState::Connected].contains(&self.0.lock().state)
    }
}

#[allow(clippy::large_enum_variant)]
pub(crate) enum ConnectionStep {
    ProtocolHeader(
        PromiseResolver<Connection>,
        Connection,
        Credentials,
        SASLMechanism,
        ConnectionProperties,
    ),
    StartOk(PromiseResolver<Connection>, Connection, Credentials),
    Open(PromiseResolver<Connection>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ConnectionState {
    Initial,
    Connecting,
    Connected,
    Closing,
    Closed,
    Error,
}

impl Default for ConnectionState {
    fn default() -> Self {
        ConnectionState::Initial
    }
}

impl fmt::Debug for ConnectionStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut debug = f.debug_struct("ConnectionStatus");
        if let Some(inner) = self.0.try_lock() {
            debug
                .field("state", &inner.state)
                .field("vhost", &inner.vhost)
                .field("username", &inner.username)
                .field("blocked", &inner.blocked);
        }
        debug.finish()
    }
}

struct Inner {
    connection_step: Option<ConnectionStep>,
    state: ConnectionState,
    vhost: String,
    username: String,
    blocked: bool,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            connection_step: None,
            state: ConnectionState::default(),
            vhost: "/".into(),
            username: "guest".into(),
            blocked: false,
        }
    }
}

impl Inner {
    fn connection_resolver(&mut self) -> Option<(PromiseResolver<Connection>, Option<Connection>)> {
        if let ConnectionState::Connecting = self.state {
            self.connection_step
                .take()
                .map(|connection_step| match connection_step {
                    ConnectionStep::ProtocolHeader(resolver, connection, ..) => (resolver, Some(connection)),
                    ConnectionStep::StartOk(resolver, connection, ..) => (resolver, Some(connection)),
                    ConnectionStep::Open(resolver, ..) => (resolver, None),
                })
        } else {
            None
        }
    }
}
<|endoftext|>