<commit_before>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
// FIXME: Remove this and redundant_semicolon once renamed lint reaches stable.
#![allow(renamed_and_removed_lints)]
#![allow(
    bad_style,
    overflowing_literals,
    improper_ctypes,
    unknown_lints,
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(target_os = "redox", feature(static_nobundle))]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<commit_msg>Import `core::ops` to use `Range` syntax<commit_after>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
// FIXME: Remove this and redundant_semicolon once renamed lint reaches stable.
#![allow(renamed_and_removed_lints)]
#![allow(
    bad_style,
    overflowing_literals,
    improper_ctypes,
    unknown_lints,
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(target_os = "redox", feature(static_nobundle))]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::ops;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<|endoftext|>


<commit_before>//! Ropey is a utf8 text rope for Rust.  It is fast, robust, and can handle
//! huge texts and memory-incoherent edits with ease.
//!
//! Ropey's atomic unit of text is Unicode scalar values (or `char`s in Rust)
//! encoded as utf8.  All of Ropey's editing and slicing operations are done
//! in terms of char indices which prevents accidental creation of invalid
//! utf8 data.
//!
//! The library is made up of four main components:
//!
//! - [`Rope`](struct.Rope.html): the main rope type.
//! - [`RopeSlice`](struct.RopeSlice.html): an immutable view into part of a
//!   `Rope`.
//! - [`iter`](iter/index.html): iterators over `Rope`/`RopeSlice` data.
//! - [`RopeBuilder`](struct.RopeBuilder.html): an efficient incremental
//!   `Rope` builder.
//!
//!
//! # A Basic Example
//!
//! Let's say we want to open up a text file, replace the 516th line (the
//! writing was terrible!), and save it back to disk.  It's contrived, but will
//! give a good sampling of the APIs and how they work together.
//!
//! ```no_run
//! # use std::io::Result;
//! use std::fs::File;
//! use std::io::{BufReader, BufWriter};
//! use ropey::Rope;
//!
//! # fn do_stuff() -> Result<()> {
//! // Load a text file.
//! let mut text = Rope::from_reader(
//!     BufReader::new(File::open("my_great_book.txt")?)
//! )?;
//!
//! // Print the 516th line (zero-indexed) to see the terrible
//! // writing.
//! println!("{}", text.line(515));
//!
//! // Get the start/end char indices of the line.
//! let start_idx = text.line_to_char(515);
//! let end_idx = text.line_to_char(516);
//!
//! // Remove the line...
//! text.remove(start_idx..end_idx);
//!
//! // ...and replace it with something better.
//! text.insert(start_idx, "The flowers are... so... dunno.\n");
//!
//! // Print the changes, along with the previous few lines for context.
//! let start_idx = text.line_to_char(511);
//! let end_idx = text.line_to_char(516);
//! println!("{}", text.slice(start_idx..end_idx));
//!
//! // Write the file back out to disk.
//! text.write_to(
//!     BufWriter::new(File::create("my_great_book.txt")?)
//! )?;
//! # Ok(())
//! # }
//! # do_stuff().unwrap();
//! ```
//!
//! More examples can be found in the `examples` directory of the git
//! repository.  Many of those examples demonstrate doing non-trivial things
//! with Ropey such as grapheme handling, search-and-replace, and streaming
//! loading of non-utf8 text files.
//!
//!
//! # Low-level APIs
//!
//! Ropey also provides access to some of its low-level APIs, enabling client
//! code to efficiently work with a `Rope`'s data and implement new
//! functionality.  The most important of those API's are:
//!
//! - The [`chunk_at_*()`](struct.Rope.html#method.chunk_at_byte)
//!   chunk-fetching methods of `Rope` and `RopeSlice`.
//! - The [`Chunks`](iter/struct.Chunks.html) iterator.
//! - The functions in [`str_utils`](str_utils/index.html) for operating on
//!   `&str` slices.
//!
//! Internally, each `Rope` stores text as a segemented collection of utf8
//! strings.  The chunk-fetching methods and `Chunks` iterator provide direct
//! access to those strings (or "chunks") as `&str` slices, allowing client
//! code to work directly with the underlying utf8 data.
//!
//! The chunk-fetching methods and `str_utils` functions are the basic
//! building blocks that Ropey itself uses to build much of its functionality.
//! For example, the [`Rope::byte_to_char()`](struct.Rope.html#method.byte_to_char)
//! method can be reimplemented as a free function like this:
//!
//! ```no_run
//! use ropey::{
//!     Rope,
//!     str_utils::byte_to_char_idx
//! };
//!
//! fn byte_to_char(rope: &Rope, byte_idx: usize) -> usize {
//!     let (chunk, b, c, _) = rope.chunk_at_byte(byte_idx);
//!     c + byte_to_char_idx(chunk, byte_idx - b)
//! }
//! ```
//!
//! And this will be just as efficient as Ropey's implementation.
//!
//! The chunk-fetching methods in particular are among the fastest functions
//! that Ropey provides, generally operating in the sub-hundred nanosecond
//! range for medium-sized (~200kB) documents on recent-ish computer systems.
//!
//!
//! # A Note About Line Endings
//!
//! Some of Ropey's APIs use the concept of line breaks or lines of text.  In
//! all such APIs, Ropey treats the following unicode sequences as line
//! breaks:
//!
//! - `U+000A`          — LF (Line Feed)
//! - `U+000B`          — VT (Vertical Tab)
//! - `U+000C`          — FF (Form Feed)
//! - `U+000D`          — CR (Carriage Return)
//! - `U+0085`          — NEL (Next Line)
//! - `U+2028`          — Line Separator
//! - `U+2029`          — Paragraph Separator
//! - `U+000D` `U+000A` — CRLF (Carriage Return + Line Feed)
//!
//! Additionally, Ropey treats line breaks as being a part of the line that
//! they mark the end of.  That is to say, lines begin immediately _after_ a
//! line break.
//!
//! CRLF pairs are always treated as a single line break, and are never split
//! across chunks.  Note, however, that slicing can still split them.

#![allow(clippy::collapsible_if)]
#![allow(clippy::inline_always)]
#![allow(clippy::needless_return)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::type_complexity)]

extern crate smallvec;

mod crlf;
mod rope;
mod rope_builder;
mod slice;
mod tree;

pub mod iter;
pub mod str_utils;

use std::ops::Bound;

pub use crate::rope::Rope;
pub use crate::rope_builder::RopeBuilder;
pub use crate::slice::RopeSlice;

//==============================================================
// Error reporting types.

/// Ropey's result type.
pub type Result<T> = std::result::Result<T, Error>;

/// Ropey's error type.
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum Error {
    ByteIndexOutOfBounds(usize, usize),  // (index, rope byte length)
    CharIndexOutOfBounds(usize, usize),  // (index, rope char length)
    LineIndexOutOfBounds(usize, usize),  // (index, rope line length)
    Utf16IndexOutOfBounds(usize, usize), // (index, rope utf16 length)

    // Unlike the range out-of-bounds error, this doesn't use Option.
    // For this error to even be possible, it needs both a start and an end.
    CharRangeInvalid(
        usize, // Start.
        usize, // End.
    ),
    CharRangeOutOfBounds(
        Option<usize>, // Start.
        Option<usize>, // End.
        usize,         // Rope char length.
    ),
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }

    // Deprecated in std.
    fn description(&self) -> &str {
        ""
    }

    // Deprecated in std.
    fn cause(&self) -> Option<&dyn std::error::Error> {
        None
    }
}

impl std::fmt::Debug for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match *self {
            Error::ByteIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Byte index out of bounds: byte index {}, Rope/RopeSlice byte length {}",
                    index, len
                )
            }
            Error::CharIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Char index out of bounds: char index {}, Rope/RopeSlice char length {}",
                    index, len
                )
            }
            Error::LineIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Line index out of bounds: line index {}, Rope/RopeSlice line count {}",
                    index, len
                )
            }
            Error::Utf16IndexOutOfBounds(index, len) => {
                write!(f, "Utf16 code-unit index out of bounds: utf16 index {}, Rope/RopeSlice utf16 length {}", index, len)
            }

            Error::CharRangeInvalid(start_idx, end_idx) => {
                write!(
                    f,
                    "Invalid char range {}..{}: start must be <= end",
                    start_idx, end_idx
                )
            }
            Error::CharRangeOutOfBounds(start_idx_opt, end_idx_opt, len) => {
                write!(f, "Char range out of bounds: char range ")?;
                write_range(f, start_idx_opt, end_idx_opt)?;
                write!(f, ", Rope/RopeSlice char length {}", len)
            }
        }
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // Just re-use the debug impl.
        std::fmt::Debug::fmt(self, f)
    }
}

fn write_range(
    f: &mut std::fmt::Formatter<'_>,
    start_idx: Option<usize>,
    end_idx: Option<usize>,
) -> std::fmt::Result {
    match (start_idx, end_idx) {
        (None, None) => {
            write!(f, "..")
        }

        (Some(start), None) => {
            write!(f, "{}..", start)
        }

        (None, Some(end)) => {
            write!(f, "..{}", end)
        }

        (Some(start), Some(end)) => {
            write!(f, "{}..{}", start, end)
        }
    }
}

//==============================================================
// Range handling utilities.

#[inline(always)]
pub(crate) fn start_bound_to_num(b: Bound<&usize>) -> Option<usize> {
    match b {
        Bound::Included(n) => Some(*n),
        Bound::Excluded(n) => Some(*n + 1),
        Bound::Unbounded => None,
    }
}

