<commit_before>//! Functions for string case manipulation, such as detecting the identifier case,
//! and converting it into appropriate form.

#[derive(Debug)]
enum DetectedCase {
    LowerCamelCase,
    UpperCamelCase,
    LowerSnakeCase,
    UpperSnakeCase,
    Unknown,
}

fn detect_case(ident: &str) -> DetectedCase {
    let trimmed_ident = ident.trim_matches('_');
    let first_lowercase =
        trimmed_ident.starts_with(|chr| chr.is_ascii_lowercase());
    let mut has_lowercase = first_lowercase;
    let mut has_uppercase = false;
    let mut has_underscore = false;

    for chr in trimmed_ident.chars() {
        if chr == '_' {
            has_underscore = true;
        } else if chr.is_ascii_uppercase() {
            has_uppercase = true;
        } else if chr.is_ascii_lowercase() {
            has_lowercase = true;
        }
    }

    if has_uppercase {
        if !has_lowercase {
            DetectedCase::UpperSnakeCase
        } else if !has_underscore {
            if first_lowercase {
                DetectedCase::LowerCamelCase
            } else {
                DetectedCase::UpperCamelCase
            }
        } else {
            // It has uppercase, it has lowercase, it has underscore.
            // No assumptions here
            DetectedCase::Unknown
        }
    } else {
        DetectedCase::LowerSnakeCase
    }
}

/// Converts an identifier to an UpperCamelCase form.
/// Returns `None` if the string is already is UpperCamelCase.
pub fn to_camel_case(ident: &str) -> Option<String> {
    let detected_case = detect_case(ident);

    match detected_case {
        DetectedCase::UpperCamelCase => return None,
        DetectedCase::LowerCamelCase => {
            let mut first_capitalized = false;
            let output = ident
                .chars()
                .map(|chr| {
                    if !first_capitalized && chr.is_ascii_lowercase() {
                        first_capitalized = true;
                        chr.to_ascii_uppercase()
                    } else {
                        chr
                    }
                })
                .collect();
            return Some(output);
        }
        _ => {}
    }

    let mut output = String::with_capacity(ident.len());

    let mut capital_added = false;
    for chr in ident.chars() {
        if chr.is_alphabetic() {
            if !capital_added {
                output.push(chr.to_ascii_uppercase());
                capital_added = true;
            } else {
                output.push(chr.to_ascii_lowercase());
            }
        } else if chr == '_' {
            // Skip this character and make the next one capital.
            capital_added = false;
        } else {
            // Put the characted as-is.
            output.push(chr);
        }
    }

    if output == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
        None
    } else {
        Some(output)
    }
}

/// Converts an identifier to a lower_snake_case form.
/// Returns `None` if the string is already in lower_snake_case.
pub fn to_lower_snake_case(ident: &str) -> Option<String> {
    // First, assume that it's UPPER_SNAKE_CASE.
    match detect_case(ident) {
        DetectedCase::LowerSnakeCase => return None,
        DetectedCase::UpperSnakeCase => {
            return Some(ident.chars().map(|chr| chr.to_ascii_lowercase()).collect())
        }
        _ => {}
    }

    // Otherwise, assume that it's CamelCase.
    let lower_snake_case = stdx::to_lower_snake_case(ident);

    if lower_snake_case == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `a` is both valid camelCase and snake_case.
        None
    } else {
        Some(lower_snake_case)
    }
}

/// Converts an identifier to an UPPER_SNAKE_CASE form.
/// Returns `None` if the string is already is UPPER_SNAKE_CASE.
pub fn to_upper_snake_case(ident: &str) -> Option<String> {
    match detect_case(ident) {
        DetectedCase::UpperSnakeCase => return None,
        DetectedCase::LowerSnakeCase => {
            return Some(ident.chars().map(|chr| chr.to_ascii_uppercase()).collect())
        }
        _ => {}
    }

    // Normalize the string from whatever form it's in currently, and then just make it uppercase.
    let upper_snake_case =
        stdx::to_lower_snake_case(ident).chars().map(|c| c.to_ascii_uppercase()).collect();

    if upper_snake_case == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
        None
    } else {
        Some(upper_snake_case)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expect_test::{expect, Expect};

    fn check<F: Fn(&str) -> Option<String>>(fun: F, input: &str, expect: Expect) {
        // `None` is translated to empty string, meaning that there is nothing to fix.
        let output = fun(input).unwrap_or_default();

        expect.assert_eq(&output);
    }

    #[test]
    fn test_to_lower_snake_case() {
        check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
        check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
        check(to_lower_snake_case, "Weird_Case", expect![["weird_case"]]);
        check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]);
        check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
        check(to_lower_snake_case, "a", expect![[""]]);
    }

    #[test]
    fn test_to_camel_case() {
        check(to_camel_case, "CamelCase", expect![[""]]);
        check(to_camel_case, "CamelCase_", expect![[""]]);
        check(to_camel_case, "_CamelCase", expect![[""]]);
        check(to_camel_case, "lowerCamelCase", expect![["LowerCamelCase"]]);
        check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
        check(to_camel_case, "UPPER_SNAKE_CASE", expect![["UpperSnakeCase"]]);
        check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]);
        check(to_camel_case, "name", expect![["Name"]]);
        check(to_camel_case, "A", expect![[""]]);
    }

    #[test]
    fn test_to_upper_snake_case() {
        check(to_upper_snake_case, "UPPER_SNAKE_CASE", expect![[""]]);
        check(to_upper_snake_case, "lower_snake_case", expect![["LOWER_SNAKE_CASE"]]);
        check(to_upper_snake_case, "Weird_Case", expect![["WEIRD_CASE"]]);
        check(to_upper_snake_case, "CamelCase", expect![["CAMEL_CASE"]]);
        check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
        check(to_upper_snake_case, "A", expect![[""]]);
    }
}
<commit_msg>Fix compilation error<commit_after>//! Functions for string case manipulation, such as detecting the identifier case,
//! and converting it into appropriate form.

#[derive(Debug)]
enum DetectedCase {
    LowerCamelCase,
    UpperCamelCase,
    LowerSnakeCase,
    UpperSnakeCase,
    Unknown,
}

fn detect_case(ident: &str) -> DetectedCase {
    let trimmed_ident = ident.trim_matches('_');
    let first_lowercase = trimmed_ident.starts_with(|chr: char| chr.is_ascii_lowercase());
    let mut has_lowercase = first_lowercase;
    let mut has_uppercase = false;
    let mut has_underscore = false;

    for chr in trimmed_ident.chars() {
        if chr == '_' {
            has_underscore = true;
        } else if chr.is_ascii_uppercase() {
            has_uppercase = true;
        } else if chr.is_ascii_lowercase() {
            has_lowercase = true;
        }
    }

    if has_uppercase {
        if !has_lowercase {
            DetectedCase::UpperSnakeCase
        } else if !has_underscore {
            if first_lowercase {
                DetectedCase::LowerCamelCase
            } else {
                DetectedCase::UpperCamelCase
            }
        } else {
            // It has uppercase, it has lowercase, it has underscore.
            // No assumptions here
            DetectedCase::Unknown
        }
    } else {
        DetectedCase::LowerSnakeCase
    }
}

/// Converts an identifier to an UpperCamelCase form.
/// Returns `None` if the string is already is UpperCamelCase.
pub fn to_camel_case(ident: &str) -> Option<String> {
    let detected_case = detect_case(ident);

    match detected_case {
        DetectedCase::UpperCamelCase => return None,
        DetectedCase::LowerCamelCase => {
            let mut first_capitalized = false;
            let output = ident
                .chars()
                .map(|chr| {
                    if !first_capitalized && chr.is_ascii_lowercase() {
                        first_capitalized = true;
                        chr.to_ascii_uppercase()
                    } else {
                        chr
                    }
                })
                .collect();
            return Some(output);
        }
        _ => {}
    }

    let mut output = String::with_capacity(ident.len());

    let mut capital_added = false;
    for chr in ident.chars() {
        if chr.is_alphabetic() {
            if !capital_added {
                output.push(chr.to_ascii_uppercase());
                capital_added = true;
            } else {
                output.push(chr.to_ascii_lowercase());
            }
        } else if chr == '_' {
            // Skip this character and make the next one capital.
            capital_added = false;
        } else {
            // Put the characted as-is.
            output.push(chr);
        }
    }

    if output == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
        None
    } else {
        Some(output)
    }
}

/// Converts an identifier to a lower_snake_case form.
/// Returns `None` if the string is already in lower_snake_case.
pub fn to_lower_snake_case(ident: &str) -> Option<String> {
    // First, assume that it's UPPER_SNAKE_CASE.
    match detect_case(ident) {
        DetectedCase::LowerSnakeCase => return None,
        DetectedCase::UpperSnakeCase => {
            return Some(ident.chars().map(|chr| chr.to_ascii_lowercase()).collect())
        }
        _ => {}
    }

    // Otherwise, assume that it's CamelCase.
    let lower_snake_case = stdx::to_lower_snake_case(ident);

    if lower_snake_case == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `a` is both valid camelCase and snake_case.
        None
    } else {
        Some(lower_snake_case)
    }
}

/// Converts an identifier to an UPPER_SNAKE_CASE form.
/// Returns `None` if the string is already is UPPER_SNAKE_CASE.
pub fn to_upper_snake_case(ident: &str) -> Option<String> {
    match detect_case(ident) {
        DetectedCase::UpperSnakeCase => return None,
        DetectedCase::LowerSnakeCase => {
            return Some(ident.chars().map(|chr| chr.to_ascii_uppercase()).collect())
        }
        _ => {}
    }

    // Normalize the string from whatever form it's in currently, and then just make it uppercase.
    let upper_snake_case =
        stdx::to_lower_snake_case(ident).chars().map(|c| c.to_ascii_uppercase()).collect();

    if upper_snake_case == ident {
        // While we didn't detect the correct case at the beginning, there
        // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
        None
    } else {
        Some(upper_snake_case)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expect_test::{expect, Expect};

    fn check<F: Fn(&str) -> Option<String>>(fun: F, input: &str, expect: Expect) {
        // `None` is translated to empty string, meaning that there is nothing to fix.
        let output = fun(input).unwrap_or_default();

        expect.assert_eq(&output);
    }

    #[test]
    fn test_to_lower_snake_case() {
        check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
        check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
        check(to_lower_snake_case, "Weird_Case", expect![["weird_case"]]);
        check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]);
        check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
        check(to_lower_snake_case, "a", expect![[""]]);
    }

    #[test]
    fn test_to_camel_case() {
        check(to_camel_case, "CamelCase", expect![[""]]);
        check(to_camel_case, "CamelCase_", expect![[""]]);
        check(to_camel_case, "_CamelCase", expect![[""]]);
        check(to_camel_case, "lowerCamelCase", expect![["LowerCamelCase"]]);
        check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
        check(to_camel_case, "UPPER_SNAKE_CASE", expect![["UpperSnakeCase"]]);
        check(to_camel_case, "Weird_Case", expect![["WeirdCase"]]);
        check(to_camel_case, "name", expect![["Name"]]);
        check(to_camel_case, "A", expect![[""]]);
    }

    #[test]
    fn test_to_upper_snake_case() {
        check(to_upper_snake_case, "UPPER_SNAKE_CASE", expect![[""]]);
        check(to_upper_snake_case, "lower_snake_case", expect![["LOWER_SNAKE_CASE"]]);
        check(to_upper_snake_case, "Weird_Case", expect![["WEIRD_CASE"]]);
        check(to_upper_snake_case, "CamelCase", expect![["CAMEL_CASE"]]);
        check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
        check(to_upper_snake_case, "A", expect![[""]]);
    }
}
<|endoftext|>


<commit_before>#![no_main]

use rust_decimal::{Decimal, MathematicalOps};

#[derive(Debug, arbitrary::Arbitrary)]
struct Data {
    a: Decimal,
    b: Decimal,
    exp_f64: f64,
    exp_i64: i64,
    exp_u64: u64,
}

libfuzzer_sys::fuzz_target!(|data: Data| {
    let _ = data.a.checked_add(data.b);
    let _ = data.a.checked_div(data.b);
    let _ = data.a.checked_exp_with_tolerance(data.b);
    let _ = data.a.checked_exp();
    let _ = data.a.checked_mul(data.b);
    let _ = data.a.checked_norm_pdf();
    let _ = data.a.checked_powd(data.b);
    let _ = data.a.checked_powf(data.exp_f64);
    let _ = data.a.checked_powi(data.exp_i64);
    let _ = data.a.checked_powu(data.exp_u64);
    let _ = data.a.checked_sub(data.b);
});
<commit_msg>Add more fuzz tests<commit_after>#![no_main]

use rust_decimal::{Decimal, MathematicalOps};

#[derive(Debug, arbitrary::Arbitrary)]
struct Data {
    a: Decimal,
    b: Decimal,
    exp_f64: f64,
    exp_i64: i64,
    exp_u64: u64,
}

libfuzzer_sys::fuzz_target!(|data: Data| {
    let _ = data.a.checked_add(data.b);
    let _ = data.a.checked_cos();
    let _ = data.a.checked_div(data.b);
    let _ = data.a.checked_exp_with_tolerance(data.b);
    let _ = data.a.checked_exp();
    let _ = data.a.checked_mul(data.b);
    let _ = data.a.checked_norm_pdf();
    let _ = data.a.checked_powd(data.b);
    let _ = data.a.checked_powf(data.exp_f64);
    let _ = data.a.checked_powi(data.exp_i64);
    let _ = data.a.checked_powu(data.exp_u64);
    let _ = data.a.checked_sin();
    let _ = data.a.checked_sub(data.b);
    let _ = data.a.checked_tan();
});
<|endoftext|>


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

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

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

        impl ::std::convert::From<$id> for ::std::string::String {
            fn from(id: $id) -> Self {
                id.full_id.into()
            }
        }

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

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

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

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

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

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

        impl ::std::cmp::Eq for $id {}

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

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

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

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

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

        impl ::std::cmp::PartialEq<&str> for $id {
            fn eq(&self, other: &&str) -> bool {
                self.as_str() == *other
            }
        }

        impl ::std::cmp::PartialEq<$id> for &str {
            fn eq(&self, other: &$id) -> bool {
                *self == other.as_str()
            }
        }

        impl ::std::cmp::PartialEq<::std::string::String> for $id {
            fn eq(&self, other: &::std::string::String) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl ::std::cmp::PartialEq<$id> for ::std::string::String {
            fn eq(&self, other: &$id) -> bool {
                self.as_str() == other.as_str()
            }
        }
    };
}
<commit_msg>Fix doc_concat macro on older versions of rustc<commit_after>/// Declares an item with a doc attribute computed by some macro expression.
/// This allows documentation to be dynamically generated based on input.
/// Necessary to work around https://github.com/rust-lang/rust/issues/52607.
macro_rules! doc_concat {
    ( $( #[doc = $doc:expr] $( $thing:tt )* )* ) => ( $( #[doc = $doc] $( $thing )* )* );
}

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

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

        impl ::std::convert::From<$id> for ::std::string::String {
            fn from(id: $id) -> Self {
                id.full_id.into()
            }
        }

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

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

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

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

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

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

        impl ::std::cmp::Eq for $id {}

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

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

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

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

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

        impl ::std::cmp::PartialEq<&str> for $id {
            fn eq(&self, other: &&str) -> bool {
                self.as_str() == *other
            }
        }

        impl ::std::cmp::PartialEq<$id> for &str {
            fn eq(&self, other: &$id) -> bool {
                *self == other.as_str()
            }
        }

        impl ::std::cmp::PartialEq<::std::string::String> for $id {
            fn eq(&self, other: &::std::string::String) -> bool {
                self.as_str() == other.as_str()
            }
        }

        impl ::std::cmp::PartialEq<$id> for ::std::string::String {
            fn eq(&self, other: &$id) -> bool {
                self.as_str() == other.as_str()
            }
        }
    };
}
<|endoftext|>


<commit_before>extern crate simple_csv;
extern crate png;

use std::env;
use std::fs::File;
use std::io::{BufWriter, BufReader};
use std::str::FromStr;
use png::HasParameters;
use simple_csv::SimpleCsvReader;

fn main(){
    let f = File::open("../long-cadence.csv").unwrap();
    let buf = BufReader::new(f);
    let mut reader = SimpleCsvReader::new(buf);
    let row = reader.next_row().unwrap().unwrap();
    let mut iter = row.iter();
    iter.next(); // dropping time

    let raw: Vec<f64> = iter
        .map(|s| f64::from_str(s).unwrap())
        .collect();
    let maximum = raw
        .iter()
        .fold(std::f64::MIN, |acc, v| acc.max(*v));
    let data: Vec<u8> = raw
        .iter()
        .map(|s| s/maximum)
        .map(|s| 255.0 * s)
        .map(|s| s as u8)
        .collect();

    println!("{}: {:?}", maximum, data);

    let mut path = env::current_dir().unwrap();
    path.push("trappist-1.0.png");

    let file = File::create(path).unwrap();
    let ref mut w = BufWriter::new(file);

    let mut encoder = png::Encoder::new(w, 11, 11);
    encoder.set(png::ColorType::Grayscale).set(png::BitDepth::Eight);
    let mut writer = encoder.write_header().unwrap();

    writer.write_image_data(data.as_slice()).unwrap();
}
<commit_msg>Clean up image showcase<commit_after>extern crate simple_csv;
extern crate png;

use std::env;
use std::fs::File;
use std::io::{BufWriter, BufReader};
use std::str::FromStr;
use png::HasParameters;
use simple_csv::SimpleCsvReader;

fn main(){
    let f = File::open("../long-cadence.csv").unwrap();
    let buf = BufReader::new(f);
    let mut reader = SimpleCsvReader::new(buf);
    let row = reader.next_row().unwrap().unwrap();
    let mut iter = row.iter();
    iter.next(); // dropping time

    let raw: Vec<f64> = iter
        .map(|s| f64::from_str(s).unwrap())
        .collect();
    let maximum = raw
        .iter()
        .fold(std::f64::MIN, |acc, v| acc.max(*v));
    let data: Vec<u8> = raw
        .iter()
        .map(|s| s/maximum)
        .map(|s| 255.0 * s)
        .map(|s| s.floor() as u8)
        .collect();

    let mut path = env::current_dir().unwrap();
    path.push("trappist-1.0.png");

    let file = File::create(path).unwrap();
    let ref mut w = BufWriter::new(file);

    let mut encoder = png::Encoder::new(w, 11, 11);
    encoder.set(png::ColorType::Grayscale).set(png::BitDepth::Eight);
    let mut writer = encoder.write_header().unwrap();

    writer.write_image_data(data.as_slice()).unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All rights reserved.
//
// 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.

//! A data structure for manipulating sets of indices (typically used for
//! representing valid lines).

// Note: this data structure has nontrivial overlap with Subset in the rope
// crate. Maybe we don't need both.

use std::cmp::{min, max};

pub struct IndexSet {
    ranges: Vec<(usize, usize)>,
}

pub fn remove_n_at<T: Clone>(v: &mut Vec<T>, index: usize, n: usize) {
    if n == 1 {
        v.remove(index);
    } else if n > 1 {
        let new_len = v.len() - n;
        for i in index..new_len {
            v[i] = v[i + n].clone();
        }
        v.truncate(new_len);
    }
}

impl IndexSet {
    /// Create a new, empty set.
    pub fn new() -> IndexSet {
        IndexSet {
            ranges: Vec::new(),
        }
    }

    /// Clear the set.
    pub fn clear(&mut self) {
        self.ranges.clear();
    }

    /// Add the range start..end to the set.
    pub fn union_one_range(&mut self, start: usize, end: usize) {
        for i in 0..self.ranges.len() {
            let (istart, iend) = self.ranges[i];
            if start > iend {
                continue;
            } else if end < istart {
                self.ranges.insert(i, (start, end));
                return;
            } else {
                self.ranges[i].0 = min(start, istart);
                let mut j = i;
                while j + 1 < self.ranges.len() && end >= self.ranges[j + 1].0 {
                    j += 1;
                }
                self.ranges[i].1 = max(end, self.ranges[j].1);
                remove_n_at(&mut self.ranges, i + 1, j - i);
                return;
            }
        }
        self.ranges.push((start, end));
    }

    /// Return an iterator that yields start..end minus the coverage in this set.
    pub fn minus_one_range(&self, start: usize, end: usize) -> MinusIter {
        let mut ranges = &self.ranges[..];
        while !ranges.is_empty() && start >= ranges[0].1 {
            ranges = &ranges[1..];
        }
        MinusIter {
            ranges: &self.ranges,
            start: start,
            end: end,
        }
    }

    #[cfg(test)]
    fn get_ranges(&self) -> &[(usize, usize)] {
        &self.ranges
    }
}

/// The iterator generated by `minus_one_range`.
pub struct MinusIter<'a> {
    ranges: &'a [(usize, usize)],
    start: usize,
    end: usize,
}

impl<'a> Iterator for MinusIter<'a> {
    type Item = (usize, usize);

    fn next(&mut self) -> Option<(usize, usize)> {
        while self.start < self.end {
            if self.ranges.is_empty() || self.end <= self.ranges[0].0 {
                let result = (self.start, self.end);
                self.start = self.end;
                return Some(result);
            }
            let result = (self.start, self.ranges[0].0);
            self.start = self.ranges[0].1;
            self.ranges = &self.ranges[1..];
            if result.1 > result.0 {
                return Some(result);
            }
        }
        None
    }
}

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

    #[test]
    fn empty_behavior() {
        let e = IndexSet::new();
        assert_eq!(e.minus_one_range(0, 0).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(3, 5).collect::<Vec<_>>(), vec![(3, 5)]);
    }

    #[test]
    fn single_range_behavior() {
        let mut e = IndexSet::new();
        e.union_one_range(3, 5);
        assert_eq!(e.minus_one_range(0, 0).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(3, 5).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(0, 3).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(0, 4).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(4, 10).collect::<Vec<_>>(), vec![(5, 10)]);
        assert_eq!(e.minus_one_range(5, 10).collect::<Vec<_>>(), vec![(5, 10)]);
        assert_eq!(e.minus_one_range(0, 10).collect::<Vec<_>>(), vec![(0, 3), (5, 10)]);
    }

    #[test]
    fn unions() {
        let mut e = IndexSet::new();
        e.union_one_range(3, 5);
        assert_eq!(e.get_ranges(), &[(3, 5)]);
        e.union_one_range(7, 9);
        assert_eq!(e.get_ranges(), &[(3, 5), (7, 9)]);
        e.union_one_range(1, 2);
        assert_eq!(e.get_ranges(), &[(1, 2), (3, 5), (7, 9)]);
        e.union_one_range(2, 3);
        assert_eq!(e.get_ranges(), &[(1, 5), (7, 9)]);
        e.union_one_range(4, 6);
        assert_eq!(e.get_ranges(), &[(1, 6), (7, 9)]);
        assert_eq!(e.minus_one_range(0, 10).collect::<Vec<_>>(), vec![(0, 1), (6, 7), (9, 10)]);

        e.clear();
        assert_eq!(e.get_ranges(), &[]);
        e.union_one_range(3, 4);
        assert_eq!(e.get_ranges(), &[(3, 4)]);
        e.union_one_range(5, 6);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6)]);
        e.union_one_range(7, 8);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8)]);
        e.union_one_range(9, 10);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8), (9, 10)]);
        e.union_one_range(11, 12);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8), (9, 10), (11, 12)]);
        e.union_one_range(2, 10);
        assert_eq!(e.get_ranges(), &[(2, 10), (11, 12)]);
    }
}
<commit_msg>Fix overly inclusive IndexSet::minus_one_range<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// 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.

//! A data structure for manipulating sets of indices (typically used for
//! representing valid lines).

// Note: this data structure has nontrivial overlap with Subset in the rope
// crate. Maybe we don't need both.

use std::cmp::{min, max};

pub struct IndexSet {
    ranges: Vec<(usize, usize)>,
}

pub fn remove_n_at<T: Clone>(v: &mut Vec<T>, index: usize, n: usize) {
    if n == 1 {
        v.remove(index);
    } else if n > 1 {
        let new_len = v.len() - n;
        for i in index..new_len {
            v[i] = v[i + n].clone();
        }
        v.truncate(new_len);
    }
}

impl IndexSet {
    /// Create a new, empty set.
    pub fn new() -> IndexSet {
        IndexSet {
            ranges: Vec::new(),
        }
    }

    /// Clear the set.
    pub fn clear(&mut self) {
        self.ranges.clear();
    }

    /// Add the range start..end to the set.
    pub fn union_one_range(&mut self, start: usize, end: usize) {
        for i in 0..self.ranges.len() {
            let (istart, iend) = self.ranges[i];
            if start > iend {
                continue;
            } else if end < istart {
                self.ranges.insert(i, (start, end));
                return;
            } else {
                self.ranges[i].0 = min(start, istart);
                let mut j = i;
                while j + 1 < self.ranges.len() && end >= self.ranges[j + 1].0 {
                    j += 1;
                }
                self.ranges[i].1 = max(end, self.ranges[j].1);
                remove_n_at(&mut self.ranges, i + 1, j - i);
                return;
            }
        }
        self.ranges.push((start, end));
    }

    /// Return an iterator that yields start..end minus the coverage in this set.
    pub fn minus_one_range(&self, start: usize, end: usize) -> MinusIter {
        let mut ranges = &self.ranges[..];
        while !ranges.is_empty() && start >= ranges[0].1 {
            ranges = &ranges[1..];
        }
        MinusIter {
            ranges: ranges,
            start: start,
            end: end,
        }
    }

    #[cfg(test)]
    fn get_ranges(&self) -> &[(usize, usize)] {
        &self.ranges
    }
}

/// The iterator generated by `minus_one_range`.
pub struct MinusIter<'a> {
    ranges: &'a [(usize, usize)],
    start: usize,
    end: usize,
}

impl<'a> Iterator for MinusIter<'a> {
    type Item = (usize, usize);

    fn next(&mut self) -> Option<(usize, usize)> {
        while self.start < self.end {
            if self.ranges.is_empty() || self.end <= self.ranges[0].0 {
                let result = (self.start, self.end);
                self.start = self.end;
                return Some(result);
            }
            let result = (self.start, self.ranges[0].0);
            self.start = self.ranges[0].1;
            self.ranges = &self.ranges[1..];
            if result.1 > result.0 {
                return Some(result);
            }
        }
        None
    }
}

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

    #[test]
    fn empty_behavior() {
        let e = IndexSet::new();
        assert_eq!(e.minus_one_range(0, 0).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(3, 5).collect::<Vec<_>>(), vec![(3, 5)]);
    }

    #[test]
    fn single_range_behavior() {
        let mut e = IndexSet::new();
        e.union_one_range(3, 5);
        assert_eq!(e.minus_one_range(0, 0).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(3, 5).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(0, 3).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(0, 4).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(4, 10).collect::<Vec<_>>(), vec![(5, 10)]);
        assert_eq!(e.minus_one_range(5, 10).collect::<Vec<_>>(), vec![(5, 10)]);
        assert_eq!(e.minus_one_range(0, 10).collect::<Vec<_>>(), vec![(0, 3), (5, 10)]);
    }

    #[test]
    fn two_range_minus() {
        let mut e = IndexSet::new();
        e.union_one_range(3, 5);
        e.union_one_range(7, 9);
        assert_eq!(e.minus_one_range(0, 0).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(3, 5).collect::<Vec<_>>(), vec![]);
        assert_eq!(e.minus_one_range(0, 3).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(0, 4).collect::<Vec<_>>(), vec![(0, 3)]);
        assert_eq!(e.minus_one_range(4, 10).collect::<Vec<_>>(), vec![(5, 7), (9, 10)]);
        assert_eq!(e.minus_one_range(5, 10).collect::<Vec<_>>(), vec![(5, 7), (9, 10)]);
        assert_eq!(e.minus_one_range(8, 10).collect::<Vec<_>>(), vec![(9, 10)]);
        assert_eq!(e.minus_one_range(0, 10).collect::<Vec<_>>(), vec![(0, 3), (5, 7), (9, 10)]);
    }

    #[test]
    fn unions() {
        let mut e = IndexSet::new();
        e.union_one_range(3, 5);
        assert_eq!(e.get_ranges(), &[(3, 5)]);
        e.union_one_range(7, 9);
        assert_eq!(e.get_ranges(), &[(3, 5), (7, 9)]);
        e.union_one_range(1, 2);
        assert_eq!(e.get_ranges(), &[(1, 2), (3, 5), (7, 9)]);
        e.union_one_range(2, 3);
        assert_eq!(e.get_ranges(), &[(1, 5), (7, 9)]);
        e.union_one_range(4, 6);
        assert_eq!(e.get_ranges(), &[(1, 6), (7, 9)]);
        assert_eq!(e.minus_one_range(0, 10).collect::<Vec<_>>(), vec![(0, 1), (6, 7), (9, 10)]);

        e.clear();
        assert_eq!(e.get_ranges(), &[]);
        e.union_one_range(3, 4);
        assert_eq!(e.get_ranges(), &[(3, 4)]);
        e.union_one_range(5, 6);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6)]);
        e.union_one_range(7, 8);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8)]);
        e.union_one_range(9, 10);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8), (9, 10)]);
        e.union_one_range(11, 12);
        assert_eq!(e.get_ranges(), &[(3, 4), (5, 6), (7, 8), (9, 10), (11, 12)]);
        e.union_one_range(2, 10);
        assert_eq!(e.get_ranges(), &[(2, 10), (11, 12)]);
    }
}
<|endoftext|>


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

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="flex-flow" sub_properties="flex-direction flex-wrap" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
    use properties::longhands::{flex_direction, flex_wrap};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut direction = None;
        let mut wrap = None;
        loop {
            if direction.is_none() {
                if let Ok(value) = input.try(|input| flex_direction::parse(context, input)) {
                    direction = Some(value);
                    continue
                }
            }
            if wrap.is_none() {
                if let Ok(value) = input.try(|input| flex_wrap::parse(context, input)) {
                    wrap = Some(value);
                    continue
                }
            }
            break
        }

        if direction.is_none() && wrap.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_direction: unwrap_or_initial!(flex_direction, direction),
            flex_wrap: unwrap_or_initial!(flex_wrap, wrap),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.flex_direction.to_css(dest)?;
            dest.write_str(" ")?;
            self.flex_wrap.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="flex" sub_properties="flex-grow flex-shrink flex-basis" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-property">
    use parser::Parse;
    use values::specified::{Number, NoCalcLength};
    % if product == "gecko":
        use values::specified::LengthOrPercentageOrAuto;
    % else:
        use values::specified::LengthOrPercentageOrAutoOrContent;
    % endif

    pub fn parse_flexibility(input: &mut Parser)
                             -> Result<(Number, Option<Number>),()> {
        let grow = try!(Number::parse_non_negative(input));
        let shrink = input.try(Number::parse_non_negative).ok();
        Ok((grow, shrink))
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut grow = None;
        let mut shrink = None;
        let mut basis = None;

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                flex_grow: Number(0.0),
                flex_shrink: Number(0.0),
                % if product == "gecko":
                    flex_basis: LengthOrPercentageOrAuto::Auto
                % else:
                    flex_basis: LengthOrPercentageOrAutoOrContent::Auto
                % endif

            })
        }
        loop {
            if grow.is_none() {
                if let Ok((flex_grow, flex_shrink)) = input.try(parse_flexibility) {
                    grow = Some(flex_grow);
                    shrink = flex_shrink;
                    continue
                }
            }
            if basis.is_none() {
                % if product == "gecko":
                    if let Ok(value) = input.try(|i| LengthOrPercentageOrAuto::parse(context, i)) {
                % else:
                    if let Ok(value) = input.try(|i| LengthOrPercentageOrAutoOrContent::parse(context, i)) {
                % endif
                    basis = Some(value);
                    continue
                }
            }
            break
        }

        if grow.is_none() && basis.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_grow: grow.unwrap_or(Number(1.0)),
            flex_shrink: shrink.unwrap_or(Number(1.0)),
            % if product == "gecko":
                flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero()))
            % else:
                flex_basis: basis.unwrap_or(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero()))
            % endif
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.flex_grow.to_css(dest));
            try!(write!(dest, " "));

            try!(self.flex_shrink.to_css(dest));
            try!(write!(dest, " "));

            self.flex_basis.to_css(dest)
        }
    }
</%helpers:shorthand>
<commit_msg>Stylo: Add grid-gap shorthand<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="flex-flow" sub_properties="flex-direction flex-wrap" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
    use properties::longhands::{flex_direction, flex_wrap};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut direction = None;
        let mut wrap = None;
        loop {
            if direction.is_none() {
                if let Ok(value) = input.try(|input| flex_direction::parse(context, input)) {
                    direction = Some(value);
                    continue
                }
            }
            if wrap.is_none() {
                if let Ok(value) = input.try(|input| flex_wrap::parse(context, input)) {
                    wrap = Some(value);
                    continue
                }
            }
            break
        }

        if direction.is_none() && wrap.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_direction: unwrap_or_initial!(flex_direction, direction),
            flex_wrap: unwrap_or_initial!(flex_wrap, wrap),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.flex_direction.to_css(dest)?;
            dest.write_str(" ")?;
            self.flex_wrap.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="flex" sub_properties="flex-grow flex-shrink flex-basis" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-property">
    use parser::Parse;
    use values::specified::{Number, NoCalcLength};
    % if product == "gecko":
        use values::specified::LengthOrPercentageOrAuto;
    % else:
        use values::specified::LengthOrPercentageOrAutoOrContent;
    % endif

    pub fn parse_flexibility(input: &mut Parser)
                             -> Result<(Number, Option<Number>),()> {
        let grow = try!(Number::parse_non_negative(input));
        let shrink = input.try(Number::parse_non_negative).ok();
        Ok((grow, shrink))
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut grow = None;
        let mut shrink = None;
        let mut basis = None;

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                flex_grow: Number(0.0),
                flex_shrink: Number(0.0),
                % if product == "gecko":
                    flex_basis: LengthOrPercentageOrAuto::Auto
                % else:
                    flex_basis: LengthOrPercentageOrAutoOrContent::Auto
                % endif

            })
        }
        loop {
            if grow.is_none() {
                if let Ok((flex_grow, flex_shrink)) = input.try(parse_flexibility) {
                    grow = Some(flex_grow);
                    shrink = flex_shrink;
                    continue
                }
            }
            if basis.is_none() {
                % if product == "gecko":
                    if let Ok(value) = input.try(|i| LengthOrPercentageOrAuto::parse(context, i)) {
                % else:
                    if let Ok(value) = input.try(|i| LengthOrPercentageOrAutoOrContent::parse(context, i)) {
                % endif
                    basis = Some(value);
                    continue
                }
            }
            break
        }

        if grow.is_none() && basis.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_grow: grow.unwrap_or(Number(1.0)),
            flex_shrink: shrink.unwrap_or(Number(1.0)),
            % if product == "gecko":
                flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero()))
            % else:
                flex_basis: basis.unwrap_or(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero()))
            % endif
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.flex_grow.to_css(dest));
            try!(write!(dest, " "));

            try!(self.flex_shrink.to_css(dest));
            try!(write!(dest, " "));

            self.flex_basis.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="grid-gap" sub_properties="grid-row-gap grid-column-gap"
                    spec="https://drafts.csswg.org/css-grid/#propdef-grid-gap"
                    products="gecko">
  use properties::longhands::{grid_row_gap, grid_column_gap};

  pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
      let row_gap = grid_row_gap::parse(context, input)?;
      let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());

      Ok(Longhands {
        grid_row_gap: row_gap,
        grid_column_gap: column_gap,
      })
  }

  impl<'a> ToCss for LonghandsToSerialize<'a>  {
      fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
          if self.grid_row_gap == self.grid_column_gap {
            self.grid_row_gap.to_css(dest)
          } else {
            self.grid_row_gap.to_css(dest)?;
            dest.write_str(" ")?;
            self.grid_column_gap.to_css(dest)
          }
      }
  }

</%helpers:shorthand>
<|endoftext|>


<commit_before>//! `pagecache` is a lock-free pagecache and log for building high-performance
//! databases.

pub mod constants;
pub mod logger;

mod blob_io;
mod diskptr;
mod iobuf;
mod iterator;
mod materializer;
mod pagecache;
mod parallel_io;
mod reader;
mod reservation;
mod segment;
mod snapshot;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

use crate::{debug, AtomicLsn, DeserializeOwned, SeqCst, Serialize};

use self::{
    blob_io::{gc_blobs, read_blob, remove_blob, write_blob},
    constants::{
        BATCH_MANIFEST_PID, CONFIG_PID, COUNTER_PID, META_PID,
        PAGE_CONSOLIDATION_THRESHOLD,
    },
    iobuf::{IoBuf, IoBufs},
    iterator::{raw_segment_iter_from, LogIter},
    pagecache::Update,
    parallel_io::Pio,
    segment::SegmentAccountant,
    snapshot::advance_snapshot,
};

pub(crate) use self::{
    logger::{MessageHeader, SegmentHeader},
    reader::{read_message, read_segment_header},
    reservation::Reservation,
    snapshot::{read_snapshot_or_default, PageState, Snapshot},
};

pub use self::{
    constants::{
        BATCH_MANIFEST_INLINE_LEN, BLOB_INLINE_LEN, MAX_SPACE_AMPLIFICATION,
        MINIMUM_ITEMS_PER_SEGMENT, MSG_HEADER_LEN, SEG_HEADER_LEN,
    },
    diskptr::DiskPtr,
    logger::{Log, LogRead},
    materializer::Materializer,
    pagecache::{PageCache, PagePtr, RecoveryGuard},
    segment::SegmentMode,
};

/// The offset of a segment. This equals its LogOffset (or the offset of any
/// item contained inside it) divided by the configured segment_size.
pub type SegmentId = usize;

/// A file offset in the database log.
pub type LogOffset = u64;

/// A pointer to an blob blob.
pub type BlobPointer = Lsn;

/// A logical sequence number of a log entry.
/// A segment lsn equals to an aligned LogOffset that is
/// Segment.LogOffset & ~SegmentSize.
pub type Lsn = i64;

/// A page identifier.
pub type PageId = u64;

/// A byte used to disambiguate log message types
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum MessageKind {
    /// The EVIL_BYTE is written as a canary to help
    /// detect torn writes.
    Corrupted = 0,
    /// Indicates that the following buffer corresponds
    /// to a reservation for an in-memory operation that
    /// failed to complete. It should be skipped during
    /// recovery.
    Cancelled = 1,
    /// Indicates that the following buffer is used
    /// as padding to fill out the rest of the segment
    /// before sealing it.
    Pad = 2,
    /// Indicates that the following buffer contains
    /// an Lsn for the last write in an atomic writebatch.
    BatchManifest = 3,
    /// Indicates that this page was freed from the pagetable.
    Free = 4,
    /// Indicates that the last persisted ID was at least
    /// this high.
    Counter = 5,
    /// The meta page, stored inline
    InlineMeta = 6,
    /// The meta page, stored blobly
    BlobMeta = 7,
    /// The config page, stored inline
    InlineConfig = 8,
    /// The config page, stored blobly
    BlobConfig = 9,
    /// A consolidated page replacement, stored inline
    InlineReplace = 10,
    /// A consolidated page replacement, stored blobly
    BlobReplace = 11,
    /// A partial page update, stored inline
    InlineAppend = 12,
    /// A partial page update, stored blobly
    BlobAppend = 13,
}

impl MessageKind {
    pub(crate) const fn into(self) -> u8 {
        self as u8
    }
}

impl From<u8> for MessageKind {
    fn from(byte: u8) -> Self {
        use MessageKind::*;
        match byte {
            0 => Corrupted,
            1 => Cancelled,
            2 => Pad,
            3 => BatchManifest,
            4 => Free,
            5 => Counter,
            6 => InlineMeta,
            7 => BlobMeta,
            8 => InlineConfig,
            9 => BlobConfig,
            10 => InlineReplace,
            11 => BlobReplace,
            12 => InlineAppend,
            13 => BlobAppend,
            other => {
                debug!("encountered unexpected message kind byte {}", other);
                Corrupted
            }
        }
    }
}

/// The high-level types of stored information
/// about pages and their mutations
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LogKind {
    /// Persisted data containing a page replacement
    Replace,
    /// Persisted immutable update
    Append,
    /// Freeing of a page
    Free,
    /// Some state indicating this should be skipped
    Skip,
    /// Unexpected corruption
    Corrupted,
}

fn log_kind_from_update<PageFrag>(update: &Update<PageFrag>) -> LogKind
where
    PageFrag: DeserializeOwned + Serialize,
{
    use Update::*;

    match update {
        Free => LogKind::Free,
        Append(..) => LogKind::Append,
        Compact(..) | Counter(..) | Meta(..) | Config(..) => LogKind::Replace,
    }
}

impl From<MessageKind> for LogKind {
    fn from(kind: MessageKind) -> Self {
        use MessageKind::*;
        match kind {
            Free => LogKind::Free,

            InlineReplace | Counter | BlobReplace | InlineMeta | BlobMeta
            | InlineConfig | BlobConfig => LogKind::Replace,

            InlineAppend | BlobAppend => LogKind::Append,

            Cancelled | Pad | BatchManifest => LogKind::Skip,
            other => {
                debug!("encountered unexpected message kind byte {:?}", other);
                LogKind::Corrupted
            }
        }
    }
}

fn assert_usize<T>(from: T) -> usize
where
    usize: TryFrom<T, Error = std::num::TryFromIntError>,
{
    usize::try_from(from).expect("lost data cast while converting to usize")
}

// TODO remove this when atomic fetch_max stabilizes in #48655
fn bump_atomic_lsn(atomic_lsn: &AtomicLsn, to: Lsn) {
    let mut current = atomic_lsn.load(SeqCst);
    loop {
        if current >= to {
            return;
        }
        let last = atomic_lsn.compare_and_swap(current, to, SeqCst);
        if last == current {
            // we succeeded.
            return;
        }
        current = last;
    }
}

use std::convert::{TryFrom, TryInto};

#[cfg(feature = "compression")]
use zstd::block::decompress;

#[inline]
pub(crate) fn u64_to_arr(number: u64) -> [u8; 8] {
    number.to_le_bytes()
}

#[inline]
pub(crate) fn arr_to_u64(arr: &[u8]) -> u64 {
    arr.try_into().map(u64::from_le_bytes).unwrap()
}

#[inline]
pub(crate) fn arr_to_u32(arr: &[u8]) -> u32 {
    arr.try_into().map(u32::from_le_bytes).unwrap()
}

#[inline]
pub(crate) fn u32_to_arr(number: u32) -> [u8; 4] {
    number.to_le_bytes()
}

pub(crate) fn maybe_decompress(buf: Vec<u8>) -> std::io::Result<Vec<u8>> {
    #[cfg(feature = "compression")]
    {
        use std::sync::atomic::AtomicUsize;

        use super::*;

        static MAX_COMPRESSION_RATIO: AtomicUsize = AtomicUsize::new(1);
        use std::sync::atomic::Ordering::{Acquire, Release};

        let _measure = Measure::new(&M.decompress);
        loop {
            let ratio = MAX_COMPRESSION_RATIO.load(Acquire);
            match decompress(&*buf, buf.len() * ratio) {
                Err(ref e) if e.kind() == std::io::ErrorKind::Other => {
                    debug!(
                        "bumping expected compression \
                         ratio up from {} to {}: {:?}",
                        ratio,
                        ratio + 1,
                        e
                    );
                    let _who_cares = MAX_COMPRESSION_RATIO.compare_and_swap(
                        ratio,
                        ratio + 1,
                        Release,
                    );
                }
                other => return other,
            }
        }
    }

    #[cfg(not(feature = "compression"))]
    Ok(buf)
}
<commit_msg>fix lsn doc<commit_after>//! `pagecache` is a lock-free pagecache and log for building high-performance
//! databases.

pub mod constants;
pub mod logger;

mod blob_io;
mod diskptr;
mod iobuf;
mod iterator;
mod materializer;
mod pagecache;
mod parallel_io;
mod reader;
mod reservation;
mod segment;
mod snapshot;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

use crate::{debug, AtomicLsn, DeserializeOwned, SeqCst, Serialize};

use self::{
    blob_io::{gc_blobs, read_blob, remove_blob, write_blob},
    constants::{
        BATCH_MANIFEST_PID, CONFIG_PID, COUNTER_PID, META_PID,
        PAGE_CONSOLIDATION_THRESHOLD,
    },
    iobuf::{IoBuf, IoBufs},
    iterator::{raw_segment_iter_from, LogIter},
    pagecache::Update,
    parallel_io::Pio,
    segment::SegmentAccountant,
    snapshot::advance_snapshot,
};

pub(crate) use self::{
    logger::{MessageHeader, SegmentHeader},
    reader::{read_message, read_segment_header},
    reservation::Reservation,
    snapshot::{read_snapshot_or_default, PageState, Snapshot},
};

pub use self::{
    constants::{
        BATCH_MANIFEST_INLINE_LEN, BLOB_INLINE_LEN, MAX_SPACE_AMPLIFICATION,
        MINIMUM_ITEMS_PER_SEGMENT, MSG_HEADER_LEN, SEG_HEADER_LEN,
    },
    diskptr::DiskPtr,
    logger::{Log, LogRead},
    materializer::Materializer,
    pagecache::{PageCache, PagePtr, RecoveryGuard},
    segment::SegmentMode,
};

/// The offset of a segment. This equals its LogOffset (or the offset of any
/// item contained inside it) divided by the configured segment_size.
pub type SegmentId = usize;

/// A file offset in the database log.
pub type LogOffset = u64;

/// A pointer to an blob blob.
pub type BlobPointer = Lsn;

/// The logical sequence number of an item in the database log.
pub type Lsn = i64;

/// A page identifier.
pub type PageId = u64;

/// A byte used to disambiguate log message types
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum MessageKind {
    /// The EVIL_BYTE is written as a canary to help
    /// detect torn writes.
    Corrupted = 0,
    /// Indicates that the following buffer corresponds
    /// to a reservation for an in-memory operation that
    /// failed to complete. It should be skipped during
    /// recovery.
    Cancelled = 1,
    /// Indicates that the following buffer is used
    /// as padding to fill out the rest of the segment
    /// before sealing it.
    Pad = 2,
    /// Indicates that the following buffer contains
    /// an Lsn for the last write in an atomic writebatch.
    BatchManifest = 3,
    /// Indicates that this page was freed from the pagetable.
    Free = 4,
    /// Indicates that the last persisted ID was at least
    /// this high.
    Counter = 5,
    /// The meta page, stored inline
    InlineMeta = 6,
    /// The meta page, stored blobly
    BlobMeta = 7,
    /// The config page, stored inline
    InlineConfig = 8,
    /// The config page, stored blobly
    BlobConfig = 9,
    /// A consolidated page replacement, stored inline
    InlineReplace = 10,
    /// A consolidated page replacement, stored blobly
    BlobReplace = 11,
    /// A partial page update, stored inline
    InlineAppend = 12,
    /// A partial page update, stored blobly
    BlobAppend = 13,
}

impl MessageKind {
    pub(crate) const fn into(self) -> u8 {
        self as u8
    }
}

impl From<u8> for MessageKind {
    fn from(byte: u8) -> Self {
        use MessageKind::*;
        match byte {
            0 => Corrupted,
            1 => Cancelled,
            2 => Pad,
            3 => BatchManifest,
            4 => Free,
            5 => Counter,
            6 => InlineMeta,
            7 => BlobMeta,
            8 => InlineConfig,
            9 => BlobConfig,
            10 => InlineReplace,
            11 => BlobReplace,
            12 => InlineAppend,
            13 => BlobAppend,
            other => {
                debug!("encountered unexpected message kind byte {}", other);
                Corrupted
            }
        }
    }
}

/// The high-level types of stored information
/// about pages and their mutations
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LogKind {
    /// Persisted data containing a page replacement
    Replace,
    /// Persisted immutable update
    Append,
    /// Freeing of a page
    Free,
    /// Some state indicating this should be skipped
    Skip,
    /// Unexpected corruption
    Corrupted,
}

fn log_kind_from_update<PageFrag>(update: &Update<PageFrag>) -> LogKind
where
    PageFrag: DeserializeOwned + Serialize,
{
    use Update::*;

    match update {
        Free => LogKind::Free,
        Append(..) => LogKind::Append,
        Compact(..) | Counter(..) | Meta(..) | Config(..) => LogKind::Replace,
    }
}

impl From<MessageKind> for LogKind {
    fn from(kind: MessageKind) -> Self {
        use MessageKind::*;
        match kind {
            Free => LogKind::Free,

            InlineReplace | Counter | BlobReplace | InlineMeta | BlobMeta
            | InlineConfig | BlobConfig => LogKind::Replace,

            InlineAppend | BlobAppend => LogKind::Append,

            Cancelled | Pad | BatchManifest => LogKind::Skip,
            other => {
                debug!("encountered unexpected message kind byte {:?}", other);
                LogKind::Corrupted
            }
        }
    }
}

fn assert_usize<T>(from: T) -> usize
where
    usize: TryFrom<T, Error = std::num::TryFromIntError>,
{
    usize::try_from(from).expect("lost data cast while converting to usize")
}

// TODO remove this when atomic fetch_max stabilizes in #48655
fn bump_atomic_lsn(atomic_lsn: &AtomicLsn, to: Lsn) {
    let mut current = atomic_lsn.load(SeqCst);
    loop {
        if current >= to {
            return;
        }
        let last = atomic_lsn.compare_and_swap(current, to, SeqCst);
        if last == current {
            // we succeeded.
            return;
        }
        current = last;
    }
}

use std::convert::{TryFrom, TryInto};

#[cfg(feature = "compression")]
use zstd::block::decompress;

#[inline]
pub(crate) fn u64_to_arr(number: u64) -> [u8; 8] {
    number.to_le_bytes()
}

#[inline]
pub(crate) fn arr_to_u64(arr: &[u8]) -> u64 {
    arr.try_into().map(u64::from_le_bytes).unwrap()
}

#[inline]
pub(crate) fn arr_to_u32(arr: &[u8]) -> u32 {
    arr.try_into().map(u32::from_le_bytes).unwrap()
}

#[inline]
pub(crate) fn u32_to_arr(number: u32) -> [u8; 4] {
    number.to_le_bytes()
}

pub(crate) fn maybe_decompress(buf: Vec<u8>) -> std::io::Result<Vec<u8>> {
    #[cfg(feature = "compression")]
    {
        use std::sync::atomic::AtomicUsize;

        use super::*;

        static MAX_COMPRESSION_RATIO: AtomicUsize = AtomicUsize::new(1);
        use std::sync::atomic::Ordering::{Acquire, Release};

        let _measure = Measure::new(&M.decompress);
        loop {
            let ratio = MAX_COMPRESSION_RATIO.load(Acquire);
            match decompress(&*buf, buf.len() * ratio) {
                Err(ref e) if e.kind() == std::io::ErrorKind::Other => {
                    debug!(
                        "bumping expected compression \
                         ratio up from {} to {}: {:?}",
                        ratio,
                        ratio + 1,
                        e
                    );
                    let _who_cares = MAX_COMPRESSION_RATIO.compare_and_swap(
                        ratio,
                        ratio + 1,
                        Release,
                    );
                }
                other => return other,
            }
        }
    }

    #[cfg(not(feature = "compression"))]
    Ok(buf)
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::process::Command;
use std::env;

fn debug() -> bool {
    match env::var("DEBUG") {
        Ok(s) => s == "true",
        Err(_) => false
    }
}

fn mode() -> &'static str {
    if debug() { "Debug" } else { "Release" }
}

#[cfg(not(windows))]
fn object_path(libname: &str) -> String {
    format!("build/{}/obj.target/{}/src/{}.o", mode(), libname, libname)
}

#[cfg(windows)]
fn object_path(libname: &str) -> String {
    format!("build\\{}\\obj\\{}\\{}.obj", mode(), libname, libname)
}

fn build_object_file() {
    // Ensure that all package.json dependencies and dev dependencies are installed.
    Command::new("npm").arg("install").status().ok()
        .expect(r#"failed to run "npm install" for neon-sys"#);

    // Run the package.json `configure` script, which invokes `node-gyp configure` from the local node_modules.
    Command::new("npm").arg("run").arg(if debug() { "configure-debug" } else { "configure-release" }).status().ok().unwrap();

    // Run the package.json `build` script, which invokes `node-gyp build` from the local node_modules.
    Command::new("npm").arg("run").arg(if debug() { "build-debug" } else { "build-release" }).status().ok().unwrap();
}

fn link_library() {
    // Link the built object file into a static library.
    gcc::Config::new()
        .object(object_path("neon"))
        .compile("libneon.a");
}

fn main() {
    // 1. Build the object file from source using node-gyp.
    build_object_file();

    // 2. Link the library from the object file using gcc.
    link_library();
}
<commit_msg>Fix npm path on windows<commit_after>extern crate gcc;

use std::process::Command;
use std::env;

fn debug() -> bool {
    match env::var("DEBUG") {
        Ok(s) => s == "true",
        Err(_) => false
    }
}

fn mode() -> &'static str {
    if debug() { "Debug" } else { "Release" }
}

#[cfg(unix)]
fn object_path(libname: &str) -> String {
    format!("build/{}/obj.target/{}/src/{}.o", mode(), libname, libname)
}

#[cfg(windows)]
fn object_path(libname: &str) -> String {
    format!("build\\{}\\obj\\{}\\{}.obj", mode(), libname, libname)
}

#[cfg(unix)]
const NPM_COMMAND : &'static str = "npm";

#[cfg(windows)]
const NPM_COMMAND : &'static str = "npm.cmd";

fn build_object_file() {
    // Ensure that all package.json dependencies and dev dependencies are installed.
    Command::new(NPM_COMMAND).arg("install").status().ok()
        .expect(r#"failed to run "npm install" for neon-sys"#);

    // Run the package.json `configure` script, which invokes `node-gyp configure` from the local node_modules.
    Command::new(NPM_COMMAND).arg("run").arg(if debug() { "configure-debug" } else { "configure-release" }).status().ok().unwrap();

    // Run the package.json `build` script, which invokes `node-gyp build` from the local node_modules.
    Command::new(NPM_COMMAND).arg("run").arg(if debug() { "build-debug" } else { "build-release" }).status().ok().unwrap();
}

fn link_library() {
    // Link the built object file into a static library.
    gcc::Config::new()
        .object(object_path("neon"))
        .compile("libneon.a");
}

fn main() {
    // 1. Build the object file from source using node-gyp.
    build_object_file();

    // 2. Link the library from the object file using gcc.
    link_library();
}
<|endoftext|>


<commit_before>use rlua;
use wlroots::{key_events::KeyEvent,
              xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R}, CompositorHandle,
              KeyboardHandle, KeyboardHandler, WLR_KEY_PRESSED};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self,
              compositor: CompositorHandle,
              keyboard: KeyboardHandle,
              event: &KeyEvent) {
        with_handles!([(compositor: {compositor})] => {
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        compositor.terminate();
                        ::awesome::lua::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            }
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_key(event.time_msec(),
                                         event.keycode(),
                                         event.key_state() as u32);
                seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
                let modifiers = keyboard.get_modifiers();
                LUA.with(|lua| {
                    let lua = lua.borrow_mut();
                    let state_string = if event.key_state() == WLR_KEY_PRESSED {
                        "press"
                    } else {
                        "release"
                    };
                    // TODO Awesome uses xcb_key_symbols_get_keysym,
                    // are we using the right function?

                    // TODO Should also emit by current focused client so we can
                    // do client based rules.

                    // TODO Error handling
                    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>
                        (ROOT_KEYS_HANDLE).unwrap();
                    for keysym in event.pressed_keys() {
                        for binding in &keybindings {
                            let obj: awesome::Object = binding.clone().into();
                            let key = awesome::Key::cast(obj.clone()).unwrap();
                            if key.keysym().unwrap() == keysym &&
                                key.modifiers().unwrap() == modifiers.bits() {
                                    emit_object_signal(&*lua,
                                                       obj,
                                                       state_string.into(),
                                                       keysym).unwrap();
                            }
                        }
                    }
                });
            }).expect("Seat was destroyed");
        }).unwrap();
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks());
            }).unwrap();
        }).unwrap();
    }
}
<commit_msg>Proper keybinding error handling<commit_after>use rlua::{self, Lua};
use wlroots::{key_events::KeyEvent,
              xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R}, CompositorHandle,
              KeyboardHandle, KeyboardHandler, WLR_KEY_PRESSED, KeyboardModifier};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self,
              compositor: CompositorHandle,
              keyboard: KeyboardHandle,
              event: &KeyEvent) {
        with_handles!([(compositor: {compositor})] => {
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        compositor.terminate();
                        ::awesome::lua::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            }
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_key(event.time_msec(),
                                         event.keycode(),
                                         event.key_state() as u32);
                seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
                let modifiers = keyboard.get_modifiers();
                LUA.with(|lua| {
                    let lua = lua.borrow_mut();
                    if let Err(err) = emit_awesome_keybindings(&*lua, event, modifiers) {
                        warn!("Could not emit binding for {}: {:?}", event.keycode(), err);
                    }
                });
            }).expect("Seat was destroyed");
        }).unwrap();
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks());
            }).unwrap();
        }).unwrap();
    }
}

/// Emits the Awesome keybindinsg.
fn emit_awesome_keybindings(lua: &Lua,
                            event: &KeyEvent,
                            modifiers: KeyboardModifier)
                            -> rlua::Result<()> {
    let state_string = if event.key_state() == WLR_KEY_PRESSED {
        "press"
    } else {
        "release"
    };
    // TODO Should also emit by current focused client so we can
    // do client based rules.
    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>(ROOT_KEYS_HANDLE)?;
    for keysym in event.pressed_keys() {
        for binding in &keybindings {
            let obj: awesome::Object = binding.clone().into();
            let key = awesome::Key::cast(obj.clone()).unwrap();
            if key.keysym()? == keysym && key.modifiers()? == modifiers.bits() {
                emit_object_signal(&*lua, obj, state_string.into(), keysym)?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits
            let len = filename.len() + ((line!() as f32).log10() as usize) + $msg.len() + 5;
            debug_assert!(len < buf.len(), "log will be truncated");
            let _ = write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg);
            let last = std::cmp::min(len, buf.len() - 1);
            buf[last] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..last + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<commit_msg>Ignore the fractional part of the log value<commit_after>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits
            let len = filename.len() + ((line!() as f32).log10().trunc() as usize) + $msg.len() + 5;
            debug_assert!(len < buf.len(), "log will be truncated");
            let _ = write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg);
            let last = std::cmp::min(len, buf.len() - 1);
            buf[last] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..last + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;
use openssl::crypto::hash::Hasher;
use openssl::crypto::hash::HashType::SHA256;
use serialize::hex::ToHex;
use request::Header;

pub struct SigV4 {
    headers: Vec<Header>,
    path: Option<String>,
    method: Option<String>,
    query: Option<String>,
    payload: Option<String>,
}

impl SigV4 {
    pub fn new() -> SigV4{
        SigV4 {
            headers: Vec::new(),
            path: None,
            method: None,
            query: None,
            payload: None,
        }
    }

    pub fn header(mut self, header: Header) -> SigV4 {
        self.headers.push(header);
        self
    }

    pub fn path(mut self, path: String) -> SigV4 {
        self.path = Some(path);
        self
    }

    pub fn method(mut self, method: String) -> SigV4 {
        self.method = Some(method);
        self
    }

    pub fn query(mut self, query: String) -> SigV4 {
        self.query = Some(query);
        self
    }

    pub fn payload(mut self, payload: String) -> SigV4 {
        self.payload = Some(payload);
        self
    }

    pub fn signature(self) -> String {
        self.method.unwrap()
    }

    fn hashed_payload(self) -> String {
        let val = match self.payload {
            Some(x) => x,
            None => "".to_string(),
        };
        let mut h = Hasher::new(SHA256);
        h.update(val.as_bytes());
        h.finalize().as_slice().to_hex().to_string()
    }

    fn signed_headers(mut self) -> String {
        let mut signed = String::new();
        self.sorted_headers();

        for header in self.headers.iter() {
            let key = header.key.to_ascii_lower();
            if key == "authorization" {
                continue;
            }
            signed.push_str(key.as_slice());
            signed.push(';')
        }
        signed.trim_right_chars(';').to_string()
    }

    fn sorted_headers(&mut self) {
        self.headers.sort_by(|a,b|
                        a.key.to_ascii_lower().cmp(&b.key.to_ascii_lower()))
    }
}

#[cfg(test)]
mod tests {
    use super::SigV4;
    use request::Header;

#[test]
    fn test_new_sigv4() {
        let sig = SigV4::new();
        assert_eq!(sig.headers.len(), 0)
    }

#[test]
    fn test_add_header() {
        let h = Header{ key: "test".to_string(),
        value: "a string".to_string()};

        let sig = SigV4::new().header(h);
        assert_eq!(sig.headers[0].value.as_slice(), "a string")
    }

#[test]
    fn test_signature() {
        let sig = SigV4::new().method("GET".to_string()).path("/".to_string());
        assert_eq!(sig.signature().as_slice(), "GET")
    }

#[test]
    fn test_signed_headers() {
        let h = Header{ key: "test".to_string(),
        value: "a string".to_string()};
        let h2 = Header{ key: "Content-Type".to_string(),
        value: "application/x-www-form-urlencoded; charset=utf-8".to_string()};
        let h3 = Header{ key: "X-Amz-Date".to_string(),
        value: "20120228T030031Z".to_string()};
        let h4 = Header{ key: "Authorization".to_string(),
        value: "none".to_string()};

        let sig = SigV4::new().header(h).header(h2).header(h3).header(h4);
        assert_eq!(sig.signed_headers().as_slice(), "content-type;test;x-amz-date")
    }

#[test]
    fn test_hashed_payload() {
        let sig = SigV4::new().
            payload("Action=ListUsers&Version=2010-05-08".to_string());
        assert_eq!(sig.hashed_payload(),
        "b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2")
    }

#[test]
    fn test_empty_payload() {
        let sig = SigV4::new();
        assert_eq!(sig.hashed_payload(),
        "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
    }
}
<commit_msg>squash double spaces<commit_after>use std::ascii::AsciiExt;
use openssl::crypto::hash::Hasher;
use openssl::crypto::hash::HashType::SHA256;
use serialize::hex::ToHex;
use request::Header;

pub struct SigV4 {
    headers: Vec<Header>,
    path: Option<String>,
    method: Option<String>,
    query: Option<String>,
    payload: Option<String>,
}

impl SigV4 {
    pub fn new() -> SigV4{
        SigV4 {
            headers: Vec::new(),
            path: None,
            method: None,
            query: None,
            payload: None,
        }
    }

    pub fn header(mut self, header: Header) -> SigV4 {
        self.headers.push(header);
        self
    }

    pub fn path(mut self, path: String) -> SigV4 {
        self.path = Some(path);
        self
    }

    pub fn method(mut self, method: String) -> SigV4 {
        self.method = Some(method);
        self
    }

    pub fn query(mut self, query: String) -> SigV4 {
        self.query = Some(query);
        self
    }

    pub fn payload(mut self, payload: String) -> SigV4 {
        self.payload = Some(payload);
        self
    }

    pub fn signature(self) -> String {
        self.method.unwrap()
    }

    fn hashed_payload(self) -> String {
        let val = match self.payload {
            Some(x) => x,
            None => "".to_string(),
        };
        let mut h = Hasher::new(SHA256);
        h.update(val.as_bytes());
        h.finalize().as_slice().to_hex().to_string()
    }

    fn signed_headers(mut self) -> String {
        self.sort_headers();
        let mut h = String::new();

        for header in self.headers.iter() {
            let key = header.key.to_ascii_lower();
            if key == "authorization" {
                continue;
            }
            h.push_str(key.as_slice());
            h.push(';')
        }
        h.trim_right_chars(';').to_string()
    }

    fn canonical_headers(mut self) -> String {
        self.sort_headers();
        let mut h = String::new();

        for header in self.headers.iter() {
            let key = header.key.to_ascii_lower();
            if key == "authorization" {
                continue;
            }
            h.push_str(format!("{}:{}\n", key, canonical_value(&header.value)).as_slice());
        }
        h
    }

    fn sort_headers(&mut self) {
        self.headers.sort_by(|a,b|
                        a.key.to_ascii_lower().cmp(&b.key.to_ascii_lower()))
    }
}

fn canonical_value(val: &String) -> String {
    if val.starts_with("\""){
        val.to_string()
    } else {
        val.replace("  ", " ").trim().to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::SigV4;
    use request::Header;

#[test]
    fn test_new_sigv4() {
        let sig = SigV4::new();
        assert_eq!(sig.headers.len(), 0)
    }

#[test]
    fn test_add_header() {
        let h = Header{ key: "test".to_string(),
        value: "a string".to_string()};

        let sig = SigV4::new().header(h);
        assert_eq!(sig.headers[0].value.as_slice(), "a string")
    }

#[test]
    fn test_signature() {
        let sig = SigV4::new().method("GET".to_string()).path("/".to_string());
        assert_eq!(sig.signature().as_slice(), "GET")
    }

#[test]
    fn test_signed_headers() {
        let h = Header{ key: "test".to_string(),
        value: "a string".to_string()};
        let h2 = Header{ key: "Content-Type".to_string(),
        value: "application/x-www-form-urlencoded; charset=utf-8".to_string()};
        let h3 = Header{ key: "X-Amz-Date".to_string(),
        value: "20120228T030031Z".to_string()};
        let h4 = Header{ key: "Authorization".to_string(),
        value: "none".to_string()};

        let sig = SigV4::new().header(h).header(h2).header(h3).header(h4);
        assert_eq!(sig.signed_headers().as_slice(), "content-type;test;x-amz-date")
    }

#[test]
    fn test_hashed_payload() {
        let sig = SigV4::new().
            payload("Action=ListUsers&Version=2010-05-08".to_string());
        assert_eq!(sig.hashed_payload(),
        "b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2")
    }

#[test]
    fn test_empty_payload() {
        let sig = SigV4::new();
        assert_eq!(sig.hashed_payload(),
        "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
    }

    #[test]
    fn test_canonical_headers() {
        let h = Header{ key: "Xyz".to_string(), value: "1".to_string() };
        let h2 = Header{ key: "Abc".to_string(), value: "2".to_string() };
        let h3 = Header{ key: "Mno".to_string(), value: "3".to_string() };
        let h4 = Header{ key: "Authorization".to_string(), value: "4".to_string() };
        let sig = SigV4::new().header(h).header(h2).header(h3).header(h4);
        assert_eq!(sig.canonical_headers().as_slice(), "abc:2\nmno:3\nxyz:1\n")
    }

    #[test]
    fn test_prune_whitespace() {
        let h = Header{ key: "Abc".to_string(), value: "a  b  c".to_string() };
        let sig = SigV4::new().header(h);
        assert_eq!(sig.canonical_headers().as_slice(), "abc:a b c\n")
    }

    #[test]
    fn test_no_prune_quoted() {
        let h = Header{ key: "Abc".to_string(), value: "\"a  b  c\"".to_string() };
        let sig = SigV4::new().header(h);
        assert_eq!(sig.canonical_headers().as_slice(), "abc:\"a  b  c\"\n")
    }
}
<|endoftext|>


<commit_before>use crate::sync::AtomicWaker;
use tokio_test::task;

use std::task::Waker;

trait AssertSend: Send {}
trait AssertSync: Send {}

impl AssertSend for AtomicWaker {}
impl AssertSync for AtomicWaker {}

impl AssertSend for Waker {}
impl AssertSync for Waker {}

#[cfg(tokio_wasm_not_wasi)]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
fn basic_usage() {
    let mut waker = task::spawn(AtomicWaker::new());

    waker.enter(|cx, waker| waker.register_by_ref(cx.waker()));
    waker.wake();

    assert!(waker.is_woken());
}

#[test]
fn wake_without_register() {
    let mut waker = task::spawn(AtomicWaker::new());
    waker.wake();

    // Registering should not result in a notification
    waker.enter(|cx, waker| waker.register_by_ref(cx.waker()));

    assert!(!waker.is_woken());
}

#[test]
#[cfg(not(tokio_wasm))] // wasm currently doesn't support unwinding
fn atomic_waker_panic_safe() {
    use std::panic;
    use std::ptr;
    use std::task::{RawWaker, RawWakerVTable, Waker};

    static PANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new(
        |_| panic!("clone"),
        |_| unimplemented!("wake"),
        |_| unimplemented!("wake_by_ref"),
        |_| (),
    );

    static NONPANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new(
        |_| RawWaker::new(ptr::null(), &NONPANICKING_VTABLE),
        |_| unimplemented!("wake"),
        |_| unimplemented!("wake_by_ref"),
        |_| (),
    );

    let panicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &PANICKING_VTABLE)) };
    let nonpanicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &NONPANICKING_VTABLE)) };

    let atomic_waker = AtomicWaker::new();

    let panicking = panic::AssertUnwindSafe(&panicking);

    let result = panic::catch_unwind(|| {
        let panic::AssertUnwindSafe(panicking) = panicking;
        atomic_waker.register_by_ref(panicking);
    });

    assert!(result.is_err());
    assert!(atomic_waker.take_waker().is_none());

    atomic_waker.register_by_ref(&nonpanicking);
    assert!(atomic_waker.take_waker().is_some());
}
<commit_msg>sync: fix `Sync` assertion for `AtomicWaker` (#5165)<commit_after>use crate::sync::AtomicWaker;
use tokio_test::task;

use std::task::Waker;

trait AssertSend: Send {}
trait AssertSync: Sync {}

impl AssertSend for AtomicWaker {}
impl AssertSync for AtomicWaker {}

impl AssertSend for Waker {}
impl AssertSync for Waker {}

#[cfg(tokio_wasm_not_wasi)]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
fn basic_usage() {
    let mut waker = task::spawn(AtomicWaker::new());

    waker.enter(|cx, waker| waker.register_by_ref(cx.waker()));
    waker.wake();

    assert!(waker.is_woken());
}

#[test]
fn wake_without_register() {
    let mut waker = task::spawn(AtomicWaker::new());
    waker.wake();

    // Registering should not result in a notification
    waker.enter(|cx, waker| waker.register_by_ref(cx.waker()));

    assert!(!waker.is_woken());
}

#[test]
#[cfg(not(tokio_wasm))] // wasm currently doesn't support unwinding
fn atomic_waker_panic_safe() {
    use std::panic;
    use std::ptr;
    use std::task::{RawWaker, RawWakerVTable, Waker};

    static PANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new(
        |_| panic!("clone"),
        |_| unimplemented!("wake"),
        |_| unimplemented!("wake_by_ref"),
        |_| (),
    );

    static NONPANICKING_VTABLE: RawWakerVTable = RawWakerVTable::new(
        |_| RawWaker::new(ptr::null(), &NONPANICKING_VTABLE),
        |_| unimplemented!("wake"),
        |_| unimplemented!("wake_by_ref"),
        |_| (),
    );

    let panicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &PANICKING_VTABLE)) };
    let nonpanicking = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &NONPANICKING_VTABLE)) };

    let atomic_waker = AtomicWaker::new();

    let panicking = panic::AssertUnwindSafe(&panicking);

    let result = panic::catch_unwind(|| {
        let panic::AssertUnwindSafe(panicking) = panicking;
        atomic_waker.register_by_ref(panicking);
    });

    assert!(result.is_err());
    assert!(atomic_waker.take_waker().is_none());

    atomic_waker.register_by_ref(&nonpanicking);
    assert!(atomic_waker.take_waker().is_some());
}
<|endoftext|>


<commit_before>use cargo_registry::tasks::dump_db;
use diesel::{
    connection::{Connection, SimpleConnection},
    pg::PgConnection,
};

#[test]
fn dump_db_and_reimport_dump() {
    let database_url = crate::env("TEST_DATABASE_URL");

    // TODO prefill database with some data

    let directory = dump_db::DumpDirectory::create().unwrap();
    directory.dump_db(&database_url).unwrap();

    let import_script = directory.export_dir.join("import.sql");
    let schema = TemporarySchema::create(database_url, "test_db_dump");
    diesel_migrations::run_pending_migrations(&schema.connection).unwrap();
    dump_db::run_psql(&import_script, &schema.database_url).unwrap();
}

struct TemporarySchema {
    pub database_url: String,
    pub schema_name: String,
    pub connection: PgConnection,
}

impl TemporarySchema {
    fn create(database_url: String, schema_name: &str) -> Self {
        let params = &[("options", format!("--search_path={}", schema_name))];
        let database_url = url::Url::parse_with_params(&database_url, params)
            .unwrap()
            .into_string();
        let schema_name = schema_name.to_owned();
        let connection = PgConnection::establish(&database_url).unwrap();
        connection
            .batch_execute(&format!(
                r#"DROP SCHEMA IF EXISTS "{schema_name}" CASCADE;
                   CREATE SCHEMA "{schema_name}";
                   SET SESSION search_path TO "{schema_name}",public;"#,
                schema_name = schema_name,
            ))
            .unwrap();
        Self {
            database_url,
            schema_name,
            connection,
        }
    }
}

impl Drop for TemporarySchema {
    fn drop(&mut self) {
        self.connection
            .batch_execute(&format!(
                r#"SET SESSION search_path TO DEFAULT;
                   DROP SCHEMA {schema_name} CASCADE;"#,
                schema_name = self.schema_name,
            ))
            .unwrap();
    }
}
<commit_msg>Suppress migrations output in dump_db test.<commit_after>use cargo_registry::tasks::dump_db;
use diesel::{
    connection::{Connection, SimpleConnection},
    pg::PgConnection,
};

#[test]
fn dump_db_and_reimport_dump() {
    let database_url = crate::env("TEST_DATABASE_URL");

    // TODO prefill database with some data

    let directory = dump_db::DumpDirectory::create().unwrap();
    directory.dump_db(&database_url).unwrap();

    let schema = TemporarySchema::create(database_url, "test_db_dump");
    schema.run_migrations();

    let import_script = directory.export_dir.join("import.sql");
    dump_db::run_psql(&import_script, &schema.database_url).unwrap();

    // TODO: Consistency checks on the re-imported data?
}

struct TemporarySchema {
    pub database_url: String,
    pub schema_name: String,
    pub connection: PgConnection,
}

impl TemporarySchema {
    pub fn create(database_url: String, schema_name: &str) -> Self {
        let params = &[("options", format!("--search_path={},public", schema_name))];
        let database_url = url::Url::parse_with_params(&database_url, params)
            .unwrap()
            .into_string();
        let schema_name = schema_name.to_owned();
        let connection = PgConnection::establish(&database_url).unwrap();
        connection
            .batch_execute(&format!(
                r#"DROP SCHEMA IF EXISTS "{schema_name}" CASCADE;
                   CREATE SCHEMA "{schema_name}";"#,
                schema_name = schema_name,
            ))
            .unwrap();
        Self {
            database_url,
            schema_name,
            connection,
        }
    }

    pub fn run_migrations(&self) {
        use diesel_migrations::{find_migrations_directory, run_pending_migrations_in_directory};
        let migrations_dir = find_migrations_directory().unwrap();
        run_pending_migrations_in_directory(
            &self.connection,
            &migrations_dir,
            &mut std::io::sink(),
        )
        .unwrap();
    }
}

impl Drop for TemporarySchema {
    fn drop(&mut self) {
        self.connection
            .batch_execute(&format!(r#"DROP SCHEMA "{}" CASCADE;"#, self.schema_name))
            .unwrap();
    }
}
<|endoftext|>