<commit_before>//! Window creation using glutin for gfx.
//!
//! # Examples
//!
//! The following code creates a `gfx::Surface` using glutin.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_backend_gl;
//!
//! fn main() {
//!     use gfx_backend_gl::Surface;
//!     use glutin::{EventsLoop, WindowBuilder, ContextBuilder, GlWindow};
//!
//!     // First create a window using glutin.
//!     let mut events_loop = EventsLoop::new();
//!     let wb = WindowBuilder::new();
//!     let cb = ContextBuilder::new().with_vsync(true);
//!     let glutin_window = GlWindow::new(wb, cb, &events_loop).unwrap();
//!
//!     // Then use the glutin window to create a gfx surface.
//!     let surface = Surface::from_window(glutin_window);
//! }
//! ```
//!
//! Headless initialization without a window.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_backend_gl;
//! extern crate gfx_hal;
//!
//! use gfx_hal::Instance;
//! use gfx_backend_gl::Headless;
//! use glutin::{HeadlessRendererBuilder};
//!
//! fn main() {
//!     let context = HeadlessRendererBuilder::new(256, 256)
//!         .build()
//!         .expect("Failed to build headless context");
//!     let headless = Headless(context);
//!     let _adapters = headless.enumerate_adapters();
//! }
//! ```

use hal::{self, format as f, image};

use {Backend as B, Device, PhysicalDevice, QueueFamily};

use glutin::{self, GlContext};
use Starc;

fn get_window_dimensions(window: &glutin::GlWindow) -> image::Dimensions {
    let (width, height) = window.get_inner_size().unwrap();
    let aa = window.get_pixel_format().multisampling
                   .unwrap_or(0) as image::NumSamples;
    ((width as f32 * window.hidpi_factor()) as image::Size, (height as f32 * window.hidpi_factor()) as image::Size, 1, aa.into())
}

pub struct Swapchain {
    // Underlying window, required for presentation
    pub(crate) window: Starc<glutin::GlWindow>,
}

impl hal::Swapchain<B> for Swapchain {
    fn acquire_frame(&mut self, _sync: hal::FrameSync<B>) -> hal::Frame {
        // TODO: sync
        hal::Frame::new(0)
    }
}

//TODO: if we make `Surface` a `WindowBuilder` instead of `GlWindow`,
// we could spawn window + GL context when a swapchain is requested
// and actually respect the swapchain configuration provided by the user.
pub struct Surface {
    window: Starc<glutin::GlWindow>,
}

impl Surface {
    pub fn from_window(window: glutin::GlWindow) -> Self {
        Surface {
            window: Starc::new(window)
        }
    }

    fn swapchain_formats(&self) -> Vec<f::Format> {
        let pixel_format = self.window.get_pixel_format();
        let color_bits = pixel_format.color_bits;
        let alpha_bits = pixel_format.alpha_bits;
        let srgb = pixel_format.srgb;

        // TODO: expose more formats
        match (color_bits, alpha_bits, srgb) {
            (24, 8, true) => vec![
                f::Format::Rgba8Srgb,
                f::Format::Bgra8Srgb,
            ],
            (24, 8, false) => vec![
                f::Format::Rgba8Unorm,
                f::Format::Bgra8Unorm,
            ],
            _ => vec![],
        }
    }
}

impl hal::Surface<B> for Surface {
    fn kind(&self) -> hal::image::Kind {
        let (w, h, _, a) = get_window_dimensions(&self.window);
        hal::image::Kind::D2(w, h, a)
    }

    fn capabilities_and_formats(&self, _: &PhysicalDevice) -> (hal::SurfaceCapabilities, Option<Vec<f::Format>>) {
        let dim = get_window_dimensions(&self.window);
        let extent = hal::window::Extent2D {
            width: dim.0 as u32,
            height: dim.1 as u32,
        };

        (hal::SurfaceCapabilities {
            image_count: if self.window.get_pixel_format().double_buffer { 2..3 } else { 1..2 },
            current_extent: Some(extent),
            extents: extent..hal::window::Extent2D {
                width: dim.0 as u32 + 1,
                height: dim.1 as u32 + 1
            },
            max_image_layers: 1,
        }, Some(self.swapchain_formats()))
    }

    fn supports_queue_family(&self, _: &QueueFamily) -> bool { true }
}

impl Device {
    pub(crate) fn create_swapchain_impl(
        &self,
        surface: &mut Surface,
        _config: hal::SwapchainConfig,
    ) -> (Swapchain, hal::Backbuffer<B>) {
        let swapchain = Swapchain {
            window: surface.window.clone(),
        };
        let backbuffer = hal::Backbuffer::Framebuffer(0);
        (swapchain, backbuffer)
    }
}

impl hal::Instance for Surface {
    type Backend = B;
    fn enumerate_adapters(&self) -> Vec<hal::Adapter<B>> {
        unsafe { self.window.make_current().unwrap() };
        let adapter = PhysicalDevice::new_adapter(|s| self.window.get_proc_address(s) as *const _);
        vec![adapter]
    }
}

pub fn config_context(
    builder: glutin::ContextBuilder,
    color_format: f::Format,
    ds_format: Option<f::Format>,
) -> glutin::ContextBuilder
{
    let color_base = color_format.base_format();
    let color_bits = color_base.0.describe_bits();
    let depth_bits = match ds_format {
        Some(fm) => fm.base_format().0.describe_bits(),
        None => f::BITS_ZERO,
    };
    builder
        .with_depth_buffer(depth_bits.depth)
        .with_stencil_buffer(depth_bits.stencil)
        .with_pixel_format(color_bits.color, color_bits.alpha)
        .with_srgb(color_base.1 == f::ChannelType::Srgb)
}

pub struct Headless(pub glutin::HeadlessContext);

unsafe impl Send for Headless {}
unsafe impl Sync for Headless {}

impl hal::Instance for Headless {
    type Backend = B;
    fn enumerate_adapters(&self) -> Vec<hal::Adapter<B>> {
        unsafe { self.0.make_current().unwrap() };
        let adapter = PhysicalDevice::new_adapter(|s| self.0.get_proc_address(s) as *const _);
        vec![adapter]
    }
}
<commit_msg>gl: Add an accessor to the GlWindow underlying a Surface.<commit_after>//! Window creation using glutin for gfx.
//!
//! # Examples
//!
//! The following code creates a `gfx::Surface` using glutin.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_backend_gl;
//!
//! fn main() {
//!     use gfx_backend_gl::Surface;
//!     use glutin::{EventsLoop, WindowBuilder, ContextBuilder, GlWindow};
//!
//!     // First create a window using glutin.
//!     let mut events_loop = EventsLoop::new();
//!     let wb = WindowBuilder::new();
//!     let cb = ContextBuilder::new().with_vsync(true);
//!     let glutin_window = GlWindow::new(wb, cb, &events_loop).unwrap();
//!
//!     // Then use the glutin window to create a gfx surface.
//!     let surface = Surface::from_window(glutin_window);
//! }
//! ```
//!
//! Headless initialization without a window.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_backend_gl;
//! extern crate gfx_hal;
//!
//! use gfx_hal::Instance;
//! use gfx_backend_gl::Headless;
//! use glutin::{HeadlessRendererBuilder};
//!
//! fn main() {
//!     let context = HeadlessRendererBuilder::new(256, 256)
//!         .build()
//!         .expect("Failed to build headless context");
//!     let headless = Headless(context);
//!     let _adapters = headless.enumerate_adapters();
//! }
//! ```

use hal::{self, format as f, image};

use {Backend as B, Device, PhysicalDevice, QueueFamily};

use glutin::{self, GlContext};
use Starc;

fn get_window_dimensions(window: &glutin::GlWindow) -> image::Dimensions {
    let (width, height) = window.get_inner_size().unwrap();
    let aa = window.get_pixel_format().multisampling
                   .unwrap_or(0) as image::NumSamples;
    ((width as f32 * window.hidpi_factor()) as image::Size, (height as f32 * window.hidpi_factor()) as image::Size, 1, aa.into())
}

pub struct Swapchain {
    // Underlying window, required for presentation
    pub(crate) window: Starc<glutin::GlWindow>,
}

impl hal::Swapchain<B> for Swapchain {
    fn acquire_frame(&mut self, _sync: hal::FrameSync<B>) -> hal::Frame {
        // TODO: sync
        hal::Frame::new(0)
    }
}

//TODO: if we make `Surface` a `WindowBuilder` instead of `GlWindow`,
// we could spawn window + GL context when a swapchain is requested
// and actually respect the swapchain configuration provided by the user.
pub struct Surface {
    window: Starc<glutin::GlWindow>,
}

impl Surface {
    pub fn from_window(window: glutin::GlWindow) -> Self {
        Surface {
            window: Starc::new(window)
        }
    }

    pub fn window(&self) -> &glutin::GlWindow {
        &self.window
    }

    fn swapchain_formats(&self) -> Vec<f::Format> {
        let pixel_format = self.window.get_pixel_format();
        let color_bits = pixel_format.color_bits;
        let alpha_bits = pixel_format.alpha_bits;
        let srgb = pixel_format.srgb;

        // TODO: expose more formats
        match (color_bits, alpha_bits, srgb) {
            (24, 8, true) => vec![
                f::Format::Rgba8Srgb,
                f::Format::Bgra8Srgb,
            ],
            (24, 8, false) => vec![
                f::Format::Rgba8Unorm,
                f::Format::Bgra8Unorm,
            ],
            _ => vec![],
        }
    }
}

impl hal::Surface<B> for Surface {
    fn kind(&self) -> hal::image::Kind {
        let (w, h, _, a) = get_window_dimensions(&self.window);
        hal::image::Kind::D2(w, h, a)
    }

    fn capabilities_and_formats(&self, _: &PhysicalDevice) -> (hal::SurfaceCapabilities, Option<Vec<f::Format>>) {
        let dim = get_window_dimensions(&self.window);
        let extent = hal::window::Extent2D {
            width: dim.0 as u32,
            height: dim.1 as u32,
        };

        (hal::SurfaceCapabilities {
            image_count: if self.window.get_pixel_format().double_buffer { 2..3 } else { 1..2 },
            current_extent: Some(extent),
            extents: extent..hal::window::Extent2D {
                width: dim.0 as u32 + 1,
                height: dim.1 as u32 + 1
            },
            max_image_layers: 1,
        }, Some(self.swapchain_formats()))
    }

    fn supports_queue_family(&self, _: &QueueFamily) -> bool { true }
}

impl Device {
    pub(crate) fn create_swapchain_impl(
        &self,
        surface: &mut Surface,
        _config: hal::SwapchainConfig,
    ) -> (Swapchain, hal::Backbuffer<B>) {
        let swapchain = Swapchain {
            window: surface.window.clone(),
        };
        let backbuffer = hal::Backbuffer::Framebuffer(0);
        (swapchain, backbuffer)
    }
}

impl hal::Instance for Surface {
    type Backend = B;
    fn enumerate_adapters(&self) -> Vec<hal::Adapter<B>> {
        unsafe { self.window.make_current().unwrap() };
        let adapter = PhysicalDevice::new_adapter(|s| self.window.get_proc_address(s) as *const _);
        vec![adapter]
    }
}

pub fn config_context(
    builder: glutin::ContextBuilder,
    color_format: f::Format,
    ds_format: Option<f::Format>,
) -> glutin::ContextBuilder
{
    let color_base = color_format.base_format();
    let color_bits = color_base.0.describe_bits();
    let depth_bits = match ds_format {
        Some(fm) => fm.base_format().0.describe_bits(),
        None => f::BITS_ZERO,
    };
    builder
        .with_depth_buffer(depth_bits.depth)
        .with_stencil_buffer(depth_bits.stencil)
        .with_pixel_format(color_bits.color, color_bits.alpha)
        .with_srgb(color_base.1 == f::ChannelType::Srgb)
}

pub struct Headless(pub glutin::HeadlessContext);

unsafe impl Send for Headless {}
unsafe impl Sync for Headless {}

impl hal::Instance for Headless {
    type Backend = B;
    fn enumerate_adapters(&self) -> Vec<hal::Adapter<B>> {
        unsafe { self.0.make_current().unwrap() };
        let adapter = PhysicalDevice::new_adapter(|s| self.0.get_proc_address(s) as *const _);
        vec![adapter]
    }
}
<|endoftext|>


<commit_before>use crate::headers::*;
use crate::resource_quota::resource_quotas_from_str;
use crate::{IndexingDirective, ResourceQuota};
use azure_sdk_core::errors::AzureError;
use chrono::{DateTime, Utc};
use http::HeaderMap;

pub(crate) fn request_charge_from_headers(headers: &HeaderMap) -> Result<f64, AzureError> {
    Ok(headers
        .get(HEADER_REQUEST_CHARGE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_REQUEST_CHARGE.to_owned()))?
        .to_str()?
        .parse()?)
}

//pub(crate) fn request_item_count_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
//    Ok(headers
//        .get(HEADER_ITEM_COUNT)
//        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_COUNT.to_owned()))?
//        .to_str()?
//        .parse()?)
//}

pub(crate) fn item_count_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_ITEM_COUNT)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_COUNT.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn role_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_ROLE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ROLE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn number_of_read_regions_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_NUMBER_OF_READ_REGIONS)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_NUMBER_OF_READ_REGIONS.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn activity_id_from_headers(headers: &HeaderMap) -> Result<uuid::Uuid, AzureError> {
    let s = headers
        .get(HEADER_ACTIVITY_ID)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ACTIVITY_ID.to_owned()))?
        .to_str()?;
    Ok(uuid::Uuid::parse_str(s)?)
}

pub(crate) fn content_path_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_CONTENT_PATH)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CONTENT_PATH.to_owned()))?
        .to_str()?)
}

pub(crate) fn alt_content_path_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_ALT_CONTENT_PATH)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ALT_CONTENT_PATH.to_owned()))?
        .to_str()?)
}

pub(crate) fn resource_quota_from_headers(
    headers: &HeaderMap,
) -> Result<Vec<ResourceQuota>, AzureError> {
    let s = headers
        .get(HEADER_RESOURCE_QUOTA)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_RESOURCE_QUOTA.to_owned()))?
        .to_str()?;
    Ok(resource_quotas_from_str(s)?)
}

pub(crate) fn resource_usage_from_headers(
    headers: &HeaderMap,
) -> Result<Vec<ResourceQuota>, AzureError> {
    let s = headers
        .get(HEADER_RESOURCE_USAGE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_RESOURCE_USAGE.to_owned()))?
        .to_str()?;
    Ok(resource_quotas_from_str(s)?)
}

pub(crate) fn quorum_acked_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_QUORUM_ACKED_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_QUORUM_ACKED_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn quorum_acked_lsn_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_QUORUM_ACKED_LSN) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn cosmos_quorum_acked_llsn_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_QUORUM_ACKED_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_QUORUM_ACKED_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn cosmos_quorum_acked_llsn_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_COSMOS_QUORUM_ACKED_LLSN) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn current_write_quorum_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_CURRENT_WRITE_QUORUM)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CURRENT_WRITE_QUORUM.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_write_quorum_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_CURRENT_WRITE_QUORUM) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn collection_partition_index_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COLLECTION_PARTITION_INDEX)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COLLECTION_PARTITION_INDEX.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn indexing_directive_from_headers(
    headers: &HeaderMap,
) -> Result<IndexingDirective, AzureError> {
    Ok(headers
        .get(HEADER_INDEXING_DIRECTIVE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_INDEXING_DIRECTIVE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn collection_service_index_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COLLECTION_SERVICE_INDEX)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COLLECTION_SERVICE_INDEX.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn item_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_ITEM_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn transport_request_id_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_TRANSPORT_REQUEST_ID)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_TRANSPORT_REQUEST_ID.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn global_committed_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_GLOBAL_COMMITTED_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_GLOBAL_COMMITTED_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn cosmos_llsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn cosmos_item_llsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_ITEM_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_ITEM_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_replica_set_size_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_CURRENT_REPLICA_SET_SIZE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CURRENT_REPLICA_SET_SIZE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_replica_set_size_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_CURRENT_REPLICA_SET_SIZE) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn schema_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_SCHEMA_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_SCHEMA_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn service_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_SERVICE_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_SERVICE_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn content_location_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(http::header::CONTENT_LOCATION)
        .ok_or_else(|| {
            let header = http::header::CONTENT_LOCATION;
            AzureError::HeaderNotFound(header.as_str().to_owned())
        })?
        .to_str()?)
}

pub(crate) fn content_type_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(http::header::CONTENT_TYPE)
        .ok_or_else(|| {
            let header = http::header::CONTENT_TYPE;
            AzureError::HeaderNotFound(header.as_str().to_owned())
        })?
        .to_str()?)
}

pub(crate) fn gateway_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_GATEWAY_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_GATEWAY_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn max_media_storage_usage_mb_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_MAX_MEDIA_STORAGE_USAGE_MB)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_MAX_MEDIA_STORAGE_USAGE_MB.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn media_storage_usage_mb_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_MEDIA_STORAGE_USAGE_MB)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_MEDIA_STORAGE_USAGE_MB.to_owned()))?
        .to_str()?
        .parse()?)
}

fn _date_from_headers(headers: &HeaderMap, header_name: &str) -> Result<DateTime<Utc>, AzureError> {
    let date = headers
        .get(header_name)
        .ok_or_else(|| AzureError::HeaderNotFound(header_name.to_owned()))?
        .to_str()?;
    debug!("date == {:#}", date);

    // since Azure returns "GMT" instead of +0000 as timezone we replace it
    // ourselves.
    // For example: Wed, 15 Jan 2020 23:39:44.369 GMT
    let date = date.replace("GMT", "+0000");
    debug!("date == {:#}", date);

    let date = DateTime::parse_from_str(&date, "%a, %e %h %Y %H:%M:%S%.f %z")?;
    debug!("date == {:#}", date);

    let date = DateTime::from_utc(date.naive_utc(), Utc);
    debug!("date == {:#}", date);

    Ok(date)
}

pub(crate) fn last_state_change_from_headers(
    headers: &HeaderMap,
) -> Result<DateTime<Utc>, AzureError> {
    _date_from_headers(headers, HEADER_LAST_STATE_CHANGE_UTC)
}

pub(crate) fn date_from_headers(headers: &HeaderMap) -> Result<DateTime<Utc>, AzureError> {
    let header = http::header::DATE;
    _date_from_headers(headers, header.as_str())
}
<commit_msg>x-ms-global-committed-lsn 0 if == -1<commit_after>use crate::headers::*;
use crate::resource_quota::resource_quotas_from_str;
use crate::{IndexingDirective, ResourceQuota};
use azure_sdk_core::errors::AzureError;
use chrono::{DateTime, Utc};
use http::HeaderMap;

pub(crate) fn request_charge_from_headers(headers: &HeaderMap) -> Result<f64, AzureError> {
    Ok(headers
        .get(HEADER_REQUEST_CHARGE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_REQUEST_CHARGE.to_owned()))?
        .to_str()?
        .parse()?)
}

//pub(crate) fn request_item_count_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
//    Ok(headers
//        .get(HEADER_ITEM_COUNT)
//        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_COUNT.to_owned()))?
//        .to_str()?
//        .parse()?)
//}

pub(crate) fn item_count_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_ITEM_COUNT)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_COUNT.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn role_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_ROLE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ROLE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn number_of_read_regions_from_headers(headers: &HeaderMap) -> Result<u32, AzureError> {
    Ok(headers
        .get(HEADER_NUMBER_OF_READ_REGIONS)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_NUMBER_OF_READ_REGIONS.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn activity_id_from_headers(headers: &HeaderMap) -> Result<uuid::Uuid, AzureError> {
    let s = headers
        .get(HEADER_ACTIVITY_ID)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ACTIVITY_ID.to_owned()))?
        .to_str()?;
    Ok(uuid::Uuid::parse_str(s)?)
}

pub(crate) fn content_path_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_CONTENT_PATH)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CONTENT_PATH.to_owned()))?
        .to_str()?)
}

pub(crate) fn alt_content_path_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_ALT_CONTENT_PATH)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ALT_CONTENT_PATH.to_owned()))?
        .to_str()?)
}

pub(crate) fn resource_quota_from_headers(
    headers: &HeaderMap,
) -> Result<Vec<ResourceQuota>, AzureError> {
    let s = headers
        .get(HEADER_RESOURCE_QUOTA)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_RESOURCE_QUOTA.to_owned()))?
        .to_str()?;
    Ok(resource_quotas_from_str(s)?)
}

pub(crate) fn resource_usage_from_headers(
    headers: &HeaderMap,
) -> Result<Vec<ResourceQuota>, AzureError> {
    let s = headers
        .get(HEADER_RESOURCE_USAGE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_RESOURCE_USAGE.to_owned()))?
        .to_str()?;
    Ok(resource_quotas_from_str(s)?)
}

pub(crate) fn quorum_acked_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_QUORUM_ACKED_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_QUORUM_ACKED_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn quorum_acked_lsn_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_QUORUM_ACKED_LSN) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn cosmos_quorum_acked_llsn_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_QUORUM_ACKED_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_QUORUM_ACKED_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn cosmos_quorum_acked_llsn_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_COSMOS_QUORUM_ACKED_LLSN) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn current_write_quorum_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_CURRENT_WRITE_QUORUM)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CURRENT_WRITE_QUORUM.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_write_quorum_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_CURRENT_WRITE_QUORUM) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn collection_partition_index_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COLLECTION_PARTITION_INDEX)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COLLECTION_PARTITION_INDEX.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn indexing_directive_from_headers(
    headers: &HeaderMap,
) -> Result<IndexingDirective, AzureError> {
    Ok(headers
        .get(HEADER_INDEXING_DIRECTIVE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_INDEXING_DIRECTIVE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn collection_service_index_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COLLECTION_SERVICE_INDEX)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COLLECTION_SERVICE_INDEX.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn item_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_ITEM_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_ITEM_LSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn transport_request_id_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_TRANSPORT_REQUEST_ID)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_TRANSPORT_REQUEST_ID.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn global_committed_lsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    let s = headers
        .get(HEADER_GLOBAL_COMMITTED_LSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_GLOBAL_COMMITTED_LSN.to_owned()))?
        .to_str()?;
    Ok(if s == "-1" { 0 } else { s.parse()? })
}

pub(crate) fn cosmos_llsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn cosmos_item_llsn_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_COSMOS_ITEM_LLSN)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_COSMOS_ITEM_LLSN.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_replica_set_size_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_CURRENT_REPLICA_SET_SIZE)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_CURRENT_REPLICA_SET_SIZE.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn current_replica_set_size_from_headers_optional(
    headers: &HeaderMap,
) -> Result<Option<u64>, AzureError> {
    Ok(match headers.get(HEADER_CURRENT_REPLICA_SET_SIZE) {
        Some(val) => Some(val.to_str()?.parse()?),
        None => None,
    })
}

pub(crate) fn schema_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_SCHEMA_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_SCHEMA_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn service_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_SERVICE_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_SERVICE_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn content_location_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(http::header::CONTENT_LOCATION)
        .ok_or_else(|| {
            let header = http::header::CONTENT_LOCATION;
            AzureError::HeaderNotFound(header.as_str().to_owned())
        })?
        .to_str()?)
}

pub(crate) fn content_type_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(http::header::CONTENT_TYPE)
        .ok_or_else(|| {
            let header = http::header::CONTENT_TYPE;
            AzureError::HeaderNotFound(header.as_str().to_owned())
        })?
        .to_str()?)
}

pub(crate) fn gateway_version_from_headers(headers: &HeaderMap) -> Result<&str, AzureError> {
    Ok(headers
        .get(HEADER_GATEWAY_VERSION)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_GATEWAY_VERSION.to_owned()))?
        .to_str()?)
}

pub(crate) fn max_media_storage_usage_mb_from_headers(
    headers: &HeaderMap,
) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_MAX_MEDIA_STORAGE_USAGE_MB)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_MAX_MEDIA_STORAGE_USAGE_MB.to_owned()))?
        .to_str()?
        .parse()?)
}

pub(crate) fn media_storage_usage_mb_from_headers(headers: &HeaderMap) -> Result<u64, AzureError> {
    Ok(headers
        .get(HEADER_MEDIA_STORAGE_USAGE_MB)
        .ok_or_else(|| AzureError::HeaderNotFound(HEADER_MEDIA_STORAGE_USAGE_MB.to_owned()))?
        .to_str()?
        .parse()?)
}

fn _date_from_headers(headers: &HeaderMap, header_name: &str) -> Result<DateTime<Utc>, AzureError> {
    let date = headers
        .get(header_name)
        .ok_or_else(|| AzureError::HeaderNotFound(header_name.to_owned()))?
        .to_str()?;
    debug!("date == {:#}", date);

    // since Azure returns "GMT" instead of +0000 as timezone we replace it
    // ourselves.
    // For example: Wed, 15 Jan 2020 23:39:44.369 GMT
    let date = date.replace("GMT", "+0000");
    debug!("date == {:#}", date);

    let date = DateTime::parse_from_str(&date, "%a, %e %h %Y %H:%M:%S%.f %z")?;
    debug!("date == {:#}", date);

    let date = DateTime::from_utc(date.naive_utc(), Utc);
    debug!("date == {:#}", date);

    Ok(date)
}

pub(crate) fn last_state_change_from_headers(
    headers: &HeaderMap,
) -> Result<DateTime<Utc>, AzureError> {
    _date_from_headers(headers, HEADER_LAST_STATE_CHANGE_UTC)
}

pub(crate) fn date_from_headers(headers: &HeaderMap) -> Result<DateTime<Utc>, AzureError> {
    let header = http::header::DATE;
    _date_from_headers(headers, header.as_str())
}
<|endoftext|>


<commit_before>/// Declares an item with a doc attribute computed by some macro expression.
/// This allows documentation to be dynamically generated based on input.
/// Necessary to work around <https://github.com/rust-lang/rust/issues/52607>.
macro_rules! doc_concat {
    ( $( #[doc = $doc:expr] $( $thing:tt )* )* ) => ( $( #[doc = $doc] $( $thing )* )* );
}

macro_rules! partial_eq_string {
    ($id:ty $([$( $g:ident ),*])?) => {
        partial_eq_string!(@imp $(<$($g),*>)?, $id, str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, &str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, String);
        partial_eq_string!(@imp $(<$($g),*>)?, str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, &str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, String, $id);
    };
    (@imp $(<$( $g:ident ),*>)?, $l:ty, $r:ty) => {
        impl $(<$($g),*>)? PartialEq<$r> for $l {
            fn eq(&self, other: &$r) -> bool {
                AsRef::<str>::as_ref(self)
                    == AsRef::<str>::as_ref(other)
            }
        }
    }
}

macro_rules! as_str_based_impls {
    ($id:ty) => {
        impl AsRef<str> for $id {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl std::fmt::Display for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.as_str())
            }
        }

        impl PartialEq for $id {
            fn eq(&self, other: &Self) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl Eq for $id {}

        impl PartialOrd for $id {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                PartialOrd::partial_cmp(self.as_str(), other.as_str())
            }
        }

        impl Ord for $id {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                Ord::cmp(self.as_str(), other.as_str())
            }
        }

        impl std::hash::Hash for $id {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.as_str().hash(state);
            }
        }

        #[cfg(feature = "serde")]
        impl serde::Serialize for $id {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serializer.serialize_str(self.as_str())
            }
        }
    };
}

macro_rules! common_impls {
    ($id:ty, $try_from:ident, $desc:literal) => {
        impl $id {
            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`")]
                pub fn as_str(&self) -> &str {
                    &self.full_id
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.full_id.as_bytes()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `String`")]
                pub fn into_string(self) -> String {
                    self.full_id.into()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `Vec<u8>`")]
                pub fn into_bytes(self) -> Vec<u8> {
                    Box::<[u8]>::from(self.full_id).into()
                }
            }
        }

        impl From<$id> for String {
            fn from(id: $id) -> Self {
                id.into_string()
            }
        }

        impl From<$id> for Vec<u8> {
            fn from(id: $id) -> Self {
                id.into_bytes()
            }
        }

        impl std::str::FromStr for $id {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for $id {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for $id {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for $id {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                crate::deserialize_id(deserializer, $desc)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
    };
}

macro_rules! opaque_identifier {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident;
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        pub struct $id(str);

        impl $id {
            fn from_borrowed(s: &str) -> &Self {
                unsafe { std::mem::transmute(s) }
            }

            pub(super) fn from_owned(s: Box<str>) -> Box<Self> {
                unsafe { Box::from_raw(Box::into_raw(s) as _) }
            }

            fn into_owned(self: Box<Self>) -> Box<str> {
                unsafe { Box::from_raw(Box::into_raw(self) as _) }
            }

            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`.")]
                pub fn as_str(&self) -> &str {
                    &self.0
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`.")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.0.as_bytes()
                }
            }
        }

        impl std::fmt::Debug for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                <str as std::fmt::Debug>::fmt(self.as_str(), f)
            }
        }

        impl Clone for Box<$id> {
            fn clone(&self) -> Self {
                (**self).to_owned()
            }
        }

        impl ToOwned for $id {
            type Owned = Box<$id>;

            fn to_owned(&self) -> Self::Owned {
                Self::from_owned(self.0.into())
            }
        }

        impl From<&$id> for Box<$id> {
            fn from(id: &$id) -> Self {
                id.to_owned()
            }
        }

        impl AsRef<str> for Box<$id> {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl From<&$id> for std::rc::Rc<$id> {
            fn from(s: &$id) -> std::rc::Rc<$id> {
                let rc = std::rc::Rc::<str>::from(s.as_str());
                unsafe { std::rc::Rc::from_raw(std::rc::Rc::into_raw(rc) as *const $id) }
            }
        }

        impl From<&$id> for std::sync::Arc<$id> {
            fn from(s: &$id) -> std::sync::Arc<$id> {
                let arc = std::sync::Arc::<str>::from(s.as_str());
                unsafe { std::sync::Arc::from_raw(std::sync::Arc::into_raw(arc) as *const $id) }
            }
        }

        impl<'a> From<&'a str> for &'a $id {
            fn from(s: &'a str) -> Self {
                $id::from_borrowed(s)
            }
        }

        impl From<&str> for Box<$id> {
            fn from(s: &str) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<String> for Box<$id> {
            fn from(s: String) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Box::<str>::deserialize(deserializer).map($id::from_owned)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
        partial_eq_string!(Box<$id>);
    };
}

macro_rules! opaque_identifier_validated {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident [ $validate_id:ident ];
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
        #[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent, crate = "serde"))]
        pub struct $id(str);

        impl $id {
            #[allow(clippy::transmute_ptr_to_ptr)]
            fn from_borrowed(s: &str) -> &Self {
                unsafe { std::mem::transmute(s) }
            }

            pub(super) fn from_owned(s: Box<str>) -> Box<Self> {
                unsafe { Box::from_raw(Box::into_raw(s) as _) }
            }

            fn into_owned(self: Box<Self>) -> Box<str> {
                unsafe { Box::from_raw(Box::into_raw(self) as _) }
            }

            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`.")]
                pub fn as_str(&self) -> &str {
                    &self.0
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`.")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.0.as_bytes()
                }
            }
        }

        impl std::fmt::Debug for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                <str as std::fmt::Debug>::fmt(self.as_str(), f)
            }
        }

        impl Clone for Box<$id> {
            fn clone(&self) -> Self {
                (**self).to_owned()
            }
        }

        impl ToOwned for $id {
            type Owned = Box<$id>;

            fn to_owned(&self) -> Self::Owned {
                Self::from_owned(self.0.into())
            }
        }

        impl From<&$id> for Box<$id> {
            fn from(id: &$id) -> Self {
                id.to_owned()
            }
        }

        impl AsRef<str> for $id {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl AsRef<str> for Box<$id> {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl From<&$id> for std::rc::Rc<$id> {
            fn from(s: &$id) -> std::rc::Rc<$id> {
                let rc = std::rc::Rc::<str>::from(s.as_str());
                unsafe { std::rc::Rc::from_raw(std::rc::Rc::into_raw(rc) as *const $id) }
            }
        }

        impl From<&$id> for std::sync::Arc<$id> {
            fn from(s: &$id) -> std::sync::Arc<$id> {
                let arc = std::sync::Arc::<str>::from(s.as_str());
                unsafe { std::sync::Arc::from_raw(std::sync::Arc::into_raw(arc) as *const $id) }
            }
        }

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                use serde::de::Error;

                let s = String::deserialize(deserializer)?;

                match try_from(s) {
                    Ok(o) => Ok(o),
                    Err(e) => Err(D::Error::custom(e)),
                }
            }
        }

        fn try_from<S>(s: S) -> Result<Box<$id>, crate::Error>
        where
            S: AsRef<str> + Into<Box<str>>,
        {
            $validate_id(s.as_ref())?;
            Ok($id::from_owned(s.into()))
        }

        impl<'a> std::convert::TryFrom<&'a str> for &'a $id {
            type Error = crate::Error;

            fn try_from(s: &'a str) -> Result<Self, Self::Error> {
                $validate_id(s)?;
                Ok($id::from_borrowed(s))
            }
        }

        impl std::str::FromStr for Box<$id> {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for Box<$id> {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for Box<$id> {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                try_from(s)
            }
        }

        impl std::fmt::Display for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.as_str())
            }
        }

        partial_eq_string!($id);
        partial_eq_string!(Box<$id>);
    }
}
<commit_msg>identifiers: Reduce macro code duplication<commit_after>/// Declares an item with a doc attribute computed by some macro expression.
/// This allows documentation to be dynamically generated based on input.
/// Necessary to work around <https://github.com/rust-lang/rust/issues/52607>.
macro_rules! doc_concat {
    ( $( #[doc = $doc:expr] $( $thing:tt )* )* ) => ( $( #[doc = $doc] $( $thing )* )* );
}

macro_rules! partial_eq_string {
    ($id:ty $([$( $g:ident ),*])?) => {
        partial_eq_string!(@imp $(<$($g),*>)?, $id, str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, &str);
        partial_eq_string!(@imp $(<$($g),*>)?, $id, String);
        partial_eq_string!(@imp $(<$($g),*>)?, str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, &str, $id);
        partial_eq_string!(@imp $(<$($g),*>)?, String, $id);
    };
    (@imp $(<$( $g:ident ),*>)?, $l:ty, $r:ty) => {
        impl $(<$($g),*>)? PartialEq<$r> for $l {
            fn eq(&self, other: &$r) -> bool {
                AsRef::<str>::as_ref(self)
                    == AsRef::<str>::as_ref(other)
            }
        }
    }
}

macro_rules! as_str_based_impls {
    ($id:ty) => {
        impl AsRef<str> for $id {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl std::fmt::Display for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.as_str())
            }
        }

        impl PartialEq for $id {
            fn eq(&self, other: &Self) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl Eq for $id {}

        impl PartialOrd for $id {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                PartialOrd::partial_cmp(self.as_str(), other.as_str())
            }
        }

        impl Ord for $id {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                Ord::cmp(self.as_str(), other.as_str())
            }
        }

        impl std::hash::Hash for $id {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.as_str().hash(state);
            }
        }

        #[cfg(feature = "serde")]
        impl serde::Serialize for $id {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serializer.serialize_str(self.as_str())
            }
        }
    };
}

macro_rules! common_impls {
    ($id:ty, $try_from:ident, $desc:literal) => {
        impl $id {
            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`")]
                pub fn as_str(&self) -> &str {
                    &self.full_id
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.full_id.as_bytes()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `String`")]
                pub fn into_string(self) -> String {
                    self.full_id.into()
                }
            }

            doc_concat! {
                #[doc = concat!("Converts this `", stringify!($id), "` into a `Vec<u8>`")]
                pub fn into_bytes(self) -> Vec<u8> {
                    Box::<[u8]>::from(self.full_id).into()
                }
            }
        }

        impl From<$id> for String {
            fn from(id: $id) -> Self {
                id.into_string()
            }
        }

        impl From<$id> for Vec<u8> {
            fn from(id: $id) -> Self {
                id.into_bytes()
            }
        }

        impl std::str::FromStr for $id {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for $id {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for $id {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                $try_from(s)
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for $id {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                crate::deserialize_id(deserializer, $desc)
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
    };
}

macro_rules! opaque_identifier_common_impls {
    ($id:ty) => {
        impl $id {
            fn from_borrowed(s: &str) -> &Self {
                unsafe { std::mem::transmute(s) }
            }

            pub(super) fn from_owned(s: Box<str>) -> Box<Self> {
                unsafe { Box::from_raw(Box::into_raw(s) as _) }
            }

            fn into_owned(self: Box<Self>) -> Box<str> {
                unsafe { Box::from_raw(Box::into_raw(self) as _) }
            }

            doc_concat! {
                #[doc = concat!("Creates a string slice from this `", stringify!($id), "`.")]
                pub fn as_str(&self) -> &str {
                    &self.0
                }
            }

            doc_concat! {
                #[doc = concat!("Creates a byte slice from this `", stringify!($id), "`.")]
                pub fn as_bytes(&self) -> &[u8] {
                    self.0.as_bytes()
                }
            }
        }

        impl std::fmt::Debug for $id {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                <str as std::fmt::Debug>::fmt(self.as_str(), f)
            }
        }

        impl Clone for Box<$id> {
            fn clone(&self) -> Self {
                (**self).to_owned()
            }
        }

        impl ToOwned for $id {
            type Owned = Box<$id>;

            fn to_owned(&self) -> Self::Owned {
                Self::from_owned(self.0.into())
            }
        }

        impl From<&$id> for Box<$id> {
            fn from(id: &$id) -> Self {
                id.to_owned()
            }
        }

        impl AsRef<str> for Box<$id> {
            fn as_ref(&self) -> &str {
                self.as_str()
            }
        }

        impl From<&$id> for std::rc::Rc<$id> {
            fn from(s: &$id) -> std::rc::Rc<$id> {
                let rc = std::rc::Rc::<str>::from(s.as_str());
                unsafe { std::rc::Rc::from_raw(std::rc::Rc::into_raw(rc) as *const $id) }
            }
        }

        impl From<&$id> for std::sync::Arc<$id> {
            fn from(s: &$id) -> std::sync::Arc<$id> {
                let arc = std::sync::Arc::<str>::from(s.as_str());
                unsafe { std::sync::Arc::from_raw(std::sync::Arc::into_raw(arc) as *const $id) }
            }
        }

        as_str_based_impls!($id);
        partial_eq_string!($id);
        partial_eq_string!(Box<$id>);
    };
}

macro_rules! opaque_identifier {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident;
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        pub struct $id(str);

        opaque_identifier_common_impls!($id);

        impl<'a> From<&'a str> for &'a $id {
            fn from(s: &'a str) -> Self {
                $id::from_borrowed(s)
            }
        }

        impl From<&str> for Box<$id> {
            fn from(s: &str) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<String> for Box<$id> {
            fn from(s: String) -> Self {
                $id::from_owned(s.into())
            }
        }

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Box::<str>::deserialize(deserializer).map($id::from_owned)
            }
        }
    };
}

macro_rules! opaque_identifier_validated {
    (
        $( #[doc = $docs:literal] )*
        $vis:vis type $id:ident [ $validate_id:ident ];
    ) => {
        $( #[doc = $docs] )*
        #[repr(transparent)]
        pub struct $id(str);

        opaque_identifier_common_impls!($id);

        impl From<Box<$id>> for String {
            fn from(id: Box<$id>) -> Self {
                id.into_owned().into()
            }
        }

        #[cfg(feature = "serde")]
        impl<'de> serde::Deserialize<'de> for Box<$id> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                use serde::de::Error;

                let s = String::deserialize(deserializer)?;

                match try_from(s) {
                    Ok(o) => Ok(o),
                    Err(e) => Err(D::Error::custom(e)),
                }
            }
        }

        fn try_from<S>(s: S) -> Result<Box<$id>, crate::Error>
        where
            S: AsRef<str> + Into<Box<str>>,
        {
            $validate_id(s.as_ref())?;
            Ok($id::from_owned(s.into()))
        }

        impl<'a> std::convert::TryFrom<&'a str> for &'a $id {
            type Error = crate::Error;

            fn try_from(s: &'a str) -> Result<Self, Self::Error> {
                $validate_id(s)?;
                Ok($id::from_borrowed(s))
            }
        }

        impl std::str::FromStr for Box<$id> {
            type Err = crate::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                try_from(s)
            }
        }

        impl std::convert::TryFrom<&str> for Box<$id> {
            type Error = crate::Error;

            fn try_from(s: &str) -> Result<Self, Self::Error> {
                try_from(s)
            }
        }

        impl std::convert::TryFrom<String> for Box<$id> {
            type Error = crate::Error;

            fn try_from(s: String) -> Result<Self, Self::Error> {
                try_from(s)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::time::Duration;
use std::collections::HashMap;

// struct to cache results of expensive calculations
struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    calculation: T,
    values: HashMap<u32, u32>,
}

impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            values: HashMap::new(),
        }
    }

    fn value(&mut self, arg: u32) -> u32 {
        match self.values.get(&arg) {
            Some(&v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.values.insert(arg, v);
                v
            }
        }
    }
}

fn generate_workout(intensity: u32, random_number: u32) {
    let mut expensive_result = Cacher::new( |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    });

    if intensity < 25 {
        println!("Today, do {} pushups!", expensive_result.value(intensity));
        println!("Next, do {} situps!", expensive_result.value(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!("Today, run for {} minutes!", expensive_result.value(intensity));
        }
    }
}

fn main() {
    let simulated_user_specified_value = 10;
    let simulated_randon_number = 7;

    generate_workout(simulated_user_specified_value, simulated_randon_number);
}

#[test]
fn call_with_different_values() {
    let mut c = Cacher::new(|a| a);

    let v1 = c.value(1);
    let v2 = c.value(2);

    assert_ne!(v2, v1);
    assert_eq!(v2, 2);
}
<commit_msg>make Cacher generic<commit_after>use std::collections::HashMap;
use std::hash::Hash;
use std::thread;
use std::time::Duration;

// struct to cache results of expensive calculations
struct Cacher<T, U, V>
where
    T: Fn(U) -> V,
    U: Eq + Hash + Copy,
    V: Copy,
{
    calculation: T,
    values: HashMap<U, V>,
}

impl<T, U, V> Cacher<T, U, V>
where
    T: Fn(U) -> V,
    U: Eq + Hash + Copy,
    V: Copy,
{
    fn new(calculation: T) -> Cacher<T, U, V> {
        Cacher {
            calculation,
            values: HashMap::new(),
        }
    }

    fn value(&mut self, arg: U) ->  V {
        match self.values.get(&arg) {
            Some(v) => v.to_owned(),
            None => {
                let v = (self.calculation)(arg);
                self.values.insert(arg, v);
                v
            }
        }
    }
}

fn generate_workout(intensity: u32, random_number: u32) {
    let mut expensive_result = Cacher::new(|num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    });

    if intensity < 25 {
        println!("Today, do {} pushups!", expensive_result.value(intensity));
        println!("Next, do {} situps!", expensive_result.value(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!(
                "Today, run for {} minutes!",
                expensive_result.value(intensity)
            );
        }
    }
}

fn main() {
    let simulated_user_specified_value = 10;
    let simulated_randon_number = 7;

    generate_workout(simulated_user_specified_value, simulated_randon_number);
}

#[test]
fn call_with_different_values() {
    let mut c = Cacher::new(|a| a);

    let v1 = c.value(1);
    let v2 = c.value(2);

    assert_ne!(v2, v1);
    assert_eq!(v2, 2);
}

#[test]
fn call_with_different_types() {
    let mut c1 = Cacher::new(|a| a);
    let mut c2 = Cacher::new(|a| a);

    let v1 = c1.value(1);
    let v2 = c2.value("Test");

    assert_eq!(v1, 1);
    assert_eq!(v2, "Test");
}
<|endoftext|>


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

use binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCommitUndoActions,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNRedo,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn is_modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe {
            BNIsBackedByDatabase(
                self.handle,
                view_type.as_ref().as_ptr() as *const _
            )
        }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(Ref::new(BinaryView::from_raw(res)))
            }
        }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

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

use binaryninjacore_sys::{
    BNBeginUndoActions,
    BNCloseFile,
    BNCommitUndoActions,
    BNCreateFileMetadata,
    BNFileMetadata,
    BNFreeFileMetadata,
    BNGetCurrentOffset,
    BNGetCurrentView,
    BNGetFileViewOfType,
    BNGetFilename,
    BNIsAnalysisChanged,
    BNIsBackedByDatabase,
    //BNSetFileMetadataNavigationHandler,
    BNIsFileModified,
    BNMarkFileModified,
    BNMarkFileSaved,
    BNNavigate,
    BNNewFileReference,
    BNRedo,
    BNSetFilename,
    BNUndo,
};

use crate::binaryview::BinaryView;

use crate::rc::*;
use crate::string::*;

#[derive(PartialEq, Eq, Hash)]
pub struct FileMetadata {
    pub(crate) handle: *mut BNFileMetadata,
}

unsafe impl Send for FileMetadata {}
unsafe impl Sync for FileMetadata {}

impl FileMetadata {
    pub(crate) fn from_raw(handle: *mut BNFileMetadata) -> Self {
        Self { handle }
    }

    pub fn new() -> Ref<Self> {
        unsafe {
            Ref::new(Self {
                handle: BNCreateFileMetadata(),
            })
        }
    }

    pub fn with_filename<S: BnStrCompatible>(name: S) -> Ref<Self> {
        let ret = FileMetadata::new();
        ret.set_filename(name);
        ret
    }

    pub fn close(&self) {
        unsafe {
            BNCloseFile(self.handle);
        }
    }

    pub fn filename(&self) -> BnString {
        unsafe {
            let raw = BNGetFilename(self.handle);
            BnString::from_raw(raw)
        }
    }

    pub fn set_filename<S: BnStrCompatible>(&self, name: S) {
        let name = name.as_bytes_with_nul();

        unsafe {
            BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _);
        }
    }

    pub fn is_modified(&self) -> bool {
        unsafe { BNIsFileModified(self.handle) }
    }

    pub fn mark_modified(&self) {
        unsafe {
            BNMarkFileModified(self.handle);
        }
    }

    pub fn is_analysis_changed(&self) -> bool {
        unsafe { BNIsAnalysisChanged(self.handle) }
    }

    pub fn mark_saved(&self) {
        unsafe {
            BNMarkFileSaved(self.handle);
        }
    }

    pub fn is_database_backed<S: BnStrCompatible>(&self, view_type: S) -> bool {
        let view_type = view_type.as_bytes_with_nul();

        unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) }
    }

    pub fn begin_undo_actions(&self) {
        unsafe {
            BNBeginUndoActions(self.handle);
        }
    }

    pub fn commit_undo_actions(&self) {
        unsafe {
            BNCommitUndoActions(self.handle);
        }
    }

    pub fn undo(&self) {
        unsafe {
            BNUndo(self.handle);
        }
    }

    pub fn redo(&self) {
        unsafe {
            BNRedo(self.handle);
        }
    }

    pub fn current_view(&self) -> BnString {
        unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) }
    }

    pub fn current_offset(&self) -> u64 {
        unsafe { BNGetCurrentOffset(self.handle) }
    }

    pub fn navigate_to<S: BnStrCompatible>(&self, view: S, offset: u64) -> Result<(), ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    pub fn get_view_of_type<S: BnStrCompatible>(&self, view: S) -> Result<Ref<BinaryView>, ()> {
        let view = view.as_bytes_with_nul();

        unsafe {
            let res = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _);

            if res.is_null() {
                Err(())
            } else {
                Ok(Ref::new(BinaryView::from_raw(res)))
            }
        }
    }
}

impl ToOwned for FileMetadata {
    type Owned = Ref<Self>;

    fn to_owned(&self) -> Self::Owned {
        unsafe { RefCountable::inc_ref(self) }
    }
}

unsafe impl RefCountable for FileMetadata {
    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
        Ref::new(Self {
            handle: BNNewFileReference(handle.handle),
        })
    }

    unsafe fn dec_ref(handle: &Self) {
        BNFreeFileMetadata(handle.handle);
    }
}

/*
BNCreateDatabase,
BNCreateDatabaseWithProgress,
BNOpenExistingDatabase,
BNOpenExistingDatabaseWithProgress,
*/
<|endoftext|>


<commit_before>use ::cairo;
use ::glib::translate::*;
use ::libc;

use std::str::FromStr;

use error::*;
use length::*;
use transform::*;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
    fn rsvg_property_bag_dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag;
    fn rsvg_property_bag_free (pbag: *mut RsvgPropertyBag);
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag {
    unsafe {
        rsvg_property_bag_dup (pbag)
    }
}

pub fn free (pbag: *mut RsvgPropertyBag) {
    unsafe {
        rsvg_property_bag_free (pbag);
    }
}

pub fn length_or_none (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <Option<RsvgLength>, NodeError> {
    let value = lookup (pbag, key);

    if let Some (v) = value {
        RsvgLength::parse (&v, length_dir).map (|l| Some (l))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}

pub fn length_or_default (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::default ()),
        Err (e)       => Err (e)
    }
}

pub fn length_or_value (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir, length_str: &str) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::parse (length_str, length_dir).unwrap ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
    where T: FromStr<Err = AttributeError>
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::from_str (&v).map (|v| Some (v))
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok (None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError>
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (T::default ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, value: T) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError> + Copy
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (value),
        Err (e)       => Err (e)
    }
}

pub fn transform_or_none (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<cairo::Matrix>, NodeError> {
    if let Some (s) = lookup (pbag, key) {
        parse_transform (&s)
            .map (|v| Some (v))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}
<commit_msg>property_bag.rs: Implement parse_or_default() in terms of parse_or_value()<commit_after>use ::cairo;
use ::glib::translate::*;
use ::libc;

use std::str::FromStr;

use error::*;
use length::*;
use transform::*;

pub enum RsvgPropertyBag {}

extern "C" {
    fn rsvg_property_bag_lookup (pbag: *const RsvgPropertyBag, key: *const libc::c_char) -> *const libc::c_char;
    fn rsvg_property_bag_dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag;
    fn rsvg_property_bag_free (pbag: *mut RsvgPropertyBag);
}

pub fn lookup (pbag: *const RsvgPropertyBag, key: &str) -> Option<String> {
    unsafe {
        let c_value = rsvg_property_bag_lookup (pbag, key.to_glib_none ().0);
        from_glib_none (c_value)
    }
}

pub fn dup (pbag: *const RsvgPropertyBag) -> *mut RsvgPropertyBag {
    unsafe {
        rsvg_property_bag_dup (pbag)
    }
}

pub fn free (pbag: *mut RsvgPropertyBag) {
    unsafe {
        rsvg_property_bag_free (pbag);
    }
}

pub fn length_or_none (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <Option<RsvgLength>, NodeError> {
    let value = lookup (pbag, key);

    if let Some (v) = value {
        RsvgLength::parse (&v, length_dir).map (|l| Some (l))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}

pub fn length_or_default (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::default ()),
        Err (e)       => Err (e)
    }
}

pub fn length_or_value (pbag: *const RsvgPropertyBag, key: &'static str, length_dir: LengthDir, length_str: &str) -> Result <RsvgLength, NodeError> {
    let r = length_or_none (pbag, key, length_dir);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (RsvgLength::parse (length_str, length_dir).unwrap ()),
        Err (e)       => Err (e)
    }
}

pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
    where T: FromStr<Err = AttributeError>
{
    let value = lookup (pbag, key);

    match value {
        Some (v) => {
            T::from_str (&v).map (|v| Some (v))
                .map_err (|e| NodeError::attribute_error (key, e))
        },

        None => Ok (None)
    }
}

pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError> + Copy
{
    parse_or_value (pbag, key, T::default ())
}

pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, value: T) -> Result <T, NodeError>
    where T: Default + FromStr<Err = AttributeError> + Copy
{
    let r = parse_or_none::<T> (pbag, key);

    match r {
        Ok (Some (v)) => Ok (v),
        Ok (None)     => Ok (value),
        Err (e)       => Err (e)
    }
}

pub fn transform_or_none (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<cairo::Matrix>, NodeError> {
    if let Some (s) = lookup (pbag, key) {
        parse_transform (&s)
            .map (|v| Some (v))
            .map_err (|e| NodeError::attribute_error (key, e))
    } else {
        Ok (None)
    }
}
<|endoftext|>


<commit_before>use nalgebra::Vector2;
use std::cmp::max;
use super::rounding_error_tolerant_math::*;
use std::ops::{Add, Sub, Mul, Neg, Shl, Shr, BitAnd};
use array_ext::*;
use num::{PrimInt, Signed};

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  if shift == 0 {return input}
  let half = T::one() << (shift - 1);
  let mask = (T::one() << shift) - T::one();
  if input & mask == half {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + half) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// The coefficients are required to be small enough that `coefficient.abs() << shift` does not overflow.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_fractional <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  if coefficients.len () == 0 {return T::zero()}
  let half = T::one() << (shift - 1);
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_fractional must be in the range [-0.5, 0.5]");
  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

#[cfg (test)]
mod tests {
  use super::*;

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  quickcheck! {
    fn evaluate_polynomial_fractional_is_accurate (coefficients: Vec<i32>, input: i32, shift: u8)->bool {
      //scale everything to reasonable values
      let shift = (shift >> 5) as usize + 1; //up to 16, so all i32 coefficients are valid
      let half = 1i64 << (shift - 1);
      let input = ((input as i64)*half) >> 31;
      let result = evaluate_polynomial_fractional (& coefficients, input, shift) ;
      let mut float_result = 0.0;
      let float_input = input as f64/(1i64 << shift) as f64;
      for coefficient in coefficients.iter().rev() {
        float_result = float_result*float_input +*coefficient as f64;
      }
      let difference = result as f64 - float_result;
      //allow a little leeway for the floats to be an accurate as well
      difference <= 1.0001
    }
  }
}
<commit_msg>Switched the tests to use infinite-precision math instead of floating points<commit_after>use nalgebra::Vector2;
use std::cmp::max;
use super::rounding_error_tolerant_math::*;
use std::ops::{Add, Sub, Mul, Neg, Shl, Shr, BitAnd};
use array_ext::*;
use num::{PrimInt, Signed};

/// Right-shift an integer, but round to nearest, with ties rounding to even.
///
/// This minimizes error, and avoids a directional bias.
pub fn right_shift_nicely_rounded <T: PrimInt> (input: T, shift: usize)->T {
  if shift == 0 {return input}
  let half = T::one() << (shift - 1);
  let mask = (T::one() << shift) - T::one();
  if input & mask == half {
    let shifted = input >> shift;
    shifted + (shifted & T::one())
  } else {
    (input + half) >> shift
  }
}

/// Approximately evaluate an integer polynomial at an input in the range [-0.5, 0.5].
///
/// The input is represented as an integer combined with a right-shift size.
/// The coefficients are required to be small enough that `coefficient.abs() << shift` does not overflow.
/// Given these conditions, the result is guaranteed to be strictly within 1 of the ideal result.
/// For instance, if the ideal result was 2.125, this function could return 2 or 3,
/// but if it was 2, this function can only return exactly 2.
pub fn evaluate_polynomial_fractional <Coefficient: Copy, T: PrimInt + Signed + From <Coefficient>> (coefficients: & [Coefficient], input: T, shift: usize)->T {
  if coefficients.len () == 0 {return T::zero()}
  let half = T::one() << (shift - 1);
  assert!(-half <= input && input <= half, "inputs to evaluate_polynomial_fractional must be in the range [-0.5, 0.5]");
  let mut result = T::zero();
  for coefficient in coefficients.iter().skip(1).rev() {
    result = right_shift_nicely_rounded ((result + (*coefficient).into())*input, shift);
  }
  result + coefficients [0].into()
}

#[cfg (test)]
mod tests {
  use super::*;
  use num::FromPrimitive;
  use num::bigint::BigInt;
  use num::rational::{Ratio, BigRational};

  #[test]
  fn test_right_shift_nicely_rounded() {
    let inputs: Vec<(i64, usize, i64)> = vec![
      (0, 0, 0), (0, 5, 0), (1, 3, 0), (4, 3, 0), (5, 3, 1),
      (999, 1, 500), (998, 1, 499), (997, 1, 498)
    ];
    for (input, shift, result) in inputs {
      assert_eq!(right_shift_nicely_rounded (input, shift), result);
      assert_eq!(right_shift_nicely_rounded (-input, shift), -result);
    }
  }

  quickcheck! {
    fn evaluate_polynomial_fractional_is_accurate (coefficients: Vec<i32>, input: i32, shift: u8)->bool {
      //scale everything to reasonable values
      let shift = (shift >> 5) as usize + 1; //up to 16, so all i32 coefficients are valid
      let half = 1i64 << (shift - 1);
      let input = ((input as i64)*half) >> 31;
      let result = evaluate_polynomial_fractional (& coefficients, input, shift) ;
      let mut perfect_result: BigRational = Ratio::from_integer (FromPrimitive::from_i64 (0).unwrap());
      let perfect_input = Ratio::from_integer (BigInt::from_i64 (input).unwrap())/Ratio::from_integer (BigInt::from_i64 (1i64).unwrap() << shift);
      for coefficient in coefficients.iter().rev() {
        perfect_result = perfect_result*& perfect_input + Ratio::from_integer (FromPrimitive::from_i32 (*coefficient).unwrap ());
      }
      let difference = Ratio::from_integer (FromPrimitive::from_i64 (result).unwrap()) - perfect_result;
      difference < Ratio::from_integer (FromPrimitive::from_i64 (1).unwrap())
    }
  }
}
<|endoftext|>