#[inline(always)]
pub(crate) fn end_bound_to_num(b: Bound<&usize>) -> Option<usize> {
    match b {
        Bound::Included(n) => Some(*n + 1),
        Bound::Excluded(n) => Some(*n),
        Bound::Unbounded => None,
    }
}
<commit_msg>Document the Error type's variants.<commit_after>//! Ropey is a utf8 text rope for Rust.  It is fast, robust, and can handle
//! huge texts and memory-incoherent edits with ease.
//!
//! Ropey's atomic unit of text is Unicode scalar values (or `char`s in Rust)
//! encoded as utf8.  All of Ropey's editing and slicing operations are done
//! in terms of char indices which prevents accidental creation of invalid
//! utf8 data.
//!
//! The library is made up of four main components:
//!
//! - [`Rope`](struct.Rope.html): the main rope type.
//! - [`RopeSlice`](struct.RopeSlice.html): an immutable view into part of a
//!   `Rope`.
//! - [`iter`](iter/index.html): iterators over `Rope`/`RopeSlice` data.
//! - [`RopeBuilder`](struct.RopeBuilder.html): an efficient incremental
//!   `Rope` builder.
//!
//!
//! # A Basic Example
//!
//! Let's say we want to open up a text file, replace the 516th line (the
//! writing was terrible!), and save it back to disk.  It's contrived, but will
//! give a good sampling of the APIs and how they work together.
//!
//! ```no_run
//! # use std::io::Result;
//! use std::fs::File;
//! use std::io::{BufReader, BufWriter};
//! use ropey::Rope;
//!
//! # fn do_stuff() -> Result<()> {
//! // Load a text file.
//! let mut text = Rope::from_reader(
//!     BufReader::new(File::open("my_great_book.txt")?)
//! )?;
//!
//! // Print the 516th line (zero-indexed) to see the terrible
//! // writing.
//! println!("{}", text.line(515));
//!
//! // Get the start/end char indices of the line.
//! let start_idx = text.line_to_char(515);
//! let end_idx = text.line_to_char(516);
//!
//! // Remove the line...
//! text.remove(start_idx..end_idx);
//!
//! // ...and replace it with something better.
//! text.insert(start_idx, "The flowers are... so... dunno.\n");
//!
//! // Print the changes, along with the previous few lines for context.
//! let start_idx = text.line_to_char(511);
//! let end_idx = text.line_to_char(516);
//! println!("{}", text.slice(start_idx..end_idx));
//!
//! // Write the file back out to disk.
//! text.write_to(
//!     BufWriter::new(File::create("my_great_book.txt")?)
//! )?;
//! # Ok(())
//! # }
//! # do_stuff().unwrap();
//! ```
//!
//! More examples can be found in the `examples` directory of the git
//! repository.  Many of those examples demonstrate doing non-trivial things
//! with Ropey such as grapheme handling, search-and-replace, and streaming
//! loading of non-utf8 text files.
//!
//!
//! # Low-level APIs
//!
//! Ropey also provides access to some of its low-level APIs, enabling client
//! code to efficiently work with a `Rope`'s data and implement new
//! functionality.  The most important of those API's are:
//!
//! - The [`chunk_at_*()`](struct.Rope.html#method.chunk_at_byte)
//!   chunk-fetching methods of `Rope` and `RopeSlice`.
//! - The [`Chunks`](iter/struct.Chunks.html) iterator.
//! - The functions in [`str_utils`](str_utils/index.html) for operating on
//!   `&str` slices.
//!
//! Internally, each `Rope` stores text as a segemented collection of utf8
//! strings.  The chunk-fetching methods and `Chunks` iterator provide direct
//! access to those strings (or "chunks") as `&str` slices, allowing client
//! code to work directly with the underlying utf8 data.
//!
//! The chunk-fetching methods and `str_utils` functions are the basic
//! building blocks that Ropey itself uses to build much of its functionality.
//! For example, the [`Rope::byte_to_char()`](struct.Rope.html#method.byte_to_char)
//! method can be reimplemented as a free function like this:
//!
//! ```no_run
//! use ropey::{
//!     Rope,
//!     str_utils::byte_to_char_idx
//! };
//!
//! fn byte_to_char(rope: &Rope, byte_idx: usize) -> usize {
//!     let (chunk, b, c, _) = rope.chunk_at_byte(byte_idx);
//!     c + byte_to_char_idx(chunk, byte_idx - b)
//! }
//! ```
//!
//! And this will be just as efficient as Ropey's implementation.
//!
//! The chunk-fetching methods in particular are among the fastest functions
//! that Ropey provides, generally operating in the sub-hundred nanosecond
//! range for medium-sized (~200kB) documents on recent-ish computer systems.
//!
//!
//! # A Note About Line Endings
//!
//! Some of Ropey's APIs use the concept of line breaks or lines of text.  In
//! all such APIs, Ropey treats the following unicode sequences as line
//! breaks:
//!
//! - `U+000A`          — LF (Line Feed)
//! - `U+000B`          — VT (Vertical Tab)
//! - `U+000C`          — FF (Form Feed)
//! - `U+000D`          — CR (Carriage Return)
//! - `U+0085`          — NEL (Next Line)
//! - `U+2028`          — Line Separator
//! - `U+2029`          — Paragraph Separator
//! - `U+000D` `U+000A` — CRLF (Carriage Return + Line Feed)
//!
//! Additionally, Ropey treats line breaks as being a part of the line that
//! they mark the end of.  That is to say, lines begin immediately _after_ a
//! line break.
//!
//! CRLF pairs are always treated as a single line break, and are never split
//! across chunks.  Note, however, that slicing can still split them.

#![allow(clippy::collapsible_if)]
#![allow(clippy::inline_always)]
#![allow(clippy::needless_return)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::type_complexity)]

extern crate smallvec;

mod crlf;
mod rope;
mod rope_builder;
mod slice;
mod tree;

pub mod iter;
pub mod str_utils;

use std::ops::Bound;

pub use crate::rope::Rope;
pub use crate::rope_builder::RopeBuilder;
pub use crate::slice::RopeSlice;

//==============================================================
// Error reporting types.

/// Ropey's result type.
pub type Result<T> = std::result::Result<T, Error>;

/// Ropey's error type.
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum Error {
    /// Indicates that the passed byte index was out of bounds.
    ///
    /// Contains the index attempted and the actual length of the
    /// `Rope`/`RopeSlice` in bytes, in that order.
    ByteIndexOutOfBounds(usize, usize),

    /// Indicates that the passed char index was out of bounds.
    ///
    /// Contains the index attempted and the actual length of the
    /// `Rope`/`RopeSlice` in chars, in that order.
    CharIndexOutOfBounds(usize, usize),

    /// Indicates that the passed line index was out of bounds.
    ///
    /// Contains the index attempted and the actual length of the
    /// `Rope`/`RopeSlice` in lines, in that order.
    LineIndexOutOfBounds(usize, usize),

    /// Indicates that the passed utf16 code-unit index was out of
    /// bounds.
    ///
    /// Contains the index attempted and the actual length of the
    /// `Rope`/`RopeSlice` in utf16 code units, in that order.
    Utf16IndexOutOfBounds(usize, usize),

    /// Indicates that a reversed char-index range (end < start) was
    /// encountered.
    ///
    /// Contains the [start, end) char indices of the range, in that order.
    CharRangeInvalid(
        usize, // Start.
        usize, // End.
    ),

    /// Indicates that the passed char-index range was partially or fully
    /// out of bounds.
    ///
    /// Contains the [start, end) char indices of the range and the actual
    /// length of the `Rope`/`RopeSlice` in chars, in that order.  When
    /// either the start or end are `None`, that indicates a half-open range.
    CharRangeOutOfBounds(
        Option<usize>, // Start.
        Option<usize>, // End.
        usize,         // Rope char length.
    ),
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }

    // Deprecated in std.
    fn description(&self) -> &str {
        ""
    }

    // Deprecated in std.
    fn cause(&self) -> Option<&dyn std::error::Error> {
        None
    }
}

impl std::fmt::Debug for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match *self {
            Error::ByteIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Byte index out of bounds: byte index {}, Rope/RopeSlice byte length {}",
                    index, len
                )
            }
            Error::CharIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Char index out of bounds: char index {}, Rope/RopeSlice char length {}",
                    index, len
                )
            }
            Error::LineIndexOutOfBounds(index, len) => {
                write!(
                    f,
                    "Line index out of bounds: line index {}, Rope/RopeSlice line count {}",
                    index, len
                )
            }
            Error::Utf16IndexOutOfBounds(index, len) => {
                write!(f, "Utf16 code-unit index out of bounds: utf16 index {}, Rope/RopeSlice utf16 length {}", index, len)
            }

            Error::CharRangeInvalid(start_idx, end_idx) => {
                write!(
                    f,
                    "Invalid char range {}..{}: start must be <= end",
                    start_idx, end_idx
                )
            }
            Error::CharRangeOutOfBounds(start_idx_opt, end_idx_opt, len) => {
                write!(f, "Char range out of bounds: char range ")?;
                write_range(f, start_idx_opt, end_idx_opt)?;
                write!(f, ", Rope/RopeSlice char length {}", len)
            }
        }
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // Just re-use the debug impl.
        std::fmt::Debug::fmt(self, f)
    }
}

fn write_range(
    f: &mut std::fmt::Formatter<'_>,
    start_idx: Option<usize>,
    end_idx: Option<usize>,
) -> std::fmt::Result {
    match (start_idx, end_idx) {
        (None, None) => {
            write!(f, "..")
        }

        (Some(start), None) => {
            write!(f, "{}..", start)
        }

        (None, Some(end)) => {
            write!(f, "..{}", end)
        }

        (Some(start), Some(end)) => {
            write!(f, "{}..{}", start, end)
        }
    }
}

//==============================================================
// Range handling utilities.

#[inline(always)]
pub(crate) fn start_bound_to_num(b: Bound<&usize>) -> Option<usize> {
    match b {
        Bound::Included(n) => Some(*n),
        Bound::Excluded(n) => Some(*n + 1),
        Bound::Unbounded => None,
    }
}

#[inline(always)]
pub(crate) fn end_bound_to_num(b: Bound<&usize>) -> Option<usize> {
    match b {
        Bound::Included(n) => Some(*n + 1),
        Bound::Excluded(n) => Some(*n),
        Bound::Unbounded => None,
    }
}
<|endoftext|>


<commit_before>//! Crate ruma_client is a [Matrix](https://matrix.org/) client library.

#![feature(try_from)]
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]

extern crate hyper;
extern crate ruma_client_api;
extern crate ruma_identifiers;
extern crate serde;
extern crate serde_json;
extern crate url;

use std::convert::TryInto;

use hyper::client::{Client as Hyper, IntoUrl};
use hyper::method::Method as HyperMethod;
use ruma_client_api::{Endpoint, Method};
use ruma_client_api::unversioned::get_supported_versions;
use url::Url;

pub use error::Error;
pub use session::Session;
pub use response::Response;

mod error;
mod response;
mod session;

/// A client for the Matrix client-server API.
#[derive(Debug)]
pub struct Client {
    homeserver_url: Url,
    hyper: Hyper,
    session: Option<Session>,
}

trait IntoHyperMethod {
    fn into_hyper(self) -> HyperMethod;
}

impl IntoHyperMethod for Method {
    fn into_hyper(self) -> HyperMethod {
        match self {
            Method::Delete => HyperMethod::Delete,
            Method::Get => HyperMethod::Get,
            Method::Put => HyperMethod::Put,
            Method::Post => HyperMethod::Post,
        }
    }
}

impl Client {
    /// Creates a new client for making requests to the given homeserver.
    ///
    /// # Errors
    ///
    /// Returns an error if the given homserver URL cannot be parsed as a URL.
    pub fn new<U>(homeserver_url: U) -> Result<Self, Error> where U: IntoUrl {
        Ok(Client {
            homeserver_url: homeserver_url.into_url()?,
            hyper: Hyper::new(),
            session: None,
        })
    }

    /// Get the versions of the Matrix client-server specification supported by the homeserver.
    pub fn get_supported_versions(&self)
    -> Result<Response<<get_supported_versions::Endpoint as Endpoint>::Response>, Error> {
        let response = self.hyper.request(
            supported_versions::Endpoint::method().into_hyper(),
            self.homeserver_url.join(&supported_versions::Endpoint::request_path(()))?,
        ).send()?;

        Ok(response.try_into()?)
    }
}
<commit_msg>Correct more module names that changed.<commit_after>//! Crate ruma_client is a [Matrix](https://matrix.org/) client library.

#![feature(try_from)]
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]

extern crate hyper;
extern crate ruma_client_api;
extern crate ruma_identifiers;
extern crate serde;
extern crate serde_json;
extern crate url;

use std::convert::TryInto;

use hyper::client::{Client as Hyper, IntoUrl};
use hyper::method::Method as HyperMethod;
use ruma_client_api::{Endpoint, Method};
use ruma_client_api::unversioned::get_supported_versions;
use url::Url;

pub use error::Error;
pub use session::Session;
pub use response::Response;

mod error;
mod response;
mod session;

/// A client for the Matrix client-server API.
#[derive(Debug)]
pub struct Client {
    homeserver_url: Url,
    hyper: Hyper,
    session: Option<Session>,
}

trait IntoHyperMethod {
    fn into_hyper(self) -> HyperMethod;
}

impl IntoHyperMethod for Method {
    fn into_hyper(self) -> HyperMethod {
        match self {
            Method::Delete => HyperMethod::Delete,
            Method::Get => HyperMethod::Get,
            Method::Put => HyperMethod::Put,
            Method::Post => HyperMethod::Post,
        }
    }
}

impl Client {
    /// Creates a new client for making requests to the given homeserver.
    ///
    /// # Errors
    ///
    /// Returns an error if the given homserver URL cannot be parsed as a URL.
    pub fn new<U>(homeserver_url: U) -> Result<Self, Error> where U: IntoUrl {
        Ok(Client {
            homeserver_url: homeserver_url.into_url()?,
            hyper: Hyper::new(),
            session: None,
        })
    }

    /// Get the versions of the Matrix client-server specification supported by the homeserver.
    pub fn get_supported_versions(&self)
    -> Result<Response<<get_supported_versions::Endpoint as Endpoint>::Response>, Error> {
        let response = self.hyper.request(
            get_supported_versions::Endpoint::method().into_hyper(),
            self.homeserver_url.join(&get_supported_versions::Endpoint::request_path(()))?,
        ).send()?;

        Ok(response.try_into()?)
    }
}
<|endoftext|>


<commit_before>use crate::error;
use crate::gitignore::Gitignore;
use crate::ignore::Ignore;
use globset::{Glob, GlobSet, GlobSetBuilder};
use std::path::Path;

pub struct NotificationFilter {
    filters: GlobSet,
    filter_count: usize,
    ignores: GlobSet,
    gitignore_files: Gitignore,
    ignore_files: Ignore,
}

impl NotificationFilter {
    pub fn new(
        filters: &[String],
        ignores: &[String],
        gitignore_files: Gitignore,
        ignore_files: Ignore,
    ) -> error::Result<Self> {
        let mut filter_set_builder = GlobSetBuilder::new();
        for f in filters {
            filter_set_builder.add(Glob::new(f)?);
            debug!("Adding filter: \"{}\"", f);
        }

        let mut ignore_set_builder = GlobSetBuilder::new();
        for i in ignores {
            let mut ignore_path = Path::new(i).to_path_buf();
            if ignore_path.is_relative() && !i.starts_with('*') {
                ignore_path = Path::new("**").join(&ignore_path);
            }
            let pattern = ignore_path
                .to_str()
                .expect("corrupted memory (string -> path -> string)");
            ignore_set_builder.add(Glob::new(pattern)?);
            debug!("Adding ignore: \"{}\"", pattern);
        }

        Ok(Self {
            filters: filter_set_builder.build()?,
            filter_count: filters.len(),
            ignores: ignore_set_builder.build()?,
            gitignore_files,
            ignore_files,
        })
    }

    pub fn is_excluded(&self, path: &Path) -> bool {
        if self.ignores.is_match(path) {
            debug!("Ignoring {:?}: matched ignore filter", path);
            return true;
        }

        if self.filters.is_match(path) {
            return false;
        }

        if self.ignore_files.is_excluded(path) {
            debug!("Ignoring {:?}: matched ignore file", path);
            return true;
        }

        if self.gitignore_files.is_excluded(path) {
            debug!("Ignoring {:?}: matched gitignore file", path);
            return true;
        }

        if self.filter_count > 0 {
            debug!("Ignoring {:?}: did not match any given filters", path);
        }

        self.filter_count > 0
    }
}

#[cfg(test)]
mod tests {
    use super::NotificationFilter;
    use crate::gitignore;
    use crate::ignore;
    use std::path::Path;

    #[test]
    fn test_allows_everything_by_default() {
        let filter = NotificationFilter::new(&[], &[], gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(!filter.is_excluded(Path::new("foo")));
    }

    #[test]
    fn test_filename() {
        let filter = NotificationFilter::new(
            &[],
            &["test.json".into()],
            gitignore::load(&[]),
            ignore::load(&[]),
        )
        .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("/path/to/test.json")));
        assert!(filter.is_excluded(Path::new("test.json")));
    }

    #[test]
    fn test_multiple_filters() {
        let filters = &["*.rs".into(), "*.toml".into()];
        let filter = NotificationFilter::new(filters, &[], gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(!filter.is_excluded(Path::new("hello.rs")));
        assert!(!filter.is_excluded(Path::new("Cargo.toml")));
        assert!(filter.is_excluded(Path::new("README.md")));
    }

    #[test]
    fn test_multiple_ignores() {
        let ignores = &["*.rs".into(), "*.toml".into()];
        let filter = NotificationFilter::new(&[], ignores, gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("hello.rs")));
        assert!(filter.is_excluded(Path::new("Cargo.toml")));
        assert!(!filter.is_excluded(Path::new("README.md")));
    }

    #[test]
    fn test_ignores_take_precedence() {
        let ignores = &["*.rs".into(), "*.toml".into()];
        let filter =
            NotificationFilter::new(ignores, ignores, gitignore::load(&[]), ignore::load(&[]))
                .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("hello.rs")));
        assert!(filter.is_excluded(Path::new("Cargo.toml")));
        assert!(filter.is_excluded(Path::new("README.md")));
    }
}
<commit_msg>fix the ignore path handling to match the README by ignoring everything below a directory<commit_after>use crate::error;
use crate::gitignore::Gitignore;
use crate::ignore::Ignore;
use globset::{Glob, GlobSet, GlobSetBuilder};
use std::path::Path;

pub struct NotificationFilter {
    filters: GlobSet,
    filter_count: usize,
    ignores: GlobSet,
    gitignore_files: Gitignore,
    ignore_files: Ignore,
}

impl NotificationFilter {
    pub fn new(
        filters: &[String],
        ignores: &[String],
        gitignore_files: Gitignore,
        ignore_files: Ignore,
    ) -> error::Result<Self> {
        let mut filter_set_builder = GlobSetBuilder::new();
        for f in filters {
            filter_set_builder.add(Glob::new(f)?);
            debug!("Adding filter: \"{}\"", f);
        }

        let mut ignore_set_builder = GlobSetBuilder::new();
        for i in ignores {
            let mut ignore_path = Path::new(i).to_path_buf();
            if ignore_path.is_relative() && !i.starts_with('*') {
                ignore_path = Path::new("**").join(&ignore_path);
            }
            if !i.ends_with('*') {
                ignore_path = ignore_path.join("**");
            }
            let pattern = ignore_path
                .to_str()
                .expect("corrupted memory (string -> path -> string)");
            ignore_set_builder.add(Glob::new(pattern)?);
            debug!("Adding ignore: \"{}\"", pattern);
        }

        Ok(Self {
            filters: filter_set_builder.build()?,
            filter_count: filters.len(),
            ignores: ignore_set_builder.build()?,
            gitignore_files,
            ignore_files,
        })
    }

    pub fn is_excluded(&self, path: &Path) -> bool {
        if self.ignores.is_match(path) {
            debug!("Ignoring {:?}: matched ignore filter", path);
            return true;
        }

        if self.filters.is_match(path) {
            return false;
        }

        if self.ignore_files.is_excluded(path) {
            debug!("Ignoring {:?}: matched ignore file", path);
            return true;
        }

        if self.gitignore_files.is_excluded(path) {
            debug!("Ignoring {:?}: matched gitignore file", path);
            return true;
        }

        if self.filter_count > 0 {
            debug!("Ignoring {:?}: did not match any given filters", path);
        }

        self.filter_count > 0
    }
}

#[cfg(test)]
mod tests {
    use super::NotificationFilter;
    use crate::gitignore;
    use crate::ignore;
    use std::path::Path;

    #[test]
    fn test_allows_everything_by_default() {
        let filter = NotificationFilter::new(&[], &[], gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(!filter.is_excluded(Path::new("foo")));
    }

    #[test]
    fn test_filename() {
        let filter = NotificationFilter::new(
            &[],
            &["test.json".into()],
            gitignore::load(&[]),
            ignore::load(&[]),
        )
        .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("/path/to/test.json")));
        assert!(filter.is_excluded(Path::new("test.json")));
    }

    #[test]
    fn test_multiple_filters() {
        let filters = &["*.rs".into(), "*.toml".into()];
        let filter = NotificationFilter::new(filters, &[], gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(!filter.is_excluded(Path::new("hello.rs")));
        assert!(!filter.is_excluded(Path::new("Cargo.toml")));
        assert!(filter.is_excluded(Path::new("README.md")));
    }

    #[test]
    fn test_multiple_ignores() {
        let ignores = &["*.rs".into(), "*.toml".into()];
        let filter = NotificationFilter::new(&[], ignores, gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("hello.rs")));
        assert!(filter.is_excluded(Path::new("Cargo.toml")));
        assert!(!filter.is_excluded(Path::new("README.md")));
    }

    #[test]
    fn test_ignores_take_precedence() {
        let ignores = &["*.rs".into(), "*.toml".into()];
        let filter =
            NotificationFilter::new(ignores, ignores, gitignore::load(&[]), ignore::load(&[]))
                .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("hello.rs")));
        assert!(filter.is_excluded(Path::new("Cargo.toml")));
        assert!(filter.is_excluded(Path::new("README.md")));
    }

    #[test]
    fn test_recursive_directory_ignore() {
        let ignores = &["target".into()];
        let filter = NotificationFilter::new(&[], ignores, gitignore::load(&[]), ignore::load(&[]))
            .expect("test filter errors");

        assert!(filter.is_excluded(Path::new("target")));
        // Make sure that sub-directories/-files are recursively ignored.
        assert!(filter.is_excluded(Path::new("target/rls")));
        assert!(filter.is_excluded(Path::new("target/rls/debug")));
        assert!(!filter.is_excluded(Path::new("hello.rs")));
        assert!(!filter.is_excluded(Path::new("Cargo.toml")));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    Capability, CryptoKVStorage, Error, GetResponse, Identity, KVStorage, Policy, Storage, Value,
};
use chrono::DateTime;
use libra_vault_client::{self as vault, Client};

/// VaultStorage utilizes Vault for maintaining encrypted, authenticated data for Libra. This
/// version currently matches the behavior of OnDiskStorage and InMemoryStorage. In the future,
/// Vault will be able to create keys, sign messages, and handle permissions across different
/// services. The specific vault service leveraged herein is called KV (Key Value) Secrets Engine -
/// Version 2 (https://www.vaultproject.io/api/secret/kv/kv-v2.html). So while Libra Secure Storage
/// calls pointers to data keys, Vault has actually a secret that contains multiple key value
/// pairs.
pub struct VaultStorage {
    client: Client,
    namespace: Option<String>,
}

impl VaultStorage {
    pub fn new(host: String, token: String, namespace: Option<String>) -> Self {
        Self {
            client: Client::new(host, token),
            namespace,
        }
    }

    pub fn namespace(&self) -> Option<String> {
        self.namespace.clone()
    }

    /// Erase all secrets and keys from the vault storage. Use with caution.
    pub fn reset(&self) -> Result<(), Error> {
        self.reset_helper("")
    }

    fn reset_helper(&self, path: &str) -> Result<(), Error> {
        let secrets = self.client.list_secrets(path)?;
        for secret in secrets {
            if secret.ends_with('/') {
                self.reset_helper(&secret)?;
            } else {
                self.client.delete_secret(&format!("{}{}", path, secret))?;
            }
        }
        Ok(())
    }

    /// Creates a token but uses the namespace for policies
    pub fn create_token(&self, policies: Vec<&str>) -> Result<String, Error> {
        let result = if let Some(ns) = &self.namespace {
            let policies: Vec<_> = policies.iter().map(|p| format!("{}/{}", ns, p)).collect();
            self.client
                .create_token(policies.iter().map(|p| &**p).collect())?
        } else {
            self.client.create_token(policies)?
        };
        Ok(result)
    }

    /// Retrieves a key from a given secret. Libra Secure Storage inserts each key into its own
    /// distinct secret store and thus the secret and key have the same identifier.
    fn get_secret(&self, key: &str) -> Result<GetResponse, Error> {
        let secret = if let Some(namespace) = &self.namespace {
            format!("{}/{}", namespace, key)
        } else {
            key.to_string()
        };
        let (value, created_time) = self.client.read_secret(&secret, key)?;
        let last_update = DateTime::parse_from_rfc3339(&created_time)?.timestamp() as u64;
        let value = Value::from_base64(&value).unwrap();
        Ok(GetResponse { last_update, value })
    }

    /// Inserts a key, value pair into a secret that shares the name of the key.
    fn set_secret(&self, key: &str, value: Value) -> Result<(), Error> {
        let secret = if let Some(namespace) = &self.namespace {
            format!("{}/{}", namespace, key)
        } else {
            key.to_string()
        };
        self.client
            .write_secret(&secret, key, &value.to_base64()?)?;
        Ok(())
    }

    /// Create a new policy in Vault, see the explanation for Policy for how the data is
    /// structured. Vault does not distingush a create and update. An update must first read the
    /// existing policy, amend the contents,  and then be applied via this API.
    fn set_policy(
        &self,
        policy_name: &str,
        key: &str,
        capabilities: &[Capability],
    ) -> Result<(), Error> {
        let (path, policy_name) = if let Some(namespace) = &self.namespace {
            let path = format!("secret/data/{}/{}", namespace, key);
            let policy_name = if policy_name == "default" {
                policy_name.to_string()
            } else {
                format!("{}/{}", namespace, policy_name)
            };
            (path, policy_name)
        } else {
            (format!("secret/data/{}", key), policy_name.to_string())
        };

        let mut vault_policy = self.client.read_policy(&policy_name).unwrap_or_default();
        let vault_capabilities: Vec<vault::Capability> = capabilities
            .iter()
            .map(|c| match c {
                Capability::Write => vault::Capability::Update,
                Capability::Read => vault::Capability::Read,
            })
            .collect();
        vault_policy.add_policy(&path, vault_capabilities);
        self.client.set_policy(&policy_name, &vault_policy)?;
        Ok(())
    }

    /// Public convenience function to return a new Vault based Storage.
    pub fn new_storage(host: String, token: String, namespace: Option<String>) -> Box<dyn Storage> {
        Box::new(VaultStorage::new(host, token, namespace))
    }
}

impl KVStorage for VaultStorage {
    fn available(&self) -> bool {
        self.client.unsealed().unwrap_or(false)
    }

    fn create(&mut self, key: &str, value: Value, policy: &Policy) -> Result<(), Error> {
        // Vault internally does not distinguish creation versus update except by permissions. So we
        // simulate that by first getting the key. If it doesn't exist, we're okay.
        match self.get_secret(&key) {
            Ok(_) => return Err(Error::KeyAlreadyExists(key.to_string())),
            Err(Error::KeyNotSet(_)) => (/* Expected this for new keys! */),
            Err(e) => return Err(e),
        }

        self.set_secret(&key, value)?;
        for permission in &policy.permissions {
            match &permission.id {
                Identity::User(id) => self.set_policy(id, key, &permission.capabilities)?,
                Identity::Anyone => self.set_policy("default", key, &permission.capabilities)?,
                Identity::NoOne => (),
            };
        }
        Ok(())
    }

    fn get(&self, key: &str) -> Result<GetResponse, Error> {
        self.get_secret(&key)
    }

    fn set(&mut self, key: &str, value: Value) -> Result<(), Error> {
        // Vault internally does not distinguish create versus udpate except by permissions. So we
        // simulate that by first getting the key. If it exists, we can update it.
        self.get_secret(&key)?;
        self.set_secret(&key, value)?;
        Ok(())
    }

    fn reset_and_clear(&mut self) -> Result<(), Error> {
        self.reset()
    }
}

impl CryptoKVStorage for VaultStorage {}
<commit_msg>[vault] Do not modify default policy<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    Capability, CryptoKVStorage, Error, GetResponse, Identity, KVStorage, Policy, Storage, Value,
};
use chrono::DateTime;
use libra_vault_client::{self as vault, Client};

const LIBRA_DEFAULT: &str = "libra_default";

/// VaultStorage utilizes Vault for maintaining encrypted, authenticated data for Libra. This
/// version currently matches the behavior of OnDiskStorage and InMemoryStorage. In the future,
/// Vault will be able to create keys, sign messages, and handle permissions across different
/// services. The specific vault service leveraged herein is called KV (Key Value) Secrets Engine -
/// Version 2 (https://www.vaultproject.io/api/secret/kv/kv-v2.html). So while Libra Secure Storage
/// calls pointers to data keys, Vault has actually a secret that contains multiple key value
/// pairs.
pub struct VaultStorage {
    client: Client,
    namespace: Option<String>,
}

impl VaultStorage {
    pub fn new(host: String, token: String, namespace: Option<String>) -> Self {
        Self {
            client: Client::new(host, token),
            namespace,
        }
    }

    pub fn namespace(&self) -> Option<String> {
        self.namespace.clone()
    }

    /// Erase all secrets and keys from the vault storage. Use with caution.
    pub fn reset(&self) -> Result<(), Error> {
        self.reset_helper("")
    }

    fn reset_helper(&self, path: &str) -> Result<(), Error> {
        let secrets = self.client.list_secrets(path)?;
        for secret in secrets {
            if secret.ends_with('/') {
                self.reset_helper(&secret)?;
            } else {
                self.client.delete_secret(&format!("{}{}", path, secret))?;
            }
        }
        Ok(())
    }

    /// Creates a token but uses the namespace for policies
    pub fn create_token(&self, mut policies: Vec<&str>) -> Result<String, Error> {
        policies.push(LIBRA_DEFAULT);
        let result = if let Some(ns) = &self.namespace {
            let policies: Vec<_> = policies.iter().map(|p| format!("{}/{}", ns, p)).collect();
            self.client
                .create_token(policies.iter().map(|p| &**p).collect())?
        } else {
            self.client.create_token(policies)?
        };
        Ok(result)
    }

    /// Retrieves a key from a given secret. Libra Secure Storage inserts each key into its own
    /// distinct secret store and thus the secret and key have the same identifier.
    fn get_secret(&self, key: &str) -> Result<GetResponse, Error> {
        let secret = if let Some(namespace) = &self.namespace {
            format!("{}/{}", namespace, key)
        } else {
            key.to_string()
        };
        let (value, created_time) = self.client.read_secret(&secret, key)?;
        let last_update = DateTime::parse_from_rfc3339(&created_time)?.timestamp() as u64;
        let value = Value::from_base64(&value).unwrap();
        Ok(GetResponse { last_update, value })
    }

    /// Inserts a key, value pair into a secret that shares the name of the key.
    fn set_secret(&self, key: &str, value: Value) -> Result<(), Error> {
        let secret = if let Some(namespace) = &self.namespace {
            format!("{}/{}", namespace, key)
        } else {
            key.to_string()
        };
        self.client
            .write_secret(&secret, key, &value.to_base64()?)?;
        Ok(())
    }

    /// Create a new policy in Vault, see the explanation for Policy for how the data is
    /// structured. Vault does not distingush a create and update. An update must first read the
    /// existing policy, amend the contents,  and then be applied via this API.
    fn set_policy(
        &self,
        policy_name: &str,
        key: &str,
        capabilities: &[Capability],
    ) -> Result<(), Error> {
        let (path, policy_name) = if let Some(namespace) = &self.namespace {
            let path = format!("secret/data/{}/{}", namespace, key);
            let policy_name = format!("{}/{}", namespace, policy_name);
            (path, policy_name)
        } else {
            (format!("secret/data/{}", key), policy_name.to_string())
        };

        let mut vault_policy = self.client.read_policy(&policy_name).unwrap_or_default();
        let vault_capabilities: Vec<vault::Capability> = capabilities
            .iter()
            .map(|c| match c {
                Capability::Write => vault::Capability::Update,
                Capability::Read => vault::Capability::Read,
            })
            .collect();
        vault_policy.add_policy(&path, vault_capabilities);
        self.client.set_policy(&policy_name, &vault_policy)?;
        Ok(())
    }

    /// Public convenience function to return a new Vault based Storage.
    pub fn new_storage(host: String, token: String, namespace: Option<String>) -> Box<dyn Storage> {
        Box::new(VaultStorage::new(host, token, namespace))
    }
}

impl KVStorage for VaultStorage {
    fn available(&self) -> bool {
        self.client.unsealed().unwrap_or(false)
    }

    fn create(&mut self, key: &str, value: Value, policy: &Policy) -> Result<(), Error> {
        // Vault internally does not distinguish creation versus update except by permissions. So we
        // simulate that by first getting the key. If it doesn't exist, we're okay.
        match self.get_secret(&key) {
            Ok(_) => return Err(Error::KeyAlreadyExists(key.to_string())),
            Err(Error::KeyNotSet(_)) => (/* Expected this for new keys! */),
            Err(e) => return Err(e),
        }

        self.set_secret(&key, value)?;
        for permission in &policy.permissions {
            match &permission.id {
                Identity::User(id) => self.set_policy(id, key, &permission.capabilities)?,
                Identity::Anyone => {
                    self.set_policy(LIBRA_DEFAULT, key, &permission.capabilities)?
                }
                Identity::NoOne => (),
            };
        }
        Ok(())
    }

    fn get(&self, key: &str) -> Result<GetResponse, Error> {
        self.get_secret(&key)
    }

    fn set(&mut self, key: &str, value: Value) -> Result<(), Error> {
        // Vault internally does not distinguish create versus udpate except by permissions. So we
        // simulate that by first getting the key. If it exists, we can update it.
        self.get_secret(&key)?;
        self.set_secret(&key, value)?;
        Ok(())
    }

    fn reset_and_clear(&mut self) -> Result<(), Error> {
        self.reset()
    }
}

impl CryptoKVStorage for VaultStorage {}
<|endoftext|>


<commit_before>use sdl2::mixer::Music;
use rand::thread_rng;
use std::path::PathBuf;
use rand::Rng;

pub struct Playlist {
    tracks: Vec<Music<'static>>,
    current_track: usize,
    pub shuffle: bool,
    pub loop_music: bool,
}

impl Playlist {
    pub fn new() -> Playlist {
        Playlist {
            tracks: Vec::new(),
            current_track: 0,
            shuffle: false,
            loop_music: false,
        }
    }

    pub fn start(&mut self) {
        if self.shuffle {
            self.shuffle();
        }
        self.play_track(0).expect("No tracks present.");
    }

    fn shuffle(&mut self) {
        if self.tracks.len() > 1 {
            let mut new_tracks = Vec::new();

            // Make sure the new first track is never the previous last track.  Keeps from hearing
            // the same song twice in a row.
            new_tracks.push(unborrow!(self.tracks.remove(thread_rng().gen_range(0, self.tracks.len()-1))));
            while self.tracks.len() > 0 {
                new_tracks.push(unborrow!(self.tracks.remove(thread_rng().gen_range(0, self.tracks.len()))));
            }
            self.tracks = new_tracks;
        }
    }

    pub fn next_track(&mut self) {
        Music::halt();
        if self.current_track < self.tracks.len() - 1 {
            unborrow!(self.play_track(self.current_track + 1))
                .expect("Track index invalid.");
        } else if self.loop_music {
            if self.shuffle {
                self.shuffle();
            }
            self.play_track(0).expect("Track index invalid.");
        }
    }

    /// Returns err if track is not a valid index into self.tracks
    pub fn play_track(&mut self, track: usize) -> Result<(), String> {
        Music::halt();
        if track < self.tracks.len() {
            self.current_track = track;
            self.tracks[track].play(1)?;
            return Ok(());
        } else {
            return Err("Track index invalid.".to_string());
        }
    }

    pub fn current_track(&self) -> usize {
        self.current_track
    }

    pub fn add_track(&mut self, path: &str) -> Result<(), String> {
        let mut file_path = PathBuf::from("assets");
        file_path.push("music");
        file_path.push(path);
        self.tracks.push(Music::from_file(file_path)?);
        Ok(())
    }
}

pub fn advance_if_needed(playlist: &mut Playlist) {
    if !Music::is_playing() {
        playlist.next_track();
    }
}
<commit_msg>Fix music halt again<commit_after>use sdl2::mixer::Music;
use rand::thread_rng;
use std::path::PathBuf;
use rand::Rng;

pub struct Playlist {
    tracks: Vec<Music<'static>>,
    current_track: usize,
    pub shuffle: bool,
    pub loop_music: bool,
}

impl Playlist {
    pub fn new() -> Playlist {
        Playlist {
            tracks: Vec::new(),
            current_track: 0,
            shuffle: false,
            loop_music: false,
        }
    }

    pub fn start(&mut self) {
        if self.shuffle {
            self.shuffle();
        }
        self.play_track(0).expect("No tracks present.");
    }

    fn shuffle(&mut self) {
        if self.tracks.len() > 1 {
            let mut new_tracks = Vec::new();

            // Make sure the new first track is never the previous last track.  Keeps from hearing
            // the same song twice in a row.
            new_tracks.push(unborrow!(self.tracks.remove(thread_rng().gen_range(0, self.tracks.len()-1))));
            while self.tracks.len() > 0 {
                new_tracks.push(unborrow!(self.tracks.remove(thread_rng().gen_range(0, self.tracks.len()))));
            }
            self.tracks = new_tracks;
        }
    }

    pub fn next_track(&mut self) {
        if self.current_track < self.tracks.len() - 1 {
            unborrow!(self.play_track(self.current_track + 1))
                .expect("Track index invalid.");
        } else if self.loop_music {
            if self.shuffle {
                self.shuffle();
            }
            self.play_track(0).expect("Track index invalid.");
        } else {
            Music::halt();
        }
    }

    /// Returns err if track is not a valid index into self.tracks
    pub fn play_track(&mut self, track: usize) -> Result<(), String> {
        if track < self.tracks.len() {
            self.current_track = track;
            self.tracks[track].play(1)?;
            return Ok(());
        } else {
            return Err("Track index invalid.".to_string());
        }
    }

    pub fn current_track(&self) -> usize {
        self.current_track
    }

    pub fn add_track(&mut self, path: &str) -> Result<(), String> {
        let mut file_path = PathBuf::from("assets");
        file_path.push("music");
        file_path.push(path);
        self.tracks.push(Music::from_file(file_path)?);
        Ok(())
    }
}

pub fn advance_if_needed(playlist: &mut Playlist) {
    if !Music::is_playing() {
        playlist.next_track();
    }
}
<|endoftext|>


<commit_before>use anyhow::{Error, Result};
use std::env;
use std::path::Path;
use std::process::Command;

/// Return a `String` to use for the given executable.
///
/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
/// gives a valid Cargo executable; or it may return a full path to a valid
/// Cargo.
pub fn get_path_for_executable(executable_name: impl AsRef<str>) -> Result<String> {
    // The current implementation checks three places for an executable to use:
    // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
    //      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
    // 2) `<executable_name>`
    //      example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
    // 3) `~/.cargo/bin/<executable_name>`
    //      example: for cargo, this tries ~/.cargo/bin/cargo
    //      It seems that this is a reasonable place to try for cargo, rustc, and rustup
    let executable_name = executable_name.as_ref();
    let env_var = executable_name.to_ascii_uppercase();
    if let Ok(path) = env::var(&env_var) {
        if is_valid_executable(&path) {
            Ok(path)
        } else {
            Err(Error::msg(format!(
                "`{}` environment variable points to something that's not a valid executable",
                env_var
            )))
        }
    } else {
        let final_path: Option<String> = if is_valid_executable(executable_name) {
            Some(executable_name.to_owned())
        } else {
            if let Some(mut path) = dirs::home_dir() {
                path.push(".cargo");
                path.push("bin");
                path.push(executable_name);
                if is_valid_executable(&path) {
                    Some(path.into_os_string().into_string().expect("Invalid Unicode in path"))
                } else {
                    None
                }
            } else {
                None
            }
        };
        final_path.ok_or(
            // This error message may also be caused by $PATH or $CARGO/$RUSTC/etc not being set correctly
            // for VSCode, even if they are set correctly in a terminal.
            // On macOS in particular, launching VSCode from terminal with `code <dirname>` causes VSCode
            // to inherit environment variables including $PATH, $CARGO, $RUSTC, etc from that terminal;
            // but launching VSCode from Dock does not inherit environment variables from a terminal.
            // For more discussion, see #3118.
            Error::msg(format!("Failed to find `{}` executable. Make sure `{}` is in `$PATH`, or set `${}` to point to a valid executable.", executable_name, executable_name, env_var))
        )
    }
}

/// Does the given `Path` point to a usable executable?
///
/// (assumes the executable takes a `--version` switch and writes to stdout,
/// which is true for `cargo`, `rustc`, and `rustup`)
fn is_valid_executable(p: impl AsRef<Path>) -> bool {
    Command::new(p.as_ref()).arg("--version").output().is_ok()
}
<commit_msg>add module-level docs so that tests pass<commit_after>//! This crate contains a single public function
//! [`get_path_for_executable`](fn.get_path_for_executable.html).
//! See docs there for more information.

use anyhow::{Error, Result};
use std::env;
use std::path::Path;
use std::process::Command;

/// Return a `String` to use for the given executable.
///
/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
/// gives a valid Cargo executable; or it may return a full path to a valid
/// Cargo.
pub fn get_path_for_executable(executable_name: impl AsRef<str>) -> Result<String> {
    // The current implementation checks three places for an executable to use:
    // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
    //      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
    // 2) `<executable_name>`
    //      example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
    // 3) `~/.cargo/bin/<executable_name>`
    //      example: for cargo, this tries ~/.cargo/bin/cargo
    //      It seems that this is a reasonable place to try for cargo, rustc, and rustup
    let executable_name = executable_name.as_ref();
    let env_var = executable_name.to_ascii_uppercase();
    if let Ok(path) = env::var(&env_var) {
        if is_valid_executable(&path) {
            Ok(path)
        } else {
            Err(Error::msg(format!(
                "`{}` environment variable points to something that's not a valid executable",
                env_var
            )))
        }
    } else {
        let final_path: Option<String> = if is_valid_executable(executable_name) {
            Some(executable_name.to_owned())
        } else {
            if let Some(mut path) = dirs::home_dir() {
                path.push(".cargo");
                path.push("bin");
                path.push(executable_name);
                if is_valid_executable(&path) {
                    Some(path.into_os_string().into_string().expect("Invalid Unicode in path"))
                } else {
                    None
                }
            } else {
                None
            }
        };
        final_path.ok_or(
            // This error message may also be caused by $PATH or $CARGO/$RUSTC/etc not being set correctly
            // for VSCode, even if they are set correctly in a terminal.
            // On macOS in particular, launching VSCode from terminal with `code <dirname>` causes VSCode
            // to inherit environment variables including $PATH, $CARGO, $RUSTC, etc from that terminal;
            // but launching VSCode from Dock does not inherit environment variables from a terminal.
            // For more discussion, see #3118.
            Error::msg(format!("Failed to find `{}` executable. Make sure `{}` is in `$PATH`, or set `${}` to point to a valid executable.", executable_name, executable_name, env_var))
        )
    }
}

/// Does the given `Path` point to a usable executable?
///
/// (assumes the executable takes a `--version` switch and writes to stdout,
/// which is true for `cargo`, `rustc`, and `rustup`)
fn is_valid_executable(p: impl AsRef<Path>) -> bool {
    Command::new(p.as_ref()).arg("--version").output().is_ok()
}
<|endoftext|>


<commit_before>extern crate ctest;

use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let mingw = target.contains("windows-gnu");
    let mut cfg = ctest::TestGenerator::new();

    // Pull in extra goodies on linux/mingw
    if target.contains("unknown-linux-gnu") {
        cfg.define("_GNU_SOURCE", None);
    } else if target.contains("windows") {
        cfg.define("_WIN32_WINNT", Some("0x8000"));
    }

    // Android doesn't actually have in_port_t but it's much easier if we
    // provide one for us to test against
    if target.contains("android") {
        cfg.define("in_port_t", Some("uint16_t"));
    }

    cfg.header("errno.h")
       .header("fcntl.h")
       .header("limits.h")
       .header("stddef.h")
       .header("stdint.h")
       .header("stdio.h")
       .header("stdlib.h")
       .header("sys/stat.h")
       .header("sys/types.h")
       .header("time.h")
       .header("wchar.h");

    if target.contains("apple-darwin") {
        cfg.header("mach-o/dyld.h");
        cfg.header("mach/mach_time.h");
    } else if target.contains("unknown-linux") ||
              target.contains("android") {
        cfg.header("linux/if_packet.h");
        cfg.header("net/ethernet.h");
    }

    if target.contains("windows") {
        cfg.header("winsock2.h"); // must be before windows.h

        cfg.header("direct.h");
        cfg.header("io.h");
        cfg.header("sys/utime.h");
        cfg.header("windows.h");
        cfg.header("process.h");
        cfg.header("ws2ipdef.h");

        if target.contains("gnu") {
            cfg.header("ws2tcpip.h");
        }
    } else {
        cfg.header("ctype.h");
        cfg.header("dirent.h");
        cfg.header("net/if.h");
        cfg.header("netdb.h");
        cfg.header("netinet/in.h");
        cfg.header("netinet/ip.h");
        cfg.header("netinet/tcp.h");
        cfg.header("pthread.h");
        cfg.header("signal.h");
        cfg.header("string.h");
        cfg.header("sys/file.h");
        cfg.header("sys/ioctl.h");
        cfg.header("sys/mman.h");
        cfg.header("sys/resource.h");
        cfg.header("sys/socket.h");
        cfg.header("sys/time.h");
        cfg.header("sys/un.h");
        cfg.header("sys/wait.h");
        cfg.header("unistd.h");
        cfg.header("utime.h");

        if target.contains("android") {
            cfg.header("arpa/inet.h");
        } else {
            cfg.header("glob.h");
            cfg.header("ifaddrs.h");
            cfg.header("sys/sysctl.h");
        }
    }

    cfg.type_name(move |ty, is_struct| {
        match ty {
            // Just pass all these through, no need for a "struct" prefix
            "glob_t" |
            "FILE" |
            "DIR" |
            "fpos_t" => ty.to_string(),
            t if t.starts_with("pthread") => t.to_string(),

            // Windows uppercase structs don't have `struct` in front, there's a
            // few special cases for windows, and then otherwise put `struct` in
            // front of everything.
            t if is_struct => {
                if windows && ty.chars().next().unwrap().is_uppercase() {
                    t.to_string()
                } else if windows && t == "stat" {
                    "struct __stat64".to_string()
                } else if windows && t == "utimbuf" {
                    "struct __utimbuf64".to_string()
                } else {
                    format!("struct {}", t)
                }
            }

            // Fixup a few types on windows that don't actually exist.
            "time64_t" if windows => "__time64_t".to_string(),
            "ssize_t" if windows => "SSIZE_T".to_string(),

            t => t.to_string(),
        }
    });

    let target2 = target.clone();
    cfg.field_name(move |struct_, field| {
        match field {
            // Our stat *_nsec fields normally don't actually exist but are part
            // of a timeval struct
            s if s.ends_with("_nsec") && struct_ == "stat" => {
                if target2.contains("apple-darwin") {
                    s.replace("_nsec", "spec.tv_nsec")
                } else if target2.contains("android") {
                    s.to_string()
                } else {
                    s.replace("e_nsec", ".tv_nsec")
                }
            }
            s => s.to_string(),
        }
    });

    let target2 = target.clone();
    cfg.skip_type(move |ty| {
        match ty {
            // sighandler_t is crazy across platforms
            "sighandler_t" => true,

            _ => false
        }
    });

    cfg.skip_signededness(|c| {
        match c {
            "LARGE_INTEGER" |
            "mach_timebase_info_data_t" |
            "float" |
            "double" => true,
            n if n.starts_with("pthread") => true,

            // windows-isms
            n if n.starts_with("P") => true,
            n if n.starts_with("H") => true,
            n if n.starts_with("LP") => true,
            _ => false,
        }
    });

    // Apparently these don't exist in mingw headers?
    cfg.skip_const(move |name| {
        match name {
            "MEM_RESET_UNDO" |
            "FILE_ATTRIBUTE_NO_SCRUB_DATA" |
            "FILE_ATTRIBUTE_INTEGRITY_STREAM" |
            "ERROR_NOTHING_TO_TERMINATE" if mingw => true,
            "SIG_IGN" => true, // sighandler_t weirdness
            _ => false,
        }
    });

    cfg.skip_fn(|name| {
        match name {
            // manually verified
            "execv" |
            "execve" |
            "execvp" |
            "execvpe" |
            "glob" |
            "getrlimit" |
            "setrlimit" |
            "signal" |
            "getopt" => true,
            _ => false,
        }
    });

    // Windows dllimport oddness?
    cfg.skip_fn_ptrcheck(move |_| windows);

    cfg.skip_field_type(|struct_, field| {
        // This is a weird union, don't check the type.
        struct_ == "ifaddrs" && field == "ifa_ifu"
    });

    cfg.generate("../src/lib.rs", "all.rs");
}
<commit_msg>Fix unused variable warning<commit_after>#![deny(warnings)]

extern crate ctest;

use std::env;

fn main() {
    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let mingw = target.contains("windows-gnu");
    let mut cfg = ctest::TestGenerator::new();

    // Pull in extra goodies on linux/mingw
    if target.contains("unknown-linux-gnu") {
        cfg.define("_GNU_SOURCE", None);
    } else if target.contains("windows") {
        cfg.define("_WIN32_WINNT", Some("0x8000"));
    }

    // Android doesn't actually have in_port_t but it's much easier if we
    // provide one for us to test against
    if target.contains("android") {
        cfg.define("in_port_t", Some("uint16_t"));
    }

    cfg.header("errno.h")
       .header("fcntl.h")
       .header("limits.h")
       .header("stddef.h")
       .header("stdint.h")
       .header("stdio.h")
       .header("stdlib.h")
       .header("sys/stat.h")
       .header("sys/types.h")
       .header("time.h")
       .header("wchar.h");

    if target.contains("apple-darwin") {
        cfg.header("mach-o/dyld.h");
        cfg.header("mach/mach_time.h");
    } else if target.contains("unknown-linux") ||
              target.contains("android") {
        cfg.header("linux/if_packet.h");
        cfg.header("net/ethernet.h");
    }

    if target.contains("windows") {
        cfg.header("winsock2.h"); // must be before windows.h

        cfg.header("direct.h");
        cfg.header("io.h");
        cfg.header("sys/utime.h");
        cfg.header("windows.h");
        cfg.header("process.h");
        cfg.header("ws2ipdef.h");

        if target.contains("gnu") {
            cfg.header("ws2tcpip.h");
        }
    } else {
        cfg.header("ctype.h");
        cfg.header("dirent.h");
        cfg.header("net/if.h");
        cfg.header("netdb.h");
        cfg.header("netinet/in.h");
        cfg.header("netinet/ip.h");
        cfg.header("netinet/tcp.h");
        cfg.header("pthread.h");
        cfg.header("signal.h");
        cfg.header("string.h");
        cfg.header("sys/file.h");
        cfg.header("sys/ioctl.h");
        cfg.header("sys/mman.h");
        cfg.header("sys/resource.h");
        cfg.header("sys/socket.h");
        cfg.header("sys/time.h");
        cfg.header("sys/un.h");
        cfg.header("sys/wait.h");
        cfg.header("unistd.h");
        cfg.header("utime.h");

        if target.contains("android") {
            cfg.header("arpa/inet.h");
        } else {
            cfg.header("glob.h");
            cfg.header("ifaddrs.h");
            cfg.header("sys/sysctl.h");
        }
    }

    cfg.type_name(move |ty, is_struct| {
        match ty {
            // Just pass all these through, no need for a "struct" prefix
            "glob_t" |
            "FILE" |
            "DIR" |
            "fpos_t" => ty.to_string(),
            t if t.starts_with("pthread") => t.to_string(),

            // Windows uppercase structs don't have `struct` in front, there's a
            // few special cases for windows, and then otherwise put `struct` in
            // front of everything.
            t if is_struct => {
                if windows && ty.chars().next().unwrap().is_uppercase() {
                    t.to_string()
                } else if windows && t == "stat" {
                    "struct __stat64".to_string()
                } else if windows && t == "utimbuf" {
                    "struct __utimbuf64".to_string()
                } else {
                    format!("struct {}", t)
                }
            }

            // Fixup a few types on windows that don't actually exist.
            "time64_t" if windows => "__time64_t".to_string(),
            "ssize_t" if windows => "SSIZE_T".to_string(),

            t => t.to_string(),
        }
    });

    let target2 = target.clone();
    cfg.field_name(move |struct_, field| {
        match field {
            // Our stat *_nsec fields normally don't actually exist but are part
            // of a timeval struct
            s if s.ends_with("_nsec") && struct_ == "stat" => {
                if target2.contains("apple-darwin") {
                    s.replace("_nsec", "spec.tv_nsec")
                } else if target2.contains("android") {
                    s.to_string()
                } else {
                    s.replace("e_nsec", ".tv_nsec")
                }
            }
            s => s.to_string(),
        }
    });

    cfg.skip_type(move |ty| {
        match ty {
            // sighandler_t is crazy across platforms
            "sighandler_t" => true,

            _ => false
        }
    });

    cfg.skip_signededness(|c| {
        match c {
            "LARGE_INTEGER" |
            "mach_timebase_info_data_t" |
            "float" |
            "double" => true,
            n if n.starts_with("pthread") => true,

            // windows-isms
            n if n.starts_with("P") => true,
            n if n.starts_with("H") => true,
            n if n.starts_with("LP") => true,
            _ => false,
        }
    });

    // Apparently these don't exist in mingw headers?
    cfg.skip_const(move |name| {
        match name {
            "MEM_RESET_UNDO" |
            "FILE_ATTRIBUTE_NO_SCRUB_DATA" |
            "FILE_ATTRIBUTE_INTEGRITY_STREAM" |
            "ERROR_NOTHING_TO_TERMINATE" if mingw => true,
            "SIG_IGN" => true, // sighandler_t weirdness
            _ => false,
        }
    });

    cfg.skip_fn(|name| {
        match name {
            // manually verified
            "execv" |
            "execve" |
            "execvp" |
            "execvpe" |
            "glob" |
            "getrlimit" |
            "setrlimit" |
            "signal" |
            "getopt" => true,
            _ => false,
        }
    });

    // Windows dllimport oddness?
    cfg.skip_fn_ptrcheck(move |_| windows);

    cfg.skip_field_type(|struct_, field| {
        // This is a weird union, don't check the type.
        struct_ == "ifaddrs" && field == "ifa_ifu"
    });

    cfg.generate("../src/lib.rs", "all.rs");
}
<|endoftext|>


<commit_before>// run-pass

pub fn main() {
    let x = "hello";
    let v = "hello";
    let y : &str = "there";

    println!("{}", x);
    println!("{}", y);

    assert_eq!(x.as_bytes()[0], 'h' as u8);
    assert_eq!(x.as_bytes()[4], 'o' as u8);

    let z : &str = "thing";
    assert_eq!(v, x);
    assert!(x != z);

    let a = "aaaa";
    let b = "bbbb";

    let c = "cccc";
    let cc = "ccccc";

    println!("{}", a);

    assert!(a < b);
    assert!(a <= b);
    assert!(a != b);
    assert!(b >= a);
    assert!(b > a);

    println!("{}", b);

    assert!(a < c);
    assert!(a <= c);
    assert!(a != c);
    assert!(c >= a);
    assert!(c > a);

    println!("{}", c);

    assert!(c < cc);
    assert!(c <= cc);
    assert!(c != cc);
    assert!(cc >= c);
    assert!(cc > c);

    println!("{}", cc);
}
<commit_msg>Improved test output for estr-slice<commit_after>// run-pass

pub fn main() {
    let x = "hello";
    let v = "hello";
    let y : &str = "there";

    println!("{}", x);
    println!("{}", y);

    assert_eq!(x.as_bytes()[0], 'h' as u8);
    assert_eq!(x.as_bytes()[4], 'o' as u8);

    let z : &str = "thing";
    assert_eq!(v, x);
    assert_ne!(x, z);

    let a = "aaaa";
    let b = "bbbb";

    let c = "cccc";
    let cc = "ccccc";

    println!("{}", a);

    assert!(a < b);
    assert!(a <= b);
    assert_ne!(a, b);
    assert!(b >= a);
    assert!(b > a);

    println!("{}", b);

    assert!(a < c);
    assert!(a <= c);
    assert_ne!(a, c);
    assert!(c >= a);
    assert!(c > a);

    println!("{}", c);

    assert!(c < cc);
    assert!(c <= cc);
    assert_ne!(c, cc);
    assert!(cc >= c);
    assert!(cc > c);

    println!("{}", cc);
}
<|endoftext|>


<commit_before>// Copyright 2017 CoreOS, 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.

//! digital ocean metadata fetcher

use metadata::Metadata;

use errors::*;

pub fn fetch_metadata() -> Result<Metadata> {
    unimplemented!();
}
<commit_msg>providers/digitalocean: initial implementation<commit_after>// Copyright 2017 CoreOS, 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.

//! digital ocean metadata fetcher

use retry;
use metadata;
use network;
use ipnetwork;
use ipnetwork::{IpNetwork,Ipv4Network,Ipv6Network};
use pnet::util::MacAddr;

use std::str::FromStr;
use std::net::{IpAddr,Ipv4Addr,Ipv6Addr};
use std::collections::HashMap;

use errors::*;

#[derive(Clone,Deserialize)]
struct Address {
    ip_address: IpAddr,
    netmask: Option<IpAddr>,
    cidr: Option<u8>,
    gateway: IpAddr,
}

#[derive(Clone,Deserialize)]
struct Interface {
    ipv4: Option<Address>,
    ipv6: Option<Address>,
    anchor_ipv4: Option<Address>,
    mac: String,
    #[serde(rename = "type")]
    type_name: String,
}

#[derive(Clone,Deserialize)]
struct Interfaces {
    public: Option<Vec<Interface>>,
    private: Option<Vec<Interface>>,
}

#[derive(Clone,Deserialize)]
struct DNS {
    nameservers: Vec<IpAddr>
}

#[derive(Clone,Deserialize)]
struct Metadata {
    hostname: String,
    interfaces: Interfaces,
    public_keys: Vec<String>,
    region: String,
    dns: DNS,
}

pub fn fetch_metadata() -> Result<metadata::Metadata> {
    let client = retry::Client::new()?;
    let data: Metadata = client.get(retry::Json, "http://169.254.169.254/metadata/v1.json".to_owned()).send()?
        .ok_or("not found")?;

    let attrs = parse_attrs(&data)?;
    let interfaces = parse_network(&data)?;

    let mut m = metadata::Metadata::builder()
        .add_ssh_keys(data.public_keys)?
        .set_hostname(data.hostname);

    for (key,val) in attrs {
        m = m.add_attribute(key,val);
    }
    for iface in interfaces {
        m = m.add_network_interface(iface);
    }
    Ok(m.build())
}

fn parse_attrs(data: &Metadata) -> Result<Vec<(String,String)>> {
    let mut attrs = Vec::new();

    attrs.push(("DIGITALOCEAN_HOSTNAME".to_owned(), data.hostname.clone()));
    attrs.push(("DIGITALOCEAN_REGION".to_owned(), data.region.clone()));

    let mut public_counter = 0;
    let mut private_counter = 0;
    if let Some(ifaces) = data.interfaces.public.clone() {
        for a in ifaces {
            if a.ipv4.is_some() {
                attrs.push((
                    format!("DIGITALOCEAN_IPV4_PUBLIC_{}", public_counter),
                    format!("{}", a.ipv4.unwrap().ip_address)
                ));
            }
            if a.ipv6.is_some() {
                attrs.push((
                    format!("DIGITALOCEAN_IPV6_PUBLIC_{}", public_counter),
                    format!("{}", a.ipv6.unwrap().ip_address)
                ));
            }
            if a.anchor_ipv4.is_some() {
                attrs.push((
                    format!("DIGITALOCEAN_IPV4_ANCHOR_{}", public_counter),
                    format!("{}", a.anchor_ipv4.unwrap().ip_address)
                ));
            }
            public_counter += 1;
        }
    }
    if let Some(ifaces) = data.interfaces.private.clone() {
        for a in ifaces {
            if a.ipv4.is_some() {
                attrs.push((
                    format!("DIGITALOCEAN_IPV4_PRIVATE_{}", public_counter),
                    format!("{}", a.ipv4.unwrap().ip_address)
                ));
            }
            if a.ipv6.is_some() {
                attrs.push((
                    format!("DIGITALOCEAN_IPV6_PRIVATE_{}", private_counter),
                    format!("{}", a.ipv6.unwrap().ip_address)
                ));
            }
            private_counter += 1;
        }
    }
    Ok(attrs)
}

fn parse_network(data: &Metadata) -> Result<Vec<network::Interface>> {
    let mut interfaces = Vec::new();
    if let Some(ifaces) = data.interfaces.public.clone() {
        interfaces.extend(parse_interfaces(data, ifaces)?);
    }
    if let Some(ifaces) = data.interfaces.private.clone() {
        interfaces.extend(parse_interfaces(data, ifaces)?);
    }
    Ok(interfaces)
}

fn parse_interfaces(data: &Metadata, interfaces: Vec<Interface>) -> Result<Vec<network::Interface>> {
    let mut iface_config_map: HashMap<MacAddr,network::Interface> = HashMap::new();
    for iface in interfaces {
        let mac = MacAddr::from_str(&iface.mac)
            .map_err(|e| Error::from(format!("{:?}", e)))
            .chain_err(|| "failed to parse mac address")?;
        let (mut addrs, mut routes) = parse_interface(&iface)?;

        if let Some(existing_iface) = iface_config_map.get_mut(&mac) {
            addrs.extend(existing_iface.ip_addresses.clone());
            routes.extend(existing_iface.routes.clone());
        }
        iface_config_map.insert(mac, network::Interface{
            mac_address: Some(mac),
            nameservers: data.dns.nameservers.clone(),
            ip_addresses: addrs,
            routes: routes,
            bond: None,
            name: None,
            priority: None,
        });
    }
    let mut iface_configs = Vec::new();
    for i in iface_config_map.values() {
        iface_configs.push(i.clone());
    }
    Ok(iface_configs)
}

fn parse_interface(interface: &Interface) -> Result<(Vec<IpNetwork>,Vec<network::NetworkRoute>)> {
    let mut addrs = Vec::new();
    let mut routes = Vec::new();

    if interface.ipv4.is_some() {
        let netmask = interface.clone().ipv4.unwrap().netmask
            .ok_or("missing netmask for ipv4 address")?;
        let prefix = ipnetwork::ip_mask_to_prefix(netmask)
            .chain_err(|| "invalid network mask")?;
        let a = match interface.clone().ipv4.unwrap().ip_address {
            IpAddr::V4(a) => Some(a),
            IpAddr::V6(_) => None,
        }.ok_or("ipv6 address in ipv4 field")?;
        let net = IpNetwork::V4(Ipv4Network::new(a, prefix)
            .chain_err(|| "invalid ip address or prefix")?);
        addrs.push(net);
        routes.push(network::NetworkRoute{
            destination: net,
            gateway: interface.clone().ipv4.unwrap().gateway,
        });

        if interface.type_name == "public" {
            routes.push(network::NetworkRoute{
                destination: IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(0,0,0,0),0)
                                    .chain_err(|| "invalid ip address or prefix")?),
                gateway: interface.clone().ipv4.unwrap().gateway,
            });
        }
    }
    if interface.ipv6.is_some() {
        let cidr = interface.clone().ipv6.unwrap().cidr
            .ok_or("missing cidr for ipv6 address")?;
        let a = match interface.clone().ipv6.unwrap().ip_address {
            IpAddr::V4(_) => None,
            IpAddr::V6(a) => Some(a),
        }.ok_or("ipv4 address in ipv6 field")?;
        let net = IpNetwork::V6(Ipv6Network::new(a, cidr)
            .chain_err(|| "invalid ip address or prefix")?);
        addrs.push(net);
        routes.push(network::NetworkRoute{
            destination: net,
            gateway: interface.clone().ipv6.unwrap().gateway,
        });
        if interface.type_name == "public" {
            routes.push(network::NetworkRoute{
                destination: IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0,0,0,0,0,0,0,0),0)
                                    .chain_err(|| "invalid ip address or prefix")?),
                gateway: interface.clone().ipv6.unwrap().gateway,
            });
        }
    }
    if interface.anchor_ipv4.is_some() {
        let netmask = interface.clone().anchor_ipv4.unwrap().netmask
            .ok_or("missing netmask for anchor ipv4 address")?;
        let prefix = ipnetwork::ip_mask_to_prefix(netmask)
            .chain_err(|| "invalid network mask")?;
        let a = match interface.clone().anchor_ipv4.unwrap().ip_address {
            IpAddr::V4(a) => Some(a),
            IpAddr::V6(_) => None,
        }.ok_or("ipv6 address in ipv4 field")?;
        let net = IpNetwork::V4(Ipv4Network::new(a, prefix)
            .chain_err(|| "invalid ip address or prefix")?);
        addrs.push(net);
        routes.push(network::NetworkRoute{
            destination: net,
            gateway: interface.clone().anchor_ipv4.unwrap().gateway,
        });
    }
    Ok((addrs,routes))
}
<|endoftext|>


<commit_before>extern crate syntax;

use test_node::TestNode;

use syntax::ext::base::ExtCtxt;
use syntax::codemap;
use syntax::codemap::DUMMY_SP;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast::Mod;
use syntax::attr;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use syntax::owned_slice::OwnedSlice;

fn get_rustspec_extern_crate() -> ast::ViewItem {
    ast::ViewItem {
        node: ast::ViewItemExternCrate(token::str_to_ident("rustspec"),
        Some((token::intern_and_get_ident("rustspec"), ast::CookedStr)),
        ast::DUMMY_NODE_ID),
        attrs: vec![
            attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("phase"),
                vec!(
                    attr::mk_word_item(InternedString::new("plugin")),
                    attr::mk_word_item(InternedString::new("link"))
                    )
                )
            ),
        ],
        vis: ast::Inherited,
        span: DUMMY_SP
    }
}

fn get_rustspec_assertions_use() -> ast::ViewItem {
    let prelude_path = ast::Path {
        span: DUMMY_SP,
        global: false,
        segments: vec!(
            ast::PathSegment {
                identifier: token::str_to_ident("rustspec"),
                lifetimes: Vec::new(),
                types: OwnedSlice::empty(),
            }
        ),
    };

    let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID)));

    ast::ViewItem {
        node: ast::ViewItemUse(vp),
        attrs: Vec::new(),
        vis: ast::Inherited,
        span: DUMMY_SP,
    }
}

pub struct TestContextNode {
    name: String,
    before: Option<P<ast::Block>>,
    children: Vec<Box<TestNode + 'static>>
}

impl TestContextNode {
    pub fn new(name: String,
               before: Option<P<ast::Block>>,
               children: Vec<Box<TestNode + 'static>>
              ) -> Box<TestContextNode> {
        box TestContextNode { name: name, children: children, before: before }
    }
}

impl TestNode for TestContextNode {
    fn to_item(&self, cx: &mut ExtCtxt, before_blocks: &mut Vec<P<ast::Block>>) -> P<ast::Item> {
        self.before.as_ref().and_then(|before| {
            before_blocks.push(before.clone());
            None::<P<ast::Block>>
        });

        let children_items = self.children.iter().map(|i| i.to_item(cx, before_blocks)).collect::<Vec<P<ast::Item>>>();

        if self.before.is_some() {
            before_blocks.pop();
        }

        let mut attributes = vec![];

        attributes.push(attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("allow"),
                vec!(attr::mk_word_item(InternedString::new("unused_attribute")))
            )
        ));

        attributes.push(attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("allow"),
                vec!(attr::mk_word_item(InternedString::new("non_snake_case")))
            )
        ));

        P(ast::Item {
            ident: cx.ident_of(self.get_name().as_slice()),
            attrs: attributes,
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemMod(Mod {
                inner: DUMMY_SP,
                view_items: vec![
                    get_rustspec_extern_crate(),
                    get_rustspec_assertions_use()
                ],
                items: children_items
            }),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    }

    fn get_name(&self) -> String {
        self.name.replace(" ", "_").replace("#", "")
    }
}
<commit_msg>PathSegment doesn't have lifetimes or types anymore<commit_after>extern crate syntax;

use test_node::TestNode;

use syntax::ext::base::ExtCtxt;
use syntax::codemap;
use syntax::codemap::DUMMY_SP;
use syntax::ast;
use syntax::ptr::P;
use syntax::ast::Mod;
use syntax::attr;
use syntax::parse::token;
use syntax::parse::token::InternedString;

fn get_rustspec_extern_crate() -> ast::ViewItem {
    ast::ViewItem {
        node: ast::ViewItemExternCrate(token::str_to_ident("rustspec"),
        Some((token::intern_and_get_ident("rustspec"), ast::CookedStr)),
        ast::DUMMY_NODE_ID),
        attrs: vec![
            attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("phase"),
                vec!(
                    attr::mk_word_item(InternedString::new("plugin")),
                    attr::mk_word_item(InternedString::new("link"))
                    )
                )
            ),
        ],
        vis: ast::Inherited,
        span: DUMMY_SP
    }
}

fn get_rustspec_assertions_use() -> ast::ViewItem {
    let prelude_path = ast::Path {
        span: DUMMY_SP,
        global: false,
        segments: vec!(
            ast::PathSegment {
                identifier: token::str_to_ident("rustspec"),
                parameters: ast::PathParameters::none()
            }
        ),
    };

    let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID)));

    ast::ViewItem {
        node: ast::ViewItemUse(vp),
        attrs: Vec::new(),
        vis: ast::Inherited,
        span: DUMMY_SP,
    }
}

pub struct TestContextNode {
    name: String,
    before: Option<P<ast::Block>>,
    children: Vec<Box<TestNode + 'static>>
}

impl TestContextNode {
    pub fn new(name: String,
               before: Option<P<ast::Block>>,
               children: Vec<Box<TestNode + 'static>>
              ) -> Box<TestContextNode> {
        box TestContextNode { name: name, children: children, before: before }
    }
}

impl TestNode for TestContextNode {
    fn to_item(&self, cx: &mut ExtCtxt, before_blocks: &mut Vec<P<ast::Block>>) -> P<ast::Item> {
        self.before.as_ref().and_then(|before| {
            before_blocks.push(before.clone());
            None::<P<ast::Block>>
        });

        let children_items = self.children.iter().map(|i| i.to_item(cx, before_blocks)).collect::<Vec<P<ast::Item>>>();

        if self.before.is_some() {
            before_blocks.pop();
        }

        let mut attributes = vec![];

        attributes.push(attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("allow"),
                vec!(attr::mk_word_item(InternedString::new("unused_attribute")))
            )
        ));

        attributes.push(attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
                InternedString::new("allow"),
                vec!(attr::mk_word_item(InternedString::new("non_snake_case")))
            )
        ));

        P(ast::Item {
            ident: cx.ident_of(self.get_name().as_slice()),
            attrs: attributes,
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemMod(Mod {
                inner: DUMMY_SP,
                view_items: vec![
                    get_rustspec_extern_crate(),
                    get_rustspec_assertions_use()
                ],
                items: children_items
            }),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    }

    fn get_name(&self) -> String {
        self.name.replace(" ", "_").replace("#", "")
    }
}
<|endoftext|>


<commit_before>// run-pass
#![feature(const_discriminant)]
#![allow(dead_code)]

use std::mem::{discriminant, Discriminant};

fn identity<T>(x: T) -> T { x }

enum Test {
    A(u8),
    B,
    C { a: u8, b: u8 },
}

const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
const TEST_B: Discriminant<Test> = discriminant(&Test::B);

enum Void {}

enum SingleVariant {
    V,
    Never(Void),
}

const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);

fn main() {
    assert_eq!(TEST_A, TEST_A_OTHER);
    assert_eq!(TEST_A, discriminant(identity(&Test::A(17))));
    assert_eq!(TEST_B, discriminant(identity(&Test::B)));
    assert_ne!(TEST_A, TEST_B);
    assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 })));

    assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V)));
}
<commit_msg>discrimant test must not be inlined!<commit_after>// run-pass
#![feature(const_discriminant)]
#![allow(dead_code)]

use std::mem::{discriminant, Discriminant};

#[inline(never)]
fn identity<T>(x: T) -> T { x }

enum Test {
    A(u8),
    B,
    C { a: u8, b: u8 },
}

const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
const TEST_B: Discriminant<Test> = discriminant(&Test::B);

enum Void {}

enum SingleVariant {
    V,
    Never(Void),
}

const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);

fn main() {
    assert_eq!(TEST_A, TEST_A_OTHER);
    assert_eq!(TEST_A, discriminant(identity(&Test::A(17))));
    assert_eq!(TEST_B, discriminant(identity(&Test::B)));
    assert_ne!(TEST_A, TEST_B);
    assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 })));

    assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V)));
}
<|endoftext|>