<commit_before>#![allow(dead_code)]
extern crate collections;

use std::io;
use self::collections::hashmap::HashMap;

priv struct Memory {
    mem: ~[u8],
    memptr: int,
    codeptr: uint,
    cache: HashMap<uint, uint>
}

pub struct BrainfuckVM {
    code: ~str,
}

impl BrainfuckVM {
    pub fn new(code : ~str) -> BrainfuckVM {
        BrainfuckVM {
            code: code,
        }
    }

    pub fn run(&self) -> bool {
        let mut state = Memory{
            mem: ~[0],
            memptr: 0,
            codeptr: 0,
            cache: HashMap::new()
        };

        if !self.eval(&mut state) {
            return false;
        }

        return true;
    }

    fn eval(&self, state: &mut Memory) -> bool {
        while (state.codeptr as uint) < (self.code.len()) {
            match self.code[state.codeptr] as char {
                '>' => {
                    state.memptr += 1;
                    if state.memptr as uint > state.mem.len()-1{
                        state.mem.push(0);
                    }
                },
                '<' => {

                    if !(state.memptr as uint <= 0) {
                        state.memptr -= 1;
                    }

                },
                '+' => {
                    state.mem[state.memptr] += 1;
                },
                '-' => {
                    state.mem[state.memptr] -= 1;
                },
                '.' => {
                    print!("{}", state.mem[state.memptr] as char);
                },
                ',' => {

                    let x = match io::stdin().read_byte() {
                        Ok(b) => b,
                        Err(_) =>  0
                    };

                    state.mem[state.memptr] = x;

                },
                '[' => {

                    let start = state.codeptr;

                    let mut depth = 0;
                    if state.mem[state.memptr] == 0 {
                        let found = match state.cache.find(&state.codeptr) {
                            Some(c) => *c,
                            None => 0
                        };
                        if found > 0 {
                            state.codeptr = found;
                        } else {
                            state.codeptr += 1;
                            let mut currentChar = self.code[state.codeptr] as char;
                            while depth > 0 || currentChar  != ']' {
                                if currentChar == '[' {
                                    depth += 1;
                                } else if currentChar == ']' {
                                    depth -= 1;
                                }
                                state.codeptr += 1;
                                currentChar = self.code[state.codeptr] as char;
                            }
                            state.cache.insert(start, state.codeptr);
                        }
                    }
                },
                ']' => {
                    let start = state.codeptr;

                    let mut depth = 0;

                    if state.mem[state.memptr] != 0 {
                        let found = match state.cache.find(&state.codeptr) {
                            Some(c) => *c,
                            None => 0
                        };

                        if found > 0 {
                            state.codeptr = found;
                        } else {
                            state.codeptr -= 1;
                            let mut currentChar = self.code[state.codeptr] as char;
                            while depth > 0 || currentChar != '[' {

                                if currentChar == ']' {
                                    depth += 1;
                                } else if currentChar == '[' {
                                    depth -= 1;
                                }
                                state.codeptr -= 1;
                                currentChar = self.code[state.codeptr] as char;
                            }
                            state.cache.insert(start, state.codeptr);
                        }
                    }

                },
                _ => {
                    // Ignore other characters
                }
            };

            //print!("Character: [{}] ", self.code[state.codeptr]);
            //print!("Memory: [{}]", state.mem);
            //print!("Memory Pointer: {} [{}]", state.memptr, state.mem[state.memptr]);
            //print!("Cache: {} \n", state.cache);
            state.codeptr += 1;
        }
        return true;
    }
}
<commit_msg>Use smallintmap, makes it faster<commit_after>#![allow(dead_code)]
extern crate collections;

use std::io;
use self::collections::smallintmap::SmallIntMap;

priv struct Memory {
    mem: ~[u8],
    memptr: int,
    codeptr: uint,
    cache: SmallIntMap<uint>
}

pub struct BrainfuckVM <'c> {
    code: &'c str,
}

impl <'c> BrainfuckVM <'c> {
    pub fn new(code : &'c str) -> BrainfuckVM<'c> {
        BrainfuckVM {
            code: code,
        }
    }

    pub fn run(&self) -> bool {
        let mut state = Memory{
            mem: ~[0],
            memptr: 0,
            codeptr: 0,
            cache: SmallIntMap::new()
        };

        if !self.eval(&mut state) {
            return false;
        }

        return true;
    }

    fn eval(&self, state: &mut Memory) -> bool {
        while (state.codeptr as uint) < (self.code.len()) {
            match self.code[state.codeptr] as char {
                '>' => {
                    state.memptr += 1;
                    if state.memptr as uint > state.mem.len()-1{
                        state.mem.push(0);
                    }
                },
                '<' => {

                    if !(state.memptr as uint <= 0) {
                        state.memptr -= 1;
                    }

                },
                '+' => {
                    state.mem[state.memptr] += 1;
                },
                '-' => {
                    state.mem[state.memptr] -= 1;
                },
                '.' => {
                    print!("{}", state.mem[state.memptr] as char);
                },
                ',' => {

                    let x = match io::stdin().read_byte() {
                        Ok(b) => b,
                        Err(_) =>  0
                    };

                    state.mem[state.memptr] = x;

                },
                '[' => {

                    let start = state.codeptr;
                    let mut depth = 0;
                    if state.mem[state.memptr] == 0 {
                        let found = match state.cache.find(&state.codeptr) {
                            Some(c) => *c,
                            None => 0
                        };
                        if found > 0 {
                            state.codeptr = found;
                        } else {
                            state.codeptr += 1;
                            let mut currentChar = self.code[state.codeptr] as char;
                            while depth > 0 || currentChar  != ']' {
                                if currentChar == '[' {
                                    depth += 1;
                                } else if currentChar == ']' {
                                    depth -= 1;
                                }
                                state.codeptr += 1;
                                currentChar = self.code[state.codeptr] as char;
                            }
                            state.cache.insert(start, state.codeptr);
                        }
                    }
                },
                ']' => {
                    let start = state.codeptr;

                    let mut depth = 0;

                    if state.mem[state.memptr] != 0 {
                        let found = match state.cache.find(&state.codeptr) {
                            Some(c) => *c,
                            None => 0
                        };

                        if found > 0 {
                            state.codeptr = found;
                        } else {
                            state.codeptr -= 1;
                            let mut currentChar = self.code[state.codeptr] as char;
                            while depth > 0 || currentChar != '[' {

                                if currentChar == ']' {
                                    depth += 1;
                                } else if currentChar == '[' {
                                    depth -= 1;
                                }
                                state.codeptr -= 1;
                                currentChar = self.code[state.codeptr] as char;
                            }
                            state.cache.insert(start, state.codeptr);
                        }
                    }

                },
                _ => {
                    // Ignore other characters
                }
            };

            //print!("Character: [{}] ", self.code[state.codeptr]);
            //print!("Memory: [{}]", state.mem);
            //print!("Memory Pointer: {} [{}]", state.memptr, state.mem[state.memptr]);
            //print!("Cache: {} \n", state.cache);
            state.codeptr += 1;
        }
        return true;
    }
}
<|endoftext|>


<commit_before>#![feature(llvm_asm)]

use std::env;

#[cfg(miri)]
compile_error!("`miri` cfg should not be set in build script");

fn not_in_miri() -> i32 {
    // Inline assembly definitely does not work in Miri.
    let dummy = 42;
    unsafe {
        llvm_asm!("" : : "r"(&dummy));
    }
    return dummy;
}

fn main() {
    not_in_miri();
    // Cargo calls `miri --print=cfg` to populate the `CARGO_CFG_*` env vars.
    // Make sure that the "miri" flag is set.
    assert!(env::var_os("CARGO_CFG_MIRI").is_some());
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-env-changed=MIRITESTVAR");
    println!("cargo:rustc-env=MIRITESTVAR=testval");
}
<commit_msg>llvm_asm → asm<commit_after>#![feature(asm)]

use std::env;

#[cfg(miri)]
compile_error!("`miri` cfg should not be set in build script");

fn not_in_miri() -> i32 {
    // Inline assembly definitely does not work in Miri.
    let mut dummy = 42;
    unsafe {
        asm!("/* {} */", in(reg) &mut dummy);
    }
    return dummy;
}

fn main() {
    not_in_miri();
    // Cargo calls `miri --print=cfg` to populate the `CARGO_CFG_*` env vars.
    // Make sure that the "miri" flag is set.
    assert!(env::var_os("CARGO_CFG_MIRI").is_some());
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-env-changed=MIRITESTVAR");
    println!("cargo:rustc-env=MIRITESTVAR=testval");
}
<|endoftext|>


<commit_before>//! This module contains `Impossible` serializer and its implementations.

use lib::*;

use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
          SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};

/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the `Serializer` compound types: `SerializeSeq`,
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`,
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
/// #
/// impl Serializer for MySerializer {
///     type Ok = ();
///     type Error = Error;
///
///     type SerializeSeq = Impossible<(), Error>;
///     /* other associated types */
///
///     /// This data format does not support serializing sequences.
///     fn serialize_seq(self,
///                      len: Option<usize>)
///                      -> Result<Self::SerializeSeq, Error> {
///         // Given Impossible cannot be instantiated, the only
///         // thing we can do here is to return an error.
/// #         stringify! {
///         Err(...)
/// #         };
/// #         unimplemented!()
///     }
///
///     /* other Serializer methods */
/// #     __serialize_unimplemented! {
/// #         bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// #         unit unit_struct unit_variant newtype_struct newtype_variant
/// #         seq_fixed_size tuple tuple_struct tuple_variant map struct
/// #         struct_variant
/// #     }
/// }
/// #
/// # fn main() {}
/// ```
pub struct Impossible<Ok, E> {
    void: Void,
    _marker: PhantomData<(Ok, E)>,
}

enum Void {}

impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeMap for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
        match self.void {}
    }

    fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(
        &mut self,
        _key: &'static str,
        _value: &T,
    ) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(
        &mut self,
        _key: &'static str,
        _value: &T,
    ) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}
<commit_msg>Hyperlink the Impossible documentation<commit_after>//! This module contains `Impossible` serializer and its implementations.

use lib::*;

use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
          SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};

/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the [`Serializer`] compound types: [`SerializeSeq`],
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
/// #
/// impl Serializer for MySerializer {
///     type Ok = ();
///     type Error = Error;
///
///     type SerializeSeq = Impossible<(), Error>;
///     /* other associated types */
///
///     /// This data format does not support serializing sequences.
///     fn serialize_seq(self,
///                      len: Option<usize>)
///                      -> Result<Self::SerializeSeq, Error> {
///         // Given Impossible cannot be instantiated, the only
///         // thing we can do here is to return an error.
/// #         stringify! {
///         Err(...)
/// #         };
/// #         unimplemented!()
///     }
///
///     /* other Serializer methods */
/// #     __serialize_unimplemented! {
/// #         bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// #         unit unit_struct unit_variant newtype_struct newtype_variant
/// #         seq_fixed_size tuple tuple_struct tuple_variant map struct
/// #         struct_variant
/// #     }
/// }
/// #
/// # fn main() {}
/// ```
///
/// [`Serializer`]: trait.Serializer.html
/// [`SerializeSeq`]: trait.SerializeSeq.html
/// [`SerializeTuple`]: trait.SerializeTuple.html
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
/// [`SerializeMap`]: trait.SerializeMap.html
/// [`SerializeStruct`]: trait.SerializeStruct.html
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
pub struct Impossible<Ok, E> {
    void: Void,
    _marker: PhantomData<(Ok, E)>,
}

enum Void {}

impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeMap for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
        match self.void {}
    }

    fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(
        &mut self,
        _key: &'static str,
        _value: &T,
    ) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}

impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where
    E: ser::Error,
{
    type Ok = Ok;
    type Error = E;

    fn serialize_field<T: ?Sized + Serialize>(
        &mut self,
        _key: &'static str,
        _value: &T,
    ) -> Result<(), E> {
        match self.void {}
    }

    fn end(self) -> Result<Ok, E> {
        match self.void {}
    }
}
<|endoftext|>


<commit_before>///Script to compress png with pngcrush.exe
///Just handle files/folders as cmd arguments. Nothing interesting

use std::env::args as cmd_args;
use std::process::Command;
use std::path::Path;
use std::fs::{create_dir, read_dir};

macro_rules! exec_cmd {
    (cmd=>$cmd:expr, $($arg:expr),*) => { Command::new($cmd)$(.arg($arg))*.status().unwrap(); }
}

#[inline(always)]
fn usage() {
    println!("Usage: pngcompress [file/dir]");
    println!("pngcrush.exe is used for compression");
}

fn main() {
    if cmd_args().len() < 2 { return usage(); }

    let script_path = cmd_args().next().unwrap();
    let script_dir = Path::new(&script_path).parent().unwrap();
    let pngcrush = script_dir.join("pngcrush.exe");
    let pngcrush = pngcrush.to_str().unwrap();

    for arg in cmd_args().skip(1) {
        let arg_path = Path::new(&arg);
        let is_file: bool = arg_path.extension().is_some();

        if is_file && arg.ends_with("png") {
            println!(">>>Compress file: {}", arg);
            let crushed_dir = arg_path.parent().unwrap().join("compressed_png");
            let _ = create_dir(crushed_dir.to_str().unwrap());
            exec_cmd!(cmd=>pngcrush, "-d", crushed_dir.to_str().unwrap(), arg_path.to_str().unwrap());
            println!("Result: {}", crushed_dir.join(arg_path.to_str().unwrap()).display());
        }
        else {
            let dir_content = read_dir(arg_path.to_str().unwrap());

            //Assume that it is not dir then
            if dir_content.is_err() { continue; }

            let dir_content = dir_content.unwrap();

            for entry in dir_content {
                let entry_path = entry.unwrap().path();
                let is_file = entry_path.extension().is_some();

                if is_file && entry_path.to_str().unwrap().ends_with(".png") {
                    println!(">>>Compress file: {}", entry_path.display());
                    let crushed_dir = entry_path.parent().unwrap().join("compressed_png");
                    let _ = create_dir(crushed_dir.to_str().unwrap());
                    exec_cmd!(cmd=>pngcrush, "-d", crushed_dir.to_str().unwrap(), entry_path.to_str().unwrap());
                    println!("Result: {}", crushed_dir.join(entry_path.file_name().unwrap()).display());
                }
            }
        }
    }
}
<commit_msg>pngcompress: Improve file-checking<commit_after>///Script to compress png with pngcrush.exe
///Just handle files/folders as cmd arguments. Nothing interesting

use std::env::args as cmd_args;
use std::process::{Command, Stdio};
use std::path::Path;
use std::fs::{create_dir, read_dir, metadata};

macro_rules! exec_cmd {
    (cmd=>$cmd:expr, $($arg:expr),*) => { Command::new($cmd)$(.arg($arg))*.stderr(Stdio::null()).stdout(Stdio::null()).status().unwrap(); }
}

macro_rules! input {
    ($msg:expr) => {{
        use std::io::{Read, Write};
        print!($msg);
        std::io::stdout().flush().unwrap();
        std::io::stdin().bytes().next();
    }}
}

macro_rules! is_file {
    ($path:expr) => { std::fs::metadata($path).unwrap().is_file() }
}

macro_rules! is_extension_eq {
    ($path:expr, $ext:expr) => { $path.extension().map_or(false, |ext| ext == $ext) }
}

#[inline(always)]
fn usage() {
    println!("Usage: pngcompress [file/dir]");
    println!("pngcrush.exe is used for compression");
}

fn main() {
    if cmd_args().len() < 2 { return usage(); }

    let script_path = cmd_args().next().unwrap();
    let pngcrush = Path::new(&script_path).parent().unwrap().join("pngcrush.exe");
    let pngcrush = pngcrush.to_str().unwrap();

    drop(script_path);

    for arg in cmd_args().skip(1) {
        let arg_is_file: bool;
        if let Ok(meta_data) = metadata(&arg) {
            arg_is_file = meta_data.is_file();
        }
        else {
            println!(">>>{}: No such file or directory", &arg);
            continue;
        }

        //File handler
        if arg_is_file {
            let arg_path = Path::new(&arg);
            if is_extension_eq!(arg_path, "png") {
                println!(">>>Compress file: {}", arg);
                let crushed_dir = arg_path.parent().unwrap().join("compressed_png");
                let _ = create_dir(crushed_dir.to_str().unwrap());
                exec_cmd!(cmd=>pngcrush, "-d", crushed_dir.to_str().unwrap(), arg_path.to_str().unwrap());
                println!("Result: {}", crushed_dir.join(arg_path.to_str().unwrap()).display());
            }
        }
        //Directory handler
        else if let Ok(dir_content) = read_dir(&arg) {
            for entry_path in dir_content {
                let entry_path = entry_path.unwrap().path();

                if is_file!(&entry_path) && is_extension_eq!(entry_path, "png") {
                    println!(">>>Compress file: {}", entry_path.display());
                    let crushed_dir = entry_path.parent().unwrap().join("compressed_png");
                    let _ = create_dir(crushed_dir.to_str().unwrap());
                    exec_cmd!(cmd=>pngcrush, "-d", crushed_dir.to_str().unwrap(), entry_path.to_str().unwrap());
                    println!("Result: {}", crushed_dir.join(entry_path.file_name().unwrap()).display());
                }
            }
        }
        //Error handler
        else {
            println!(">>>{}: cannot access directory", &arg);
            continue;
        }
    }
    input!("Press Enter to exit...");
}
<|endoftext|>


<commit_before>/// Figure 12.16: Synchronous signal handling
///
/// Status: only partially implemented, maybe does not work yet
///
/// Findings:
///
/// - instead of pthread_mutex_lock and pthread_cond_signal I found that
///   Rusts Mutex/Condvar serves the same purpose
/// - it took me a while to understand how the mutex works together with
///   pthread_cond_wait (namely, taht pthread_cond_wait unlocks the mutex),
///   although this has been the subject before.. Interesting to see
///   that rusts Mutex/Condvar behave exactly the same:
///   https://doc.rust-lang.org/std/sync/struct.Condvar.html#examples

extern crate libc;
extern crate apue;

use apue::LibcResult;

use std::sync::{Arc, Mutex, Condvar};
use std::thread;

use libc::{sigset_t, pthread_mutex_t, SIGINT, SIGQUIT, SIG_BLOCK, PTHREAD_MUTEX_INITIALIZER};
use libc::{sigwait, pthread_mutex_lock, pthread_mutex_unlock, sleep, exit, sigemptyset, sigaddset, pthread_sigmask};

unsafe fn thr_fn(mask:&sigset_t, pair:Arc<(Mutex<bool>, Condvar)>) {
    let mut signo = std::mem::uninitialized();
    loop {
        sigwait(mask, &mut signo).check_zero().expect("sigwait failed");
        match signo {
            SIGINT => {
                println!("\ninterrupt");
            },
            SIGQUIT => {
                let &(ref lock, ref cvar) = &*pair;
                let mut quitflag = lock.lock().unwrap();
                *quitflag = true;
                cvar.notify_one();
            },
            _ => {
                println!("unexpectd signal {}", signo);
                exit(1);
            }
        }
    }
}

static mut LOCK:pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;

fn main() {
    unsafe {
        let pair = Arc::new((Mutex::new(false), Condvar::new()));
        let pair2 = pair.clone();
        let (mut mask, mut oldmask) = std::mem::uninitialized();
        sigemptyset(&mut mask);
        sigaddset(&mut mask, SIGINT);
        sigaddset(&mut mask, SIGQUIT);
        pthread_sigmask(SIG_BLOCK, &mask, &mut oldmask).check_zero().expect("SIG_BLOCK error");
        thread::spawn(move || {
            thr_fn(&mask, pair2);
        });
        // Wait for the thread to start up.
        let &(ref lock, ref cvar) = &*pair;
        {
            let mut quitflag = lock.lock().unwrap();
            while !*quitflag {
                quitflag = cvar.wait(quitflag).unwrap();
            }
                * quitflag = false;
        }

    }
}<commit_msg>Finish Figure 12.16<commit_after>/// Figure 12.16: Synchronous signal handling
///
/// Findings:
///
/// - instead of pthread_mutex_lock and pthread_cond_signal I found that
///   Rusts Mutex/Condvar serves the same purpose
/// - it took me a while to understand how the mutex works together with
///   pthread_cond_wait (namely, taht pthread_cond_wait unlocks the mutex),
///   although this has been the subject before.. Interesting to see
///   that rusts Mutex/Condvar behave exactly the same:
///   https://doc.rust-lang.org/std/sync/struct.Condvar.html#examples
//
// Does not yet work with test.py, that's why I put it only behind two //
// see http://stackoverflow.com/questions/43730557/

// $ f16-signal-handling & pid=$! && sleep 0.1 && kill -s INT $pid && sleep 0.1 && kill -s QUIT $pid
// interrupt
// quit

extern crate libc;
extern crate apue;

use apue::LibcResult;

use std::sync::{Arc, Mutex, Condvar};
use std::thread;

use libc::{sigset_t, SIGINT, SIGQUIT, SIG_BLOCK, SIG_SETMASK};
use libc::{sigwait, exit, sigemptyset, sigaddset, pthread_sigmask};
use apue::my_libc::sigprocmask;

unsafe fn thr_fn(mask:&sigset_t, pair:Arc<(Mutex<bool>, Condvar)>) {
    let mut signo = std::mem::uninitialized();
    loop {
        sigwait(mask, &mut signo).check_zero().expect("sigwait failed");
        match signo {
            SIGINT => {
                println!("\ninterrupt");
            },
            SIGQUIT => {
                println!("\nquit");
                let &(ref lock, ref cvar) = &*pair;
                let mut quitflag = lock.lock().unwrap();
                *quitflag = true;
                cvar.notify_one();
            },
            _ => {
                println!("unexpectd signal {}", signo);
                exit(1);
            }
        }
    }
}

fn main() {
    unsafe {
        let pair = Arc::new((Mutex::new(false), Condvar::new()));
        let pair2 = pair.clone();
        let (mut mask, mut oldmask) = std::mem::uninitialized();
        sigemptyset(&mut mask);
        sigaddset(&mut mask, SIGINT);
        sigaddset(&mut mask, SIGQUIT);
        pthread_sigmask(SIG_BLOCK, &mask, &mut oldmask).check_zero().expect("SIG_BLOCK error");
        thread::spawn(move || {
            thr_fn(&mask, pair2);
        });
        let &(ref lock, ref cvar) = &*pair;

        // wait for the quitflag
        // trick is that the lock is unlocked on cvar.wait(quitflag)
        {
            let mut quitflag = lock.lock().unwrap();
            while !*quitflag {
                quitflag = cvar.wait(quitflag).unwrap();
            }
            *quitflag = false;
        }

        // SIGQUIT has been caught. Lock is unlocked upon dropping of the quitflag var
        // reset signal mask which unblocks SIGQUIT
        sigprocmask(SIG_SETMASK, &oldmask, std::ptr::null_mut()).check_not_negative().expect("SIG_SETMASK error");
    }
}<|endoftext|>


<commit_before>use ffi::*;
use libc::{self, int32_t};
use std::ffi::CStr;

macro_rules! error_return (
    ($context:expr) => (
        unsafe {
            flow_context_add_to_callstack($context, concat!(file!(), "\0").as_ptr() as *const libc::c_char,
                line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char);
        }
    );
);

macro_rules! error_msg (
    ($context:expr, $status: expr) => (
        unsafe {
            let c = CStr::from_ptr($crate::ffi::flow_context_set_error_get_message_buffer($context, $status as i32,
                concat!(file!(), "\0").as_ptr() as *const libc::c_char,
                line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char));
            println!("{:?}", c);
        }
    );
    ($context:expr, $status: expr, $format:expr, $($args:expr),*) => (
        let c = CStr::from_ptr($crate::ffi::flow_context_set_error_get_message_buffer($context, $status as i32,
            concat!(file!(), "\0").as_ptr() as *const libc::c_char,
            line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char));
        let formatted = fmt::format(format_args!(concat!($format, "\0"),$($args),*));
        println!("{:?} {}", c, formatted);
    );
);

pub fn job_execute(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool {
  if !flow_job_notify_graph_changed(c, job, graph_ref) {
        error_return!(c);
    }
    if !job_link_codecs(c, job, graph_ref) {
        error_return!(c);
    }
/* FIXME
    // States for a node
    // New
    // OutboundDimensionsKnown
    // Flattened
    // Optimized
    // LockedForExecution
    // Executed
    let mut passes: libc::int32_t = 0;
    while (!flow_job_graph_fully_executed(c, job, *graph_ref)) {
        if (passes >= job->max_calc_flatten_execute_passes) {
            FLOW_error(c, flow_status_Maximum_graph_passes_exceeded);
            return false;
        }
        if (!flow_job_populate_dimensions_where_certain(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_graph_pre_optimize_flatten(c, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_populate_dimensions_where_certain(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_graph_optimize(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_populate_dimensions_where_certain(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_graph_post_optimize_flatten(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_populate_dimensions_where_certain(c, job, graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
        if (!flow_job_execute_where_certain(c, job, graph_ref)) {
            error_return!(c);
        }
        passes++;

        if (!flow_job_notify_graph_changed(c, job, *graph_ref)) {
            error_return!(c);
        }
    }
    if (job->next_graph_version > 0 && job->render_last_graph
        && !flow_job_render_graph_to_png(c, job, *graph_ref, job->next_graph_version - 1)) {
        error_return!(c);
    }
*/
  true
}

pub fn job_link_codecs(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool {

    if graph_ref.is_null() || unsafe { (*graph_ref).is_null() } {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }
    if !flow_job_notify_graph_changed(c, job, graph_ref) {
        error_return!(c);
    }

/* FIXME
    struct flow_graph * g = *graph_ref;
    let mut i: int32_t = 0;
    for (i = 0; i < g->next_node_id; i++) {
        if (g->nodes[i].type == flow_ntype_decoder || g->nodes[i].type == flow_ntype_encoder) {
            uint8_t * info_bytes = &g->info_bytes[g->nodes[i].info_byte_index];
            struct flow_nodeinfo_codec * info = (struct flow_nodeinfo_codec *)info_bytes;
            if (info->codec == NULL) {
                info->codec = flow_job_get_codec_instance(c, job, info->placeholder_id);

                if (info->codec == NULL)
                    FLOW_error_msg(c, flow_status_Graph_invalid,
                                   "No matching codec or io found for placeholder id %d (node #%d).",
                                   info->placeholder_id, i);
            }
        }
    }
*/

    return true;
}

fn flow_job_notify_graph_changed(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool {
/* FIXME
    if (job == NULL || !job->record_graph_versions || job->next_graph_version > FLOW_MAX_GRAPH_VERSIONS)
        return true;

    char filename[255];
    char image_prefix[255];
    char prev_filename[255];

    if (job->next_graph_version == 0) {
        // Delete existing graphs
        int32_t i = 0;
        for (i = 0; i <= FLOW_MAX_GRAPH_VERSIONS; i++) {
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, i);
            remove(filename);
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot.png", job->debug_job_id, i);
            remove(filename);
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot.svg", job->debug_job_id, i);
            remove(filename);
            int32_t node_ix = 0;
            for (node_ix = 0; node_ix < 42; node_ix++) {
                flow_snprintf(filename, 254, "./node_frames/job_%d_node_%d.png", job->debug_job_id, node_ix);
                remove(filename);
            }
        }
    }

    int32_t prev_graph_version = job->next_graph_version - 1;
    int32_t current_graph_version = job->next_graph_version;
    job->next_graph_version++;

    flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, current_graph_version);

    flow_snprintf(image_prefix, 254, "./node_frames/job_%d_node_", job->debug_job_id);

    FILE * f = fopen(filename, "w");
    if (f == NULL) {
        FLOW_error_msg(c, flow_status_IO_error, "Failed to open %s for graph dotfile export.", filename);
        return false;
    }
    if (!flow_graph_print_to_dot(c, g, f, image_prefix)) {
        fclose(f);
        FLOW_error_return(c);
    } else {
        fclose(f);
    }
    // Compare
    if (job->next_graph_version > 1) {
        flow_snprintf(prev_filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, prev_graph_version);
        bool identical = false;
        if (!files_identical(c, prev_filename, filename, &identical)) {
            FLOW_error_return(c);
        }
        if (identical) {
            job->next_graph_version--; // Next time we will overwrite the duplicate graph. The last two graphs may
            // remain dupes.
            remove(filename);
        } else if (job->render_graph_versions) {
            flow_job_render_graph_to_png(c, job, g, prev_graph_version);
        }
    }
*/
    return true;
}

pub fn flow_job_graph_fully_executed(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool
{
/*FIXME
    int32_t i;
    for (i = 0; i < g->next_node_id; i++) {
        if (g->nodes[i].type != flow_ntype_Null) {
            if (!flow_job_node_is_executed(c, job, g, i)) {
                return false;
            }
        }
    }
*/
    return true;
}

<commit_msg>declare a few missing functions<commit_after>use ffi::*;
use libc::{self, int32_t};
use std::ffi::CStr;

macro_rules! error_return (
    ($context:expr) => (
        unsafe {
            flow_context_add_to_callstack($context, concat!(file!(), "\0").as_ptr() as *const libc::c_char,
                line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char);
        }
    );
);

macro_rules! error_msg (
    ($context:expr, $status: expr) => (
        unsafe {
            let c = CStr::from_ptr($crate::ffi::flow_context_set_error_get_message_buffer($context, $status as i32,
                concat!(file!(), "\0").as_ptr() as *const libc::c_char,
                line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char));
            println!("{:?}", c);
        }
    );
    ($context:expr, $status: expr, $format:expr, $($args:expr),*) => (
        let c = CStr::from_ptr($crate::ffi::flow_context_set_error_get_message_buffer($context, $status as i32,
            concat!(file!(), "\0").as_ptr() as *const libc::c_char,
            line!() as i32, concat!(module_path!(), "\0").as_ptr() as *const libc::c_char));
        let formatted = fmt::format(format_args!(concat!($format, "\0"),$($args),*));
        println!("{:?} {}", c, formatted);
    );
);

pub fn job_execute(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool {
  if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
        error_return!(c);
    }
    if !job_link_codecs(c, job, graph_ref) {
        error_return!(c);
    }
    // States for a node
    // New
    // OutboundDimensionsKnown
    // Flattened
    // Optimized
    // LockedForExecution
    // Executed
    let mut passes: libc::int32_t = 0;
    while !flow_job_graph_fully_executed(c, job, unsafe { *graph_ref }) {
        if passes >= unsafe { (*job).max_calc_flatten_execute_passes } {
            error_msg!(c, FlowStatusCode::MaximumGraphPassesExceeded);
            return false;
        }
        if !flow_job_populate_dimensions_where_certain(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_graph_pre_optimize_flatten(c, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_job_populate_dimensions_where_certain(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_graph_optimize(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_job_populate_dimensions_where_certain(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_graph_post_optimize_flatten(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_job_populate_dimensions_where_certain(c, job, graph_ref) {
            error_return!(c);
        }
        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
        if !flow_job_execute_where_certain(c, job, graph_ref) {
            error_return!(c);
        }
        passes += 1;

        if !flow_job_notify_graph_changed(c, job, unsafe { *graph_ref }) {
            error_return!(c);
        }
    }
    if unsafe { (*job).next_graph_version > 0 && (*job).render_last_graph
        && !flow_job_render_graph_to_png(c, job, *graph_ref, (*job).next_graph_version - 1)} {
        error_return!(c);
    }
  true
}

pub fn job_link_codecs(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool {

    if graph_ref.is_null() || unsafe { (*graph_ref).is_null() } {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }
    if !flow_job_notify_graph_changed(c, job, unsafe {*graph_ref}) {
        error_return!(c);
    }

/* FIXME
    struct flow_graph * g = *graph_ref;
    let mut i: int32_t = 0;
    for (i = 0; i < g->next_node_id; i++) {
        if (g->nodes[i].type == flow_ntype_decoder || g->nodes[i].type == flow_ntype_encoder) {
            uint8_t * info_bytes = &g->info_bytes[g->nodes[i].info_byte_index];
            struct flow_nodeinfo_codec * info = (struct flow_nodeinfo_codec *)info_bytes;
            if (info->codec == NULL) {
                info->codec = flow_job_get_codec_instance(c, job, info->placeholder_id);

                if (info->codec == NULL)
                    FLOW_error_msg(c, flow_status_Graph_invalid,
                                   "No matching codec or io found for placeholder id %d (node #%d).",
                                   info->placeholder_id, i);
            }
        }
    }
*/

    return true;
}

fn flow_job_notify_graph_changed(c: *mut Context, job: *mut Job, graph_ref: *mut Graph) -> bool {
/* FIXME
    if (job == NULL || !job->record_graph_versions || job->next_graph_version > FLOW_MAX_GRAPH_VERSIONS)
        return true;

    char filename[255];
    char image_prefix[255];
    char prev_filename[255];

    if (job->next_graph_version == 0) {
        // Delete existing graphs
        int32_t i = 0;
        for (i = 0; i <= FLOW_MAX_GRAPH_VERSIONS; i++) {
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, i);
            remove(filename);
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot.png", job->debug_job_id, i);
            remove(filename);
            flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot.svg", job->debug_job_id, i);
            remove(filename);
            int32_t node_ix = 0;
            for (node_ix = 0; node_ix < 42; node_ix++) {
                flow_snprintf(filename, 254, "./node_frames/job_%d_node_%d.png", job->debug_job_id, node_ix);
                remove(filename);
            }
        }
    }

    int32_t prev_graph_version = job->next_graph_version - 1;
    int32_t current_graph_version = job->next_graph_version;
    job->next_graph_version++;

    flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, current_graph_version);

    flow_snprintf(image_prefix, 254, "./node_frames/job_%d_node_", job->debug_job_id);

    FILE * f = fopen(filename, "w");
    if (f == NULL) {
        FLOW_error_msg(c, flow_status_IO_error, "Failed to open %s for graph dotfile export.", filename);
        return false;
    }
    if (!flow_graph_print_to_dot(c, g, f, image_prefix)) {
        fclose(f);
        FLOW_error_return(c);
    } else {
        fclose(f);
    }
    // Compare
    if (job->next_graph_version > 1) {
        flow_snprintf(prev_filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, prev_graph_version);
        bool identical = false;
        if (!files_identical(c, prev_filename, filename, &identical)) {
            FLOW_error_return(c);
        }
        if (identical) {
            job->next_graph_version--; // Next time we will overwrite the duplicate graph. The last two graphs may
            // remain dupes.
            remove(filename);
        } else if (job->render_graph_versions) {
            flow_job_render_graph_to_png(c, job, g, prev_graph_version);
        }
    }
*/
    return true;
}

pub fn flow_job_graph_fully_executed(c: *mut Context, job: *mut Job, graph_ref: *mut Graph) -> bool
{
/*FIXME
    int32_t i;
    for (i = 0; i < g->next_node_id; i++) {
        if (g->nodes[i].type != flow_ntype_Null) {
            if (!flow_job_node_is_executed(c, job, g, i)) {
                return false;
            }
        }
    }
*/
    return true;
}

pub fn flow_job_populate_dimensions_where_certain(c:*mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool
{
    /*
    // TODO: would be good to verify graph is acyclic.
    if (!flow_graph_walk_dependency_wise(c, job, graph_ref, node_visitor_dimensions, NULL, (void *)false)) {
        FLOW_error_return(c);
    }
    */
    return true;
}

pub fn flow_graph_pre_optimize_flatten(c: *mut Context, graph_ref: *mut *mut Graph) -> bool
{
    if unsafe {(*graph_ref).is_null()} {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }
    /*FIXME
    bool re_walk;
    do {
        re_walk = false;
        if (!flow_graph_walk_dependency_wise(c, NULL, graph_ref, node_visitor_flatten, NULL, &re_walk)) {
            FLOW_error_return(c);
        }
    } while (re_walk);
    */
    return true;
}

pub fn flow_graph_optimize(c: *mut Context,job: *mut Job, graph_ref: *mut *mut Graph) -> bool
{
    if unsafe { (*graph_ref).is_null()} {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }
    /*FIXME
    bool re_walk;
    do {
        re_walk = false;
        if (!flow_graph_walk(c, job, graph_ref, node_visitor_optimize, NULL, &re_walk)) {
            FLOW_error_return(c);
        }
    } while (re_walk);
    */
    return true;
}

pub fn flow_graph_post_optimize_flatten(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool
{
    if unsafe { (*graph_ref).is_null()} {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }

    /*FIXME
    bool re_walk;
    do {
        re_walk = false;
        if (!flow_graph_walk(c, job, graph_ref, node_visitor_post_optimize_flatten, NULL, &re_walk)) {
            FLOW_error_return(c);
        }
    } while (re_walk);
    */
    return true;
}

pub fn flow_job_execute_where_certain(c: *mut Context, job: *mut Job, graph_ref: *mut *mut Graph) -> bool
{
    if unsafe { (*graph_ref).is_null()} {
        error_msg!(c, FlowStatusCode::NullArgument);
        return false;
    }

    //    //Resets and creates state tracking for this graph
    //    if (!flow_job_create_state(c,job, *g)){
    //        FLOW_error_return(c);
    //    }

    /*FIXME
    if (!flow_graph_walk_dependency_wise(c, job, graph_ref, node_visitor_execute, NULL, NULL)) {
        FLOW_error_return(c);
    }
    */
    return true;
}

pub fn flow_job_render_graph_to_png(c: *mut Context, job: *mut Job, g: *mut Graph, graph_version: int32_t) -> bool
{
/*FIXME
    char filename[255];
    flow_snprintf(filename, 254, "job_%d_graph_version_%d.dot", job->debug_job_id, graph_version);

    char dotfile_command[2048];
    flow_snprintf(dotfile_command, 2048, "dot -Tpng -Gsize=11,16\\! -Gdpi=150  -O %s", filename);
    int32_t ignore = system(dotfile_command);
    ignore++;
*/
    return true;
}

/* FIXME
static bool node_visitor_post_optimize_flatten(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref,
                                               int32_t node_id, bool * quit, bool * skip_outbound_paths,
                                               void * custom_data)
{

    if (!flow_node_update_state(c, *graph_ref, node_id)) {
        FLOW_error_return(c);
    }
    struct flow_node * n = &(*graph_ref)->nodes[node_id];

    // If input nodes are populated
    if (n->state == flow_node_state_ReadyForPostOptimizeFlatten) {
        if (!flow_node_post_optimize_flatten(c, graph_ref, node_id)) {
            FLOW_error_return(c);
        }
        if (!flow_graph_validate(c, *graph_ref)) {
            FLOW_error_return(c);
        }
        *quit = true;
        *((bool *)custom_data) = true;
    } else if ((n->state & flow_node_state_InputDimensionsKnown) == 0) {
        // we can't flatten past missing dimensions
        *skip_outbound_paths = true;
    }
    return true;
}

static bool node_visitor_optimize(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref, int32_t node_id,
                                  bool * quit, bool * skip_outbound_paths, void * custom_data)
{

    struct flow_node * node = &(*graph_ref)->nodes[node_id];
    if (node->state == flow_node_state_ReadyForOptimize) {
        node->state = (flow_node_state)(node->state | flow_node_state_Optimized);
    }

    // Implement optimizations
    return true;
}

static bool flow_job_populate_dimensions_for_node(flow_c * c, struct flow_job * job, struct flow_graph * g,
                                                  int32_t node_id, bool force_estimate)
{
    uint64_t now = flow_get_high_precision_ticks();

    if (!flow_node_populate_dimensions(c, g, node_id, force_estimate)) {
        FLOW_error_return(c);
    }
    g->nodes[node_id].ticks_elapsed += (int32_t)(flow_get_high_precision_ticks() - now);
    return true;
}

bool flow_node_has_dimensions(flow_c * c, struct flow_graph * g, int32_t node_id)
{
    struct flow_node * n = &g->nodes[node_id];
    return n->result_width > 0;
}

bool flow_node_inputs_have_dimensions(flow_c * c, struct flow_graph * g, int32_t node_id)
{
    int32_t i;
    for (i = 0; i < g->next_edge_id; i++) {
        if (g->edges[i].type != flow_edgetype_null && g->edges[i].to == node_id) {
            if (!flow_node_has_dimensions(c, g, g->edges[i].from)) {
                return false;
            }
        }
    }
    return true;
}

static bool node_visitor_dimensions(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref, int32_t node_id,
                                    bool * quit, bool * skip_outbound_paths, void * custom_data)
{

    struct flow_node * n = &(*graph_ref)->nodes[node_id];

    int32_t outbound_edges = flow_graph_get_edge_count(c, *graph_ref, node_id, false, flow_edgetype_null, false, true);
    if (outbound_edges == 0) {
        return true; // Endpoint node - no need.
    }
    if (!flow_node_has_dimensions(c, *graph_ref, node_id)) {
        if (!flow_node_update_state(c, *graph_ref, node_id)) {
            FLOW_error_return(c);
        }

        // If input nodes are populated
        if ((n->state & flow_node_state_InputDimensionsKnown) > 0) {
            if (!flow_job_populate_dimensions_for_node(c, job, *graph_ref, node_id, (bool)custom_data)) {
                FLOW_error_return(c);
            }
        }
        if (!flow_node_has_dimensions(c, *graph_ref, node_id)) {
            // We couldn't populate this edge, so we sure can't populate others in this direction.
            // Stop this branch of recursion
            *skip_outbound_paths = true;
        } else {
            flow_job_notify_graph_changed(c, job, *graph_ref);
        }
    }
    return true;
}

bool flow_job_force_populate_dimensions(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref)
{
    // TODO: would be good to verify graph is acyclic.
    if (!flow_graph_walk(c, job, graph_ref, node_visitor_dimensions, NULL, (void *)true)) {
        FLOW_error_return(c);
    }
    return true;
}

static bool flow_job_node_is_executed(flow_c * c, struct flow_job * job, struct flow_graph * g, int32_t node_id)
{
    return (g->nodes[node_id].state & flow_node_state_Executed) > 0;
}
*/

/*FIXME
static bool node_visitor_execute(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref, int32_t node_id,
                                 bool * quit, bool * skip_outbound_paths, void * custom_data)
{

    if (!flow_node_update_state(c, *graph_ref, node_id)) {
        FLOW_error_return(c);
    }
    struct flow_node * n = &(*graph_ref)->nodes[node_id];

    if (!flow_job_node_is_executed(c, job, *graph_ref, node_id) && n->state == flow_node_state_ReadyForExecution) {
        uint64_t now = flow_get_high_precision_ticks();
        if (!flow_node_execute(c, job, *graph_ref, node_id)) {
            FLOW_error_return(c);
        } else {
            (*graph_ref)->nodes[node_id].ticks_elapsed += (int32_t)(flow_get_high_precision_ticks() - now);
            n->state = (flow_node_state)(n->state | flow_node_state_Executed);
            flow_job_notify_node_complete(c, job, *graph_ref, node_id);
        }
    }
    if (!flow_job_node_is_executed(c, job, *graph_ref, node_id)) {
        // If we couldn't complete this node yet, end this branch.
        *skip_outbound_paths = true;
    } else {
        flow_job_notify_graph_changed(c, job, *graph_ref);
    }
    return true;
}

// if no hits, search forward

static bool node_visitor_flatten(flow_c * c, struct flow_job * job, struct flow_graph ** graph_ref, int32_t node_id,
                                 bool * quit, bool * skip_outbound_paths, void * custom_data)
{

    if (!flow_node_update_state(c, *graph_ref, node_id)) {
        FLOW_error_return(c);
    }
    struct flow_node * n = &(*graph_ref)->nodes[node_id];

    // If input nodes are populated
    if (n->state == flow_node_state_ReadyForPreOptimizeFlatten) {
        if (!flow_node_pre_optimize_flatten(c, graph_ref, node_id)) {
            FLOW_error_return(c);
        }
        *quit = true;
        *((bool *)custom_data) = true;
    } else if ((n->state & flow_node_state_InputDimensionsKnown) == 0) {
        // we can't flatten past missing dimensions
        *skip_outbound_paths = true;
    }
    return true;
}

*/
<|endoftext|>


<commit_before>use crate::errors::*;
use aes::{chunks_count, BLOCK_SIZE};
use std;

use crate::prefix_suffix_oracles::Oracle12;
use crate::prefix_suffix_oracles::{DeterministicOracle, Oracle};

use super::challenge11::uses_ecb;

pub fn block_size<T: Oracle>(oracle: &T) -> Result<usize> {
    let mut input = Vec::new();
    let initial_len = oracle.encrypt(&input)?.len();
    loop {
        input.push(0);
        let len = oracle.encrypt(&input)?.len();
        if initial_len != len {
            return Ok(len - initial_len);
        }
    }
}

fn uses_padding<T: Oracle>(oracle: &T) -> Result<bool> {
    Ok((oracle.encrypt(&[0])?.len() - oracle.encrypt(&[])?.len()) % BLOCK_SIZE == 0)
}

pub fn prefix_plus_suffix_length<T: Oracle>(oracle: &T) -> Result<usize> {
    let initial = oracle.encrypt(&[])?.len();
    if !uses_padding(oracle)? {
        return Ok(initial);
    }

    let input = [0; BLOCK_SIZE];
    if let Some(index) = (1..=BLOCK_SIZE).find(|&i| {
        if let Ok(ciphertext) = oracle.encrypt(&input[..i]) {
            initial != ciphertext.len()
        } else {
            // Should never happen
            false
        }
    }) {
        Ok(initial - index)
    } else {
        Err(
            "length of oracle output did not change, something is wrong with the provided oracle"
                .into(),
        )
    }
}

// For an oracle prepending prefix and appending suffix to its input, this function returns
// prefix.len()/BLOCK_SIZE, that is the number of blocks fully occupied by the prefix.
//
// To determine this number, we pass two different cleartexts to the oracle and count the number
// of identical blocks at the start of the corresponding ciphertexts.

fn full_prefix_blocks_count<T: DeterministicOracle>(oracle: &T) -> Result<usize> {
    if let Some(result) = oracle
        .encrypt(&[0])?
        .chunks(BLOCK_SIZE)
        .zip(oracle.encrypt(&[1])?.chunks(BLOCK_SIZE))
        .position(|(x, y)| x != y)
    {
        Ok(result)
    } else {
        Err(
            "no differing blocks found, something is wrong with the provided oracle".into(),
        )
    }
}

// We look at the first block C not fully occupied by the prefix and fill it with a
// constant block B, say consisting of 0's.
// This part of the cleartext in oracle looks as follows:
//
//                               <------ B ------->
// prefix[?] prefix[?] prefix[?] 0 0 ... 0 || 0 0 0 suffix[0] suffix[1]
// <---------- C ------------------------>
//
// We then successively reduce the length of B until the ciphertext of C
// changes. This happens as soon as the cleartext in oracle looks as follows:
//
//                               <-- B -->
// prefix[?] prefix[?] prefix[?] 0 0 ... 0 suffix[0] || suffix[1]
// <---------- C ---------------------------------->
//
// This gives us the length of the prefix in C.
//
// We need to do this with two different constants because suffix[0] might accidentally
// coincide with the constant we have chosen.

pub fn prefix_length<T: DeterministicOracle>(oracle: &T) -> Result<usize> {
    let offset = full_prefix_blocks_count(oracle)? * BLOCK_SIZE;
    let helper = |k: u8| -> Result<usize> {
        let constant_block = vec![k; BLOCK_SIZE];
        let initial = &oracle.encrypt(&constant_block)?[offset..(offset + BLOCK_SIZE)];
        for i in 0..BLOCK_SIZE {
            let cur = oracle.encrypt(&constant_block[i + 1..])?;
            if cur.len() < offset + BLOCK_SIZE || initial != &cur[offset..(offset + BLOCK_SIZE)] {
                return Ok(i);
            }
        }
        Ok(BLOCK_SIZE)
    };

    Ok(offset + std::cmp::min(helper(0)?, helper(1)?))
}

pub fn prefix_and_suffix_length<T: DeterministicOracle>(oracle: &T) -> Result<(usize, usize)> {
    let prefix_len = prefix_length(oracle)?;
    let suffix_len = prefix_plus_suffix_length(oracle)? - prefix_len;
    Ok((prefix_len, suffix_len))
}

pub fn decrypt_suffix<T: DeterministicOracle>(oracle: &T) -> Result<Vec<u8>> {
    // The following input is chosen in such a way that the cleartext in oracle looks as follows:
    //
    //            input start      input end
    //                ↓                ↓
    // <-- prefix --> 0 ... 0 || 0 ... 0 suffix[0] || suffix[1] ...
    //                ↑          ↑
    //            prefix_len  prefix_chunks_count*BLOCK_SIZE
    //
    // The resulting ciphertext is compared to oracle([input, u]). The u yielding a match is
    // equal to suffix[0].

    let (prefix_len, suffix_len) = prefix_and_suffix_length(oracle)?;
    let (prefix_chunks_count, prefix_fill_len) = chunks_count(prefix_len);

    let mut suffix = Vec::with_capacity(suffix_len);

    let mut input = vec![0; prefix_fill_len + BLOCK_SIZE - 1];
    let reference_ciphertexts = (0..BLOCK_SIZE)
        .map(|left_shift| oracle.encrypt(&input[left_shift..]))
        .collect::<Result<Vec<Vec<u8>>>>()?;

    for i in 0..suffix_len {
        let block_index = prefix_chunks_count + i / BLOCK_SIZE;
        let left_shift = i % BLOCK_SIZE;
        for u in 0u8..=255 {
            input.push(u);
            if reference_ciphertexts[left_shift]
                [block_index * BLOCK_SIZE..(block_index + 1) * BLOCK_SIZE]
                == oracle.encrypt(&input[left_shift..])?
                    [block_index * BLOCK_SIZE..(block_index + 1) * BLOCK_SIZE]
            {
                suffix.push(u);
                break;
            }
            input.pop();
        }
    }
    Ok(suffix)
}

pub fn run() -> Result<()> {
    let oracle = Oracle12::new()?;
    if block_size(&oracle)? != BLOCK_SIZE {
        return Err("oracle does not use expected block size".into());
    }

    if !(uses_ecb(&oracle, 0)?) {
        return Err("oracle does not use ECB".into());
    }

    oracle.verify_suffix(&decrypt_suffix(&oracle)?)
}
<commit_msg>Format<commit_after>use crate::errors::*;
use aes::{chunks_count, BLOCK_SIZE};
use std;

use crate::prefix_suffix_oracles::Oracle12;
use crate::prefix_suffix_oracles::{DeterministicOracle, Oracle};

use super::challenge11::uses_ecb;

pub fn block_size<T: Oracle>(oracle: &T) -> Result<usize> {
    let mut input = Vec::new();
    let initial_len = oracle.encrypt(&input)?.len();
    loop {
        input.push(0);
        let len = oracle.encrypt(&input)?.len();
        if initial_len != len {
            return Ok(len - initial_len);
        }
    }
}

fn uses_padding<T: Oracle>(oracle: &T) -> Result<bool> {
    Ok((oracle.encrypt(&[0])?.len() - oracle.encrypt(&[])?.len()) % BLOCK_SIZE == 0)
}

pub fn prefix_plus_suffix_length<T: Oracle>(oracle: &T) -> Result<usize> {
    let initial = oracle.encrypt(&[])?.len();
    if !uses_padding(oracle)? {
        return Ok(initial);
    }

    let input = [0; BLOCK_SIZE];
    if let Some(index) = (1..=BLOCK_SIZE).find(|&i| {
        if let Ok(ciphertext) = oracle.encrypt(&input[..i]) {
            initial != ciphertext.len()
        } else {
            // Should never happen
            false
        }
    }) {
        Ok(initial - index)
    } else {
        Err(
            "length of oracle output did not change, something is wrong with the provided oracle"
                .into(),
        )
    }
}

// For an oracle prepending prefix and appending suffix to its input, this function returns
// prefix.len()/BLOCK_SIZE, that is the number of blocks fully occupied by the prefix.
//
// To determine this number, we pass two different cleartexts to the oracle and count the number
// of identical blocks at the start of the corresponding ciphertexts.

fn full_prefix_blocks_count<T: DeterministicOracle>(oracle: &T) -> Result<usize> {
    if let Some(result) = oracle
        .encrypt(&[0])?
        .chunks(BLOCK_SIZE)
        .zip(oracle.encrypt(&[1])?.chunks(BLOCK_SIZE))
        .position(|(x, y)| x != y)
    {
        Ok(result)
    } else {
        Err("no differing blocks found, something is wrong with the provided oracle".into())
    }
}

// We look at the first block C not fully occupied by the prefix and fill it with a
// constant block B, say consisting of 0's.
// This part of the cleartext in oracle looks as follows:
//
//                               <------ B ------->
// prefix[?] prefix[?] prefix[?] 0 0 ... 0 || 0 0 0 suffix[0] suffix[1]
// <---------- C ------------------------>
//
// We then successively reduce the length of B until the ciphertext of C
// changes. This happens as soon as the cleartext in oracle looks as follows:
//
//                               <-- B -->
// prefix[?] prefix[?] prefix[?] 0 0 ... 0 suffix[0] || suffix[1]
// <---------- C ---------------------------------->
//
// This gives us the length of the prefix in C.
//
// We need to do this with two different constants because suffix[0] might accidentally
// coincide with the constant we have chosen.

pub fn prefix_length<T: DeterministicOracle>(oracle: &T) -> Result<usize> {
    let offset = full_prefix_blocks_count(oracle)? * BLOCK_SIZE;
    let helper = |k: u8| -> Result<usize> {
        let constant_block = vec![k; BLOCK_SIZE];
        let initial = &oracle.encrypt(&constant_block)?[offset..(offset + BLOCK_SIZE)];
        for i in 0..BLOCK_SIZE {
            let cur = oracle.encrypt(&constant_block[i + 1..])?;
            if cur.len() < offset + BLOCK_SIZE || initial != &cur[offset..(offset + BLOCK_SIZE)] {
                return Ok(i);
            }
        }
        Ok(BLOCK_SIZE)
    };

    Ok(offset + std::cmp::min(helper(0)?, helper(1)?))
}

pub fn prefix_and_suffix_length<T: DeterministicOracle>(oracle: &T) -> Result<(usize, usize)> {
    let prefix_len = prefix_length(oracle)?;
    let suffix_len = prefix_plus_suffix_length(oracle)? - prefix_len;
    Ok((prefix_len, suffix_len))
}

pub fn decrypt_suffix<T: DeterministicOracle>(oracle: &T) -> Result<Vec<u8>> {
    // The following input is chosen in such a way that the cleartext in oracle looks as follows:
    //
    //            input start      input end
    //                ↓                ↓
    // <-- prefix --> 0 ... 0 || 0 ... 0 suffix[0] || suffix[1] ...
    //                ↑          ↑
    //            prefix_len  prefix_chunks_count*BLOCK_SIZE
    //
    // The resulting ciphertext is compared to oracle([input, u]). The u yielding a match is
    // equal to suffix[0].

    let (prefix_len, suffix_len) = prefix_and_suffix_length(oracle)?;
    let (prefix_chunks_count, prefix_fill_len) = chunks_count(prefix_len);

    let mut suffix = Vec::with_capacity(suffix_len);

    let mut input = vec![0; prefix_fill_len + BLOCK_SIZE - 1];
    let reference_ciphertexts = (0..BLOCK_SIZE)
        .map(|left_shift| oracle.encrypt(&input[left_shift..]))
        .collect::<Result<Vec<Vec<u8>>>>()?;

    for i in 0..suffix_len {
        let block_index = prefix_chunks_count + i / BLOCK_SIZE;
        let left_shift = i % BLOCK_SIZE;
        for u in 0u8..=255 {
            input.push(u);
            if reference_ciphertexts[left_shift]
                [block_index * BLOCK_SIZE..(block_index + 1) * BLOCK_SIZE]
                == oracle.encrypt(&input[left_shift..])?
                    [block_index * BLOCK_SIZE..(block_index + 1) * BLOCK_SIZE]
            {
                suffix.push(u);
                break;
            }
            input.pop();
        }
    }
    Ok(suffix)
}

pub fn run() -> Result<()> {
    let oracle = Oracle12::new()?;
    if block_size(&oracle)? != BLOCK_SIZE {
        return Err("oracle does not use expected block size".into());
    }

    if !(uses_ecb(&oracle, 0)?) {
        return Err("oracle does not use ECB".into());
    }

    oracle.verify_suffix(&decrypt_suffix(&oracle)?)
}
<|endoftext|>


<commit_before>use errors::*;

use rsa::Rsa;

use bignum::OpensslBigNum as BigNum;
use bignum::{BigNumExt, BigNumTrait};

use sha1;

const BITS: usize = 1024;

struct Server {
    rsa: Rsa<BigNum>
}

fn get_hash(message: &[u8]) -> Vec<u8> {
    let mut sha1 = sha1::Sha1::new();
    sha1.update(message);
    sha1.digest().bytes().to_vec()
}

impl Server {
    fn new() -> Self {
        Server { rsa: Rsa::generate(BITS) }
    }

    fn n(&self) -> &BigNum {
        &self.rsa.n()
    }

    fn verify_signature(&self, message: &[u8], signature: &[u8]) -> bool {
        let rsa = &self.rsa;
        let n = rsa.n();
        let signature_num = &BigNum::from_bytes_be(signature);
        if signature_num >= n {
            return false;
        }

        let plaintext = rsa.encrypt(signature_num).to_bytes_be();

        // Coming from a BigNum, the plaintext does not include any leading zeroes.
        // We therefore check that the length is one less than the length of n.
        if plaintext.len() != n.bytes() - 1 {
            return false;
        }

        // Verify that plaintext *starts with* (this is the flaw)
        // 01 || ff || ff || ... || ff || 00 || hash

        if plaintext[0] != 1 {
            return false;
        }

        let mut i = 1;
        while i < plaintext.len() && plaintext[i] == 255 {
            i += 1;
        }

        if i >= plaintext.len() || plaintext[i] != 0 {
            return false;
        }
        i += 1;

        let hash = get_hash(message);
        if i + hash.len() > plaintext.len() {
            return false;
        }

        plaintext[i..i + hash.len()] == hash[..]
    }

    // Not really required for the exercise
    fn sign_message(&self, message: &[u8]) -> Vec<u8> {
        let hash = get_hash(message);
        let len = self.rsa.n().bytes() - 1;
        let mut plaintext = Vec::with_capacity(len);
        plaintext.push(1);
        for _ in 1..len - 1 - hash.len() {
            plaintext.push(255);
        }
        plaintext.push(0);
        plaintext.extend_from_slice(&hash);
        self.rsa.decrypt(&BigNum::from_bytes_be(&plaintext)).to_bytes_be()
    }
}

 /* We first prove a general observation concerning third roots of natural numbers.
  * Let k = 2^l be a positive natural number which is a power of two.
  * Let x be some positive natural number.
  *
  * Denote by crt the cube root function on positive real numbers. Assume that
  * (1) floor( crt((x + 1)k - 1) ) < crt(xk).
  * As y - 1 < floor(y) for any real number r, we have
  * crt((x + 1)k - 1) < crt(xk) + 1.
  * Taking  the third power yields
  * (x + 1)k - 1 < xk + 3*crt(xk) + 3*crt(xk)^2 + 1,
  * which simplifies to
  * (2) k < 3*crt(xk) + 3*crt(xk)^2 + 2.
  *
  * We now determine an upper bound for the right hand side of (2).
  * As crt(xk) >= 1, we have
  * 3*crt(xk) + 3*crt(xk)^2 + 2 <= 3*crt(xk)^2 + 3*crt(xk)^2 + 2*crt(xk)^2 = 8*crt(xk)^2.
  * Denote by y a natural number such that x <= 2^y. Then
  * 8*crt(xk)^2 <= 2^(2(l + y)/3 + 3).
  *
  * Combining this bound with (2) yields
  * 2^l <= 2^(2(l + y)/3 + 3), or (l - 9)/2 <= y.
  *
  * Reversing the implication, we find that if y < (l - 9)/2, then (1) cannot hold, i.e.
  * (3) floor( crt((x + 1)k - 1) ) >= crt(xk).
  *
  * Finally, note that (3) is equivalent to the existence of a natural number r with
  * xk <= r^3 <= (x + 1)k - 1, as floor( crt((x + 1)k - 1) ) is the biggest natural number
  * r with r^3 <= (x + 1)k - 1.
  *
  * Summarizing: If x <= 2^y for some natural number y < (l - 9)/2, then there is a natural
  * number r with x2^l <= r^3 <= (x + 1)2^l - 1. */

fn forge_signature(len: usize, message: &[u8]) -> Vec<u8> {
    let hash = &get_hash(message);

    /* Search for a plaintext of length `len` of the form
     * (F) 01 || ff || ff || ... || ff || 00 || hash || *
     * which has a third root in the natural numbers.
     *
     * In fact we can always achieve this without any ff bytes in the prefix.
     * Interpret
     * 01 || 00 || hash
     * as a big-endian number x. The length of x in bytes is 2 + hash.len() and we have
     * x <= 2^(8*(2 + hash.len())). Let l = len - 2 - hash.len() be the number
     * of bytes we can fill arbitrarily. Then the numbers of the form (F) above
     * (in big-endian) are precisely the natural numbers between
     * x2^l and (x + 1)2^l - 1. As 8*(2 + hash.len()) is small compared to l, we
     * know by the general observations above that floor( crt((x + 1)k - 1) )
     * is a signature which will fool the server.
     *
     * Note that we can just as easily forge a signature with several ff bytes in the prefix
     * as long as 8*(2 + hash.len() + number of ff bytes) < (l - 9)/2.
     * */

    let x = BigNum::from_bytes_be(&{
        let mut v = Vec::with_capacity(2 + hash.len());
        v.push(1);
        v.push(0);
        v.extend_from_slice(hash);
        v
    });
    let l = len - 2 - hash.len() as usize;
    let _1 = BigNum::from_u32(1);
    let r = (&(&x + &_1).lsh(8 * l) - &_1).root(3).0;
    r.to_bytes_be()
}

pub fn run() -> Result<(), Error> {
    let server = Server::new();
    {
        // Make sure that our server accepts valid signatures
        let message = &b"foo"[..];
        let signature = server.sign_message(message);
        compare_eq(true, server.verify_signature(message, &signature))?;
    }

    // Now we forge a signature for the following message
    let message = &b"hi mom"[..];
    let len = server.n().bytes() - 1;
    let forged_signature = forge_signature(len, message);

    compare_eq(true, server.verify_signature(message, &forged_signature))
}
<commit_msg>Fix name<commit_after>use errors::*;

use rsa::Rsa;

use bignum::OpensslBigNum as BigNum;
use bignum::{BigNumExt, BigNumTrait};

use sha1;

const BITS: usize = 1024;

struct Server {
    rsa: Rsa<BigNum>
}

fn get_hash(message: &[u8]) -> Vec<u8> {
    let mut sha1 = sha1::Sha1::new();
    sha1.update(message);
    sha1.digest().bytes().to_vec()
}

impl Server {
    fn new() -> Self {
        Server { rsa: Rsa::generate(BITS) }
    }

    fn n(&self) -> &BigNum {
        &self.rsa.n()
    }

    fn verify_signature(&self, message: &[u8], signature: &[u8]) -> bool {
        let rsa = &self.rsa;
        let n = rsa.n();
        let signature_num = &BigNum::from_bytes_be(signature);
        if signature_num >= n {
            return false;
        }

        let plaintext = rsa.encrypt(signature_num).to_bytes_be();

        // Coming from a BigNum, the plaintext does not include any leading zeroes.
        // We therefore check that the length is one less than the length of n.
        if plaintext.len() != n.bytes() - 1 {
            return false;
        }

        // Verify that plaintext *starts with* (this is the flaw)
        // 01 || ff || ff || ... || ff || 00 || hash

        if plaintext[0] != 1 {
            return false;
        }

        let mut i = 1;
        while i < plaintext.len() && plaintext[i] == 255 {
            i += 1;
        }

        if i >= plaintext.len() || plaintext[i] != 0 {
            return false;
        }
        i += 1;

        let hash = get_hash(message);
        if i + hash.len() > plaintext.len() {
            return false;
        }

        plaintext[i..i + hash.len()] == hash[..]
    }

    // Not really required for the exercise
    fn sign_message(&self, message: &[u8]) -> Vec<u8> {
        let hash = get_hash(message);
        let len = self.rsa.n().bytes() - 1;
        let mut plaintext = Vec::with_capacity(len);
        plaintext.push(1);
        for _ in 1..len - 1 - hash.len() {
            plaintext.push(255);
        }
        plaintext.push(0);
        plaintext.extend_from_slice(&hash);
        self.rsa.decrypt(&BigNum::from_bytes_be(&plaintext)).to_bytes_be()
    }
}

 /* We first prove a general observation concerning third roots of natural numbers.
  * Let k = 2^l be a positive natural number which is a power of two.
  * Let x be some positive natural number.
  *
  * Denote by crt the cube root function on positive real numbers. Assume that
  * (1) floor( crt((x + 1)k - 1) ) < crt(xk).
  * As y - 1 < floor(y) for any real number r, we have
  * crt((x + 1)k - 1) < crt(xk) + 1.
  * Taking  the third power yields
  * (x + 1)k - 1 < xk + 3*crt(xk) + 3*crt(xk)^2 + 1,
  * which simplifies to
  * (2) k < 3*crt(xk) + 3*crt(xk)^2 + 2.
  *
  * We now determine an upper bound for the right hand side of (2).
  * As crt(xk) >= 1, we have
  * 3*crt(xk) + 3*crt(xk)^2 + 2 <= 3*crt(xk)^2 + 3*crt(xk)^2 + 2*crt(xk)^2 = 8*crt(xk)^2.
  * Denote by y a natural number such that x <= 2^y. Then
  * 8*crt(xk)^2 <= 2^(2(l + y)/3 + 3).
  *
  * Combining this bound with (2) yields
  * 2^l <= 2^(2(l + y)/3 + 3), or (l - 9)/2 <= y.
  *
  * Reversing the implication, we find that if y < (l - 9)/2, then (1) cannot hold, i.e.
  * (3) floor( crt((x + 1)k - 1) ) >= crt(xk).
  *
  * Finally, note that (3) is equivalent to the existence of a natural number r with
  * xk <= r^3 <= (x + 1)k - 1, as floor( crt((x + 1)k - 1) ) is the biggest natural number
  * r with r^3 <= (x + 1)k - 1.
  *
  * Summarizing: If x <= 2^y for some natural number y < (l - 9)/2, then there is a natural
  * number r with x2^l <= r^3 <= (x + 1)2^l - 1. */

fn forge_signature(len: usize, message: &[u8]) -> Vec<u8> {
    let hash = &get_hash(message);

    /* Search for a plaintext of length `len` of the form
     * (F) 01 || ff || ff || ... || ff || 00 || hash || *
     * which has a third root in the natural numbers.
     *
     * In fact we can always achieve this without any ff bytes in the prefix.
     * Interpret
     * 01 || 00 || hash
     * as a big-endian number x. The length of x in bytes is 2 + hash.len() and we have
     * x <= 2^(8*(2 + hash.len())). Let l = 8(len - 2 - hash.len()) be the number
     * of bits we can fill arbitrarily. Then the numbers of the form (F) above
     * (in big-endian) are precisely the natural numbers between
     * x2^l and (x + 1)2^l - 1. As 8*(2 + hash.len()) is small compared to l, we
     * know by the general observations above that floor( crt((x + 1)k - 1) )
     * is a signature which will fool the server.
     *
     * Note that we can just as easily forge a signature with several ff bytes in the prefix
     * as long as 8*(2 + hash.len() + number of ff bytes) < (l - 9)/2.
     * */

    let x = BigNum::from_bytes_be(&{
        let mut v = Vec::with_capacity(2 + hash.len());
        v.push(1);
        v.push(0);
        v.extend_from_slice(hash);
        v
    });
    let l = 8 * (len - 2 - hash.len()) as usize;
    let _1 = BigNum::from_u32(1);
    let r = (&(&x + &_1).lsh(l) - &_1).root(3).0;
    r.to_bytes_be()
}

pub fn run() -> Result<(), Error> {
    let server = Server::new();
    {
        // Make sure that our server accepts valid signatures
        let message = &b"foo"[..];
        let signature = server.sign_message(message);
        compare_eq(true, server.verify_signature(message, &signature))?;
    }

    // Now we forge a signature for the following message
    let message = &b"hi mom"[..];
    let len = server.n().bytes() - 1;
    let forged_signature = forge_signature(len, message);

    compare_eq(true, server.verify_signature(message, &forged_signature))
}
<|endoftext|>


<commit_before>use crate::symbol::{sym, Symbol};
use std::fmt;
use std::str::FromStr;

use rustc_macros::HashStable_Generic;

/// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).)
#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
#[derive(HashStable_Generic)]
pub enum Edition {
    // When adding new editions, be sure to do the following:
    //
    // - update the `ALL_EDITIONS` const
    // - update the `EDITION_NAME_LIST` const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
    //
    // Editions *must* be kept in order, oldest to newest.
    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,
    /// The 2021 edition
    Edition2021,
}

// Must be in order from oldest to newest.
pub const ALL_EDITIONS: &[Edition] =
    &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];

pub const EDITION_NAME_LIST: &str = "2015|2018|2021";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2018;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
            Edition::Edition2021 => "2021",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
            Edition::Edition2021 => "rust_2021_compatibility",
        }
    }

    pub fn feature_name(&self) -> Symbol {
        match *self {
            Edition::Edition2015 => sym::rust_2015_preview,
            Edition::Edition2018 => sym::rust_2018_preview,
            Edition::Edition2021 => sym::rust_2021_preview,
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => true,
            Edition::Edition2021 => false,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            "2021" => Ok(Edition::Edition2021),
            _ => Err(()),
        }
    }
}
<commit_msg>make edition 2021 stable<commit_after>use crate::symbol::{sym, Symbol};
use std::fmt;
use std::str::FromStr;

use rustc_macros::HashStable_Generic;

/// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).)
#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
#[derive(HashStable_Generic)]
pub enum Edition {
    // When adding new editions, be sure to do the following:
    //
    // - update the `ALL_EDITIONS` const
    // - update the `EDITION_NAME_LIST` const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
    //
    // Editions *must* be kept in order, oldest to newest.
    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,
    /// The 2021 edition
    Edition2021,
}

// Must be in order from oldest to newest.
pub const ALL_EDITIONS: &[Edition] =
    &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021];

pub const EDITION_NAME_LIST: &str = "2015|2018|2021";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2018;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
            Edition::Edition2021 => "2021",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
            Edition::Edition2021 => "rust_2021_compatibility",
        }
    }

    pub fn feature_name(&self) -> Symbol {
        match *self {
            Edition::Edition2015 => sym::rust_2015_preview,
            Edition::Edition2018 => sym::rust_2018_preview,
            Edition::Edition2021 => sym::rust_2021_preview,
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => true,
            Edition::Edition2021 => true,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            "2021" => Ok(Edition::Edition2021),
            _ => Err(()),
        }
    }
}
<|endoftext|>


<commit_before>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes<B> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<B>,
    }

    impl<B> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(bytes: B) -> Bytes<B> where B: DerefMut<Target=[u8]> {

            let mut rc = Rc::new(bytes);

            Bytes {
                ptr: Rc::get_mut(&mut rc).unwrap().as_mut_ptr(),
                len: rc.len(),
                sequestered: rc,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl<B> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;

    /// A thread-safe byte buffer backed by a shared allocation.
    pub struct Bytes<B> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<B>,
    }

    impl<B> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(bytes: B) -> Bytes<B> where B : DerefMut<Target=[u8]> {

            let mut arc = Arc::new(bytes);

            Bytes {
                ptr: Arc::get_mut(&mut arc).unwrap().as_mut_ptr(),
                len: arc.len(),
                sequestered: arc,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }
    }

    impl<B> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}
<commit_msg>bytes update<commit_after>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover::<Vec<u8>>() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;
    use std::any::Any;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<Box<Any>>,
    }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B: DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Rc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;
    use std::any::Any;

    /// A thread-safe byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<Box<Any>>,
    }

    unsafe impl Send for Bytes { }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B : DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Arc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            // println!("Trying recovery; strong count: {:?}", Arc::strong_count(&self.sequestered));
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}
<|endoftext|>