<commit_before>#![feature(slice_concat_ext)]
#![feature(integer_atomics)]

extern crate imageflow_helpers;
extern crate imageflow_core as fc;
extern crate imageflow_types as s;
use ::imageflow_helpers::preludes::from_std::*;
extern crate hyper;

use std::slice::SliceConcatExt;

extern crate wait_timeout;
use wait_timeout::ChildExt;
use std::time::Duration;
use std::process::{Command, Stdio, Child,Output};

use ::imageflow_helpers::process_testing::*;
use fc::test_helpers::*;
use fc::test_helpers::process_testing::ProcTestContextExtras;
use fc::test_helpers::process_testing::ProcOutputExtras;
use ::imageflow_helpers::fetching::FetchError;
use ::imageflow_helpers::fetching::{fetch_bytes,get_status_code_for};
fn server_path() -> PathBuf{
    let self_path = std::env::current_exe().expect("For --self-test to work, we need to know the binary's location. env::current_exe failed");
    self_path.parent().unwrap().join("imageflow_server")
}

fn get_next_port() -> u16{
    use std::sync::atomic::{AtomicU16, Ordering, ATOMIC_U16_INIT};
    static NEXT_PORT: AtomicU16 = ATOMIC_U16_INIT;

    NEXT_PORT.compare_and_swap(0, 36203, Ordering::SeqCst);
    NEXT_PORT.fetch_add(1, Ordering::SeqCst)
}

struct ServerInstance{
    port: u16,
}

type CallbackResult = std::result::Result<(), ::imageflow_helpers::fetching::FetchError>;
impl ServerInstance{

    fn speaks_http(&self) -> bool{
        self.hello().is_ok()
    }

    fn hello(&self) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for("/hello/are/you/running?"))
    }

    fn url_for(&self, rel_path: &str) -> String{
        format!("http://localhost:{}{}", self.port,rel_path)
    }

    fn get_status(&self, rel_path: &str) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for(rel_path))
    }

    fn request_stop(&self) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for("/test/shutdown"))
    }

    fn run<F>(c: &ProcTestContext, args: Vec<&str>, callback: F) -> (ProcOutput, CallbackResult)
    where F: Fn(&ServerInstance) -> CallbackResult {
        let instance = ServerInstance {
            port: get_next_port()
        };
        // NOTE --bind=localhost::{} (two colons) causes a generic "error:",exit code 1, and no other output. This is bad UX.
        let test_arg = "--integration-test";
        let port_arg = format!("--port={}", instance.port);
        let mut all_args = args.clone();
        all_args.insert(0, test_arg);
        all_args.insert(0, &port_arg);
        all_args.insert(0, "start");

        c.execute_callback(all_args, false,
                           |child: &mut std::process::Child| -> std::result::Result<(), ::imageflow_helpers::fetching::FetchError> {

                               ::std::thread::sleep_ms(10);
                               // Server may not be running
                               instance.hello()?;

                               callback(&instance);

                               let _ = instance.request_stop();
                               Ok(())
                           })
        //po.expect_status_code(Some(0));
    }
}

// ports 36,000 to 39,999 seem the safest.
#[test]
fn run_server_test_i4(){

    let context = ProcTestContext::create_timestamp_subdir_within("server_tests", Some(server_path()));

    {
        let c = context.subfolder_context("basics");
        c.exec("diagnose --show-compilation-info").expect_status_code(Some(0));
        c.exec("--version").expect_status_code(Some(0));
        c.exec("-V").expect_status_code(Some(0));

        //TODO: test diagnose --call-panic (xplat hard)

        //Test incorrect args
        c.execute(vec!["demo"], false, |child: &mut std::process::Child| {
        }).expect_status_code(Some(1));

    }

    {
        let c = context.subfolder_context("demo"); //stuck on port 39876
        c.subfolder_context("demo");
        let (po, callback_result) = ServerInstance::run(&c, vec!["--demo", "--data-dir=."], | server | {
            fetch_bytes(&server.url_for("/ir4/proxy_unsplash/photo-1422493757035-1e5e03968f95?width=100"))?;
            assert_eq!(server.get_status("/ir4/proxy_unsplash/notthere.jpg")?, hyper::status::StatusCode::NotFound);
            Ok(())
        });

        //po.expect_status_code(Some(0));

        callback_result.unwrap();
    }
    {
        let c = context.subfolder_context("mount_local"); //stuck on port 39876
        c.create_blank_image_here("eh", 100,100, s::EncoderPreset::libpng32());
        let (po, callback_result) = ServerInstance::run(&c, vec!["--data-dir=.", "--mount=/local/:ir4_local:./"], | server | {
            let bytes = fetch_bytes(&server.url_for("/local/eh.png?width=100"))?;

            let info = fc::clients::stateless::LibClient {}.get_image_info(&bytes).expect("Image response should be parseable");

            assert_eq!(server.get_status("/local/notthere.jpg")?, hyper::status::StatusCode::NotFound);
            assert_eq!(server.get_status("/notrouted")?, hyper::status::StatusCode::NotFound);
            Ok(())
        });
        //po.expect_status_code(Some(0));

        callback_result.unwrap();
    }
}

trait ProcTestContextHttp{
 fn execute_callback<F,T>(&self, args_vec: Vec<&str>, valgrind_on_signal_death: bool, callback: F) -> (ProcOutput, T)
where F: Fn(&mut std::process::Child) -> T;

}
impl ProcTestContextHttp for ProcTestContext{

    ///
    /// Pass false for valgrind_on_signal_death if your callback might kill the child
    fn execute_callback<F,T>(&self, args_vec: Vec<&str>, valgrind_on_signal_death: bool, callback: F) -> (ProcOutput, T)
        where F: Fn(&mut std::process::Child) -> T {
        //TODO: serialize in a safer way - this isn't correct
        let full_invocation = format!("{} {}", &self.bin_location().to_str().unwrap(), args_vec.join(" "));

        let dir = self.working_dir();
        let exe = self.bin_location();

        let valgrind_copy_result = self.create_valgrind_suppressions();
        let _ = writeln!(&mut std::io::stderr(),
                         "Executing from folder {} with valgrind_suppressions {:?}\n{}",
                         dir.to_str().unwrap(),
                         valgrind_copy_result,
                         full_invocation);
        // change working dir to dir
        let mut cmd = Command::new(exe);
        cmd.args(args_vec.as_slice()).current_dir(dir).env("RUST_BACKTRACE", "1");

        //cmd.stderr(Stdio::piped()).stdout(Stdio::piped());
        cmd.stderr(Stdio::inherit()).stdout(Stdio::inherit());

        let mut child = cmd.spawn().expect("Failed to start?");

        let result = callback(&mut child);

        ///child.kill().unwrap();
        let timeout = Some(Duration::from_secs(1));

        let (status_code, output) = match timeout {
            Some(timeout) => {
                match child.wait_timeout(timeout).unwrap() {
                    Some(status) => (status.code(), None),
                    None => {
                        // child hasn't exited yet
                        child.kill().unwrap();
                        (child.wait().unwrap().code(), None)
                    }
                }
            }
            None => {
                let output: Output = child.wait_with_output().unwrap();
                (output.status.code(), Some(output))
            }
        };

        let _ = writeln!(&mut std::io::stderr(),
                         "exit code {:?}", status_code);

        // Double check we dumped output on segfault
        if status_code == None {
            if let Some(ref out) = output {
                std::io::stderr().write(&out.stderr).unwrap();
                std::io::stdout().write(&out.stdout).unwrap();
            }
            let _ = writeln!(&mut std::io::stderr(),
                             "exit code {:?}", status_code);
        }
        // Killed by signal.
        // 11 Segmentation fault
        // 4 illegal instruction 6 abort 8 floating point error
        if status_code == None && valgrind_on_signal_death {
            if std::env::var("VALGRIND_RUNNING").is_ok() {
                let _ = writeln!(&mut std::io::stderr(),
                                 "VALGRIND_RUNNING defined; skipping valgrind pass");
            } else {
                //ALLOW TO FAIL; valgrind may not be present
                let _ = writeln!(&mut std::io::stderr(),
                                 "Starting valgrind from within self-test:");
                let mut cmd = Command::new("valgrind");
                cmd.arg("-q").arg("--error-exitcode=9").arg(exe);
                cmd.args(args_vec.as_slice()).current_dir(dir).env("RUST_BACKTRACE", "1").env("VALGRIND_RUNNING", "1");

                let _ = writeln!(&mut std::io::stderr(),
                                 "{:?}", cmd);

                let _ = cmd.status(); //.expect("Failed to start valgrind?");
            }
        }

        match output {
            Some(out) => (ProcOutput::from(out), result),
            None => (ProcOutput::from_code(status_code), result)
        }
    }

}<commit_msg>chore(travis): try 500ms to make travis OS X happy<commit_after>#![feature(slice_concat_ext)]
#![feature(integer_atomics)]

extern crate imageflow_helpers;
extern crate imageflow_core as fc;
extern crate imageflow_types as s;
use ::imageflow_helpers::preludes::from_std::*;
extern crate hyper;

use std::slice::SliceConcatExt;

extern crate wait_timeout;
use wait_timeout::ChildExt;
use std::time::Duration;
use std::process::{Command, Stdio, Child,Output};

use ::imageflow_helpers::process_testing::*;
use fc::test_helpers::*;
use fc::test_helpers::process_testing::ProcTestContextExtras;
use fc::test_helpers::process_testing::ProcOutputExtras;
use ::imageflow_helpers::fetching::FetchError;
use ::imageflow_helpers::fetching::{fetch_bytes,get_status_code_for};
fn server_path() -> PathBuf{
    let self_path = std::env::current_exe().expect("For --self-test to work, we need to know the binary's location. env::current_exe failed");
    self_path.parent().unwrap().join("imageflow_server")
}

fn get_next_port() -> u16{
    use std::sync::atomic::{AtomicU16, Ordering, ATOMIC_U16_INIT};
    static NEXT_PORT: AtomicU16 = ATOMIC_U16_INIT;

    NEXT_PORT.compare_and_swap(0, 36203, Ordering::SeqCst);
    NEXT_PORT.fetch_add(1, Ordering::SeqCst)
}

struct ServerInstance{
    port: u16,
}

type CallbackResult = std::result::Result<(), ::imageflow_helpers::fetching::FetchError>;
impl ServerInstance{

    fn speaks_http(&self) -> bool{
        self.hello().is_ok()
    }

    fn hello(&self) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for("/hello/are/you/running?"))
    }

    fn url_for(&self, rel_path: &str) -> String{
        format!("http://localhost:{}{}", self.port,rel_path)
    }

    fn get_status(&self, rel_path: &str) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for(rel_path))
    }

    fn request_stop(&self) -> std::result::Result<hyper::status::StatusCode, FetchError> {
        get_status_code_for(&self.url_for("/test/shutdown"))
    }

    fn run<F>(c: &ProcTestContext, args: Vec<&str>, callback: F) -> (ProcOutput, CallbackResult)
    where F: Fn(&ServerInstance) -> CallbackResult {
        let instance = ServerInstance {
            port: get_next_port()
        };
        // NOTE --bind=localhost::{} (two colons) causes a generic "error:",exit code 1, and no other output. This is bad UX.
        let test_arg = "--integration-test";
        let port_arg = format!("--port={}", instance.port);
        let mut all_args = args.clone();
        all_args.insert(0, test_arg);
        all_args.insert(0, &port_arg);
        all_args.insert(0, "start");

        c.execute_callback(all_args, false,
                           |child: &mut std::process::Child| -> std::result::Result<(), ::imageflow_helpers::fetching::FetchError> {

                               ::std::thread::sleep_ms(500);
                               // Server may not be running
                               instance.hello()?;

                               callback(&instance);

                               let _ = instance.request_stop();
                               Ok(())
                           })
        //po.expect_status_code(Some(0));
    }
}

// ports 36,000 to 39,999 seem the safest.
#[test]
fn run_server_test_i4(){

    let context = ProcTestContext::create_timestamp_subdir_within("server_tests", Some(server_path()));

    {
        let c = context.subfolder_context("basics");
        c.exec("diagnose --show-compilation-info").expect_status_code(Some(0));
        c.exec("--version").expect_status_code(Some(0));
        c.exec("-V").expect_status_code(Some(0));

        //TODO: test diagnose --call-panic (xplat hard)

        //Test incorrect args
        c.execute(vec!["demo"], false, |child: &mut std::process::Child| {
        }).expect_status_code(Some(1));

    }

    {
        let c = context.subfolder_context("demo"); //stuck on port 39876
        c.subfolder_context("demo");
        let (po, callback_result) = ServerInstance::run(&c, vec!["--demo", "--data-dir=."], | server | {
            fetch_bytes(&server.url_for("/ir4/proxy_unsplash/photo-1422493757035-1e5e03968f95?width=100"))?;
            assert_eq!(server.get_status("/ir4/proxy_unsplash/notthere.jpg")?, hyper::status::StatusCode::NotFound);
            Ok(())
        });

        //po.expect_status_code(Some(0));

        callback_result.unwrap();
    }
    {
        let c = context.subfolder_context("mount_local"); //stuck on port 39876
        c.create_blank_image_here("eh", 100,100, s::EncoderPreset::libpng32());
        let (po, callback_result) = ServerInstance::run(&c, vec!["--data-dir=.", "--mount=/local/:ir4_local:./"], | server | {
            let bytes = fetch_bytes(&server.url_for("/local/eh.png?width=100"))?;

            let info = fc::clients::stateless::LibClient {}.get_image_info(&bytes).expect("Image response should be parseable");

            assert_eq!(server.get_status("/local/notthere.jpg")?, hyper::status::StatusCode::NotFound);
            assert_eq!(server.get_status("/notrouted")?, hyper::status::StatusCode::NotFound);
            Ok(())
        });
        //po.expect_status_code(Some(0));

        callback_result.unwrap();
    }
}

trait ProcTestContextHttp{
 fn execute_callback<F,T>(&self, args_vec: Vec<&str>, valgrind_on_signal_death: bool, callback: F) -> (ProcOutput, T)
where F: Fn(&mut std::process::Child) -> T;

}
impl ProcTestContextHttp for ProcTestContext{

    ///
    /// Pass false for valgrind_on_signal_death if your callback might kill the child
    fn execute_callback<F,T>(&self, args_vec: Vec<&str>, valgrind_on_signal_death: bool, callback: F) -> (ProcOutput, T)
        where F: Fn(&mut std::process::Child) -> T {
        //TODO: serialize in a safer way - this isn't correct
        let full_invocation = format!("{} {}", &self.bin_location().to_str().unwrap(), args_vec.join(" "));

        let dir = self.working_dir();
        let exe = self.bin_location();

        let valgrind_copy_result = self.create_valgrind_suppressions();
        let _ = writeln!(&mut std::io::stderr(),
                         "Executing from folder {} with valgrind_suppressions {:?}\n{}",
                         dir.to_str().unwrap(),
                         valgrind_copy_result,
                         full_invocation);
        // change working dir to dir
        let mut cmd = Command::new(exe);
        cmd.args(args_vec.as_slice()).current_dir(dir).env("RUST_BACKTRACE", "1");

        //cmd.stderr(Stdio::piped()).stdout(Stdio::piped());
        cmd.stderr(Stdio::inherit()).stdout(Stdio::inherit());

        let mut child = cmd.spawn().expect("Failed to start?");

        let result = callback(&mut child);

        ///child.kill().unwrap();
        let timeout = Some(Duration::from_secs(1));

        let (status_code, output) = match timeout {
            Some(timeout) => {
                match child.wait_timeout(timeout).unwrap() {
                    Some(status) => (status.code(), None),
                    None => {
                        // child hasn't exited yet
                        child.kill().unwrap();
                        (child.wait().unwrap().code(), None)
                    }
                }
            }
            None => {
                let output: Output = child.wait_with_output().unwrap();
                (output.status.code(), Some(output))
            }
        };

        let _ = writeln!(&mut std::io::stderr(),
                         "exit code {:?}", status_code);

        // Double check we dumped output on segfault
        if status_code == None {
            if let Some(ref out) = output {
                std::io::stderr().write(&out.stderr).unwrap();
                std::io::stdout().write(&out.stdout).unwrap();
            }
            let _ = writeln!(&mut std::io::stderr(),
                             "exit code {:?}", status_code);
        }
        // Killed by signal.
        // 11 Segmentation fault
        // 4 illegal instruction 6 abort 8 floating point error
        if status_code == None && valgrind_on_signal_death {
            if std::env::var("VALGRIND_RUNNING").is_ok() {
                let _ = writeln!(&mut std::io::stderr(),
                                 "VALGRIND_RUNNING defined; skipping valgrind pass");
            } else {
                //ALLOW TO FAIL; valgrind may not be present
                let _ = writeln!(&mut std::io::stderr(),
                                 "Starting valgrind from within self-test:");
                let mut cmd = Command::new("valgrind");
                cmd.arg("-q").arg("--error-exitcode=9").arg(exe);
                cmd.args(args_vec.as_slice()).current_dir(dir).env("RUST_BACKTRACE", "1").env("VALGRIND_RUNNING", "1");

                let _ = writeln!(&mut std::io::stderr(),
                                 "{:?}", cmd);

                let _ = cmd.status(); //.expect("Failed to start valgrind?");
            }
        }

        match output {
            Some(out) => (ProcOutput::from(out), result),
            None => (ProcOutput::from_code(status_code), result)
        }
    }

}<|endoftext|>


<commit_before>//! Support for JPG image decoding.
use snafu::{OptionExt, ResultExt};

use super::{CustomMessageSnafu, CustomSnafu, DecodeError, MissingAttributeSnafu};
use crate::adapters::{DecodeResult, PixelDataObject, PixelRWAdapter};
use jpeg_decoder::Decoder;
use std::io::Cursor;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JPEGAdapter;

impl JPEGAdapter {
    fn encoded_frames(&self, src: &dyn PixelDataObject) -> Result<Vec<Vec<u8>>, DecodeError> {
        // Embedded jpegs can span multiple fragments
        // Create 1:1 mapping between frame and fragment data
        // https://dicom.nema.org/dicom/2013/output/chtml/part05/sect_8.2.html
        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let mut frame_to_fragments: Vec<Vec<u8>> = vec![Vec::new(); nr_frames];
        let fragments = src
            .raw_pixel_data()
            .context(CustomMessageSnafu {
                message: "Expected to have raw pixel data available",
            })?
            .fragments;
        {
            let mut current_frame = 0;
            for fragment in &fragments {
                let mut decoder = Decoder::new(Cursor::new(fragment));
                let info = decoder.read_info();
                let is_new_frame = info.is_ok();
                if is_new_frame {
                    frame_to_fragments[current_frame].extend_from_slice(fragment);
                    current_frame += 1;
                } else if current_frame > 0 {
                    // Not the start of a new frame
                    // try to append to last known frame if already created
                    frame_to_fragments[current_frame - 1].extend_from_slice(fragment);
                } else {
                    // when reading the initial frame we got an error from the decoder
                    info.map_err(|e| Box::new(e) as Box<_>)
                        .context(CustomSnafu)?;
                }
            }
            if current_frame != nr_frames {
                return CustomMessageSnafu {
                    message: "Could not extract expected number of frames from fragments",
                }
                .fail();
            }
        }
        Ok(frame_to_fragments)
    }
}

impl PixelRWAdapter for JPEGAdapter {
    /// Decode DICOM image data with jpeg encoding.

    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src
            .cols()
            .context(MissingAttributeSnafu { name: "Columns" })?;
        let rows = src.rows().context(MissingAttributeSnafu { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttributeSnafu {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttributeSnafu {
            name: "BitsAllocated",
        })?;

        if bits_allocated != 8 && bits_allocated != 16 {
            return CustomMessageSnafu {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail();
        }

        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let bytes_per_sample = bits_allocated / 8;
        let encoded_frames = self.encoded_frames(src)?;

        // `stride` it the total number of bytes for each sample plane
        let stride: usize = (bytes_per_sample as usize * cols as usize * rows as usize).into();
        dst.resize((samples_per_pixel as usize * stride) * nr_frames, 0);

        let mut offset = 0;
        for frame in encoded_frames {
            let mut decoder = Decoder::new(Cursor::new(frame));

            let decoded = decoder
                .decode()
                .map_err(|e| Box::new(e) as Box<_>)
                .context(CustomSnafu)?;

            let decoded_len = decoded.len();
            dst[offset..(offset + decoded_len)].copy_from_slice(&decoded);
            offset += decoded_len
        }
        Ok(())
    }
}
<commit_msg>Fix warning issues by clippy<commit_after>//! Support for JPG image decoding.
use snafu::{OptionExt, ResultExt};

use super::{CustomMessageSnafu, CustomSnafu, DecodeError, MissingAttributeSnafu};
use crate::adapters::{DecodeResult, PixelDataObject, PixelRWAdapter};
use jpeg_decoder::Decoder;
use std::io::Cursor;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JPEGAdapter;

impl JPEGAdapter {
    fn encoded_frames(&self, src: &dyn PixelDataObject) -> Result<Vec<Vec<u8>>, DecodeError> {
        // Embedded jpegs can span multiple fragments
        // Create 1:1 mapping between frame and fragment data
        // https://dicom.nema.org/dicom/2013/output/chtml/part05/sect_8.2.html
        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let mut frame_to_fragments: Vec<Vec<u8>> = vec![Vec::new(); nr_frames];
        let fragments = src
            .raw_pixel_data()
            .context(CustomMessageSnafu {
                message: "Expected to have raw pixel data available",
            })?
            .fragments;
        {
            let mut current_frame = 0;
            for fragment in &fragments {
                let mut decoder = Decoder::new(Cursor::new(fragment));
                let info = decoder.read_info();
                let is_new_frame = info.is_ok();
                if is_new_frame {
                    frame_to_fragments[current_frame].extend_from_slice(fragment);
                    current_frame += 1;
                } else if current_frame > 0 {
                    // Not the start of a new frame
                    // try to append to last known frame if already created
                    frame_to_fragments[current_frame - 1].extend_from_slice(fragment);
                } else {
                    // when reading the initial frame we got an error from the decoder
                    info.map_err(|e| Box::new(e) as Box<_>)
                        .context(CustomSnafu)?;
                }
            }
            if current_frame != nr_frames {
                return CustomMessageSnafu {
                    message: "Could not extract expected number of frames from fragments",
                }
                .fail();
            }
        }
        Ok(frame_to_fragments)
    }
}

impl PixelRWAdapter for JPEGAdapter {
    /// Decode DICOM image data with jpeg encoding.

    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src
            .cols()
            .context(MissingAttributeSnafu { name: "Columns" })?;
        let rows = src.rows().context(MissingAttributeSnafu { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttributeSnafu {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttributeSnafu {
            name: "BitsAllocated",
        })?;

        if bits_allocated != 8 && bits_allocated != 16 {
            return CustomMessageSnafu {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail();
        }

        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let bytes_per_sample = bits_allocated / 8;
        let encoded_frames = self.encoded_frames(src)?;

        // `stride` it the total number of bytes for each sample plane
        let stride: usize = bytes_per_sample as usize * cols as usize * rows as usize;
        dst.resize((samples_per_pixel as usize * stride) * nr_frames, 0);

        let mut offset = 0;
        for frame in encoded_frames {
            let mut decoder = Decoder::new(Cursor::new(frame));

            let decoded = decoder
                .decode()
                .map_err(|e| Box::new(e) as Box<_>)
                .context(CustomSnafu)?;

            let decoded_len = decoded.len();
            dst[offset..(offset + decoded_len)].copy_from_slice(&decoded);
            offset += decoded_len
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use rustc::traits::Reveal;
use rustc::ty::{self, TyCtxt, Ty, Instance};
use rustc::mir;

use syntax::ast::Mutability;

use super::{
    EvalResult, EvalError,
    Global, GlobalId, Lvalue,
    PrimVal,
    EvalContext, StackPopCleanup,
};

use rustc_const_math::ConstInt;

use std::fmt;
use std::error::Error;

pub fn eval_body_as_primval<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
    let limits = super::ResourceLimits::default();
    let mut ecx = EvalContext::<Evaluator>::new(tcx, limits, (), ());
    let cid = GlobalId { instance, promoted: None };
    if ecx.tcx.has_attr(instance.def_id(), "linkage") {
        return Err(ConstEvalError::NotConst("extern global".to_string()).into());
    }

    let mir = ecx.load_mir(instance.def)?;
    if !ecx.globals.contains_key(&cid) {
        ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
        let mutable = !mir.return_ty.is_freeze(
                ecx.tcx,
                ty::ParamEnv::empty(Reveal::All),
                mir.span);
        let mutability = if mutable {
            Mutability::Mutable
        } else {
            Mutability::Immutable
        };
        let cleanup = StackPopCleanup::MarkStatic(mutability);
        let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
        trace!("pushing stack frame for global: {}", name);
        ecx.push_stack_frame(
            instance,
            mir.span,
            mir,
            Lvalue::Global(cid),
            cleanup,
        )?;

        while ecx.step()? {}
    }
    let value = ecx.globals.get(&cid).expect("global not cached").value;
    Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
}

pub fn eval_body_as_integer<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, ConstInt> {
    let (prim, ty) = eval_body_as_primval(tcx, instance)?;
    let prim = prim.to_bytes()?;
    use syntax::ast::{IntTy, UintTy};
    use rustc::ty::TypeVariants::*;
    use rustc_const_math::{ConstIsize, ConstUsize};
    Ok(match ty.sty {
        TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
        TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
        TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
        TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
        TyUint(UintTy::U128) => ConstInt::U128(prim),
        TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
        _ => return Err(ConstEvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string()).into()),
    })
}

struct Evaluator;

impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
    fn into(self) -> EvalError<'tcx> {
        EvalError::MachineError(Box::new(self))
    }
}

#[derive(Clone, Debug)]
enum ConstEvalError {
    NeedsRfc(String),
    NotConst(String),
}

impl fmt::Display for ConstEvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(ref msg) =>
                write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
            NotConst(ref msg) =>
                write!(f, "Cannot evaluate within constants: \"{}\"", msg),
        }
    }
}

impl Error for ConstEvalError {
    fn description(&self) -> &str {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(_) =>
                "this feature needs an rfc before being allowed inside constants",
            NotConst(_) =>
                "this feature is not compatible with constant evaluation",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<'tcx> super::Machine<'tcx> for Evaluator {
    type Data = ();
    type MemoryData = ();
    fn call_missing_fn<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _instance: ty::Instance<'tcx>,
        _destination: Option<(Lvalue<'tcx>, mir::BasicBlock)>,
        _arg_operands: &[mir::Operand<'tcx>],
        _sig: ty::FnSig<'tcx>,
        path: String,
    ) -> EvalResult<'tcx> {
        // some simple things like `malloc` might get accepted in the future
        Err(ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)).into())
    }

    fn ptr_op<'a>(
        _ecx: &EvalContext<'a, 'tcx, Self>,
        _bin_op: mir::BinOp,
        _left: PrimVal,
        _left_ty: Ty<'tcx>,
        _right: PrimVal,
        _right_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
        Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
    }

    fn check_non_const_fn_call(instance: ty::Instance<'tcx>) -> EvalResult<'tcx> {
        return Err(ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into());
    }
}
<commit_msg>Rename `const_eval::Evaluator` to `CompileTimeFunctionEvaluator`<commit_after>use rustc::traits::Reveal;
use rustc::ty::{self, TyCtxt, Ty, Instance};
use rustc::mir;

use syntax::ast::Mutability;

use super::{
    EvalResult, EvalError,
    Global, GlobalId, Lvalue,
    PrimVal,
    EvalContext, StackPopCleanup,
};

use rustc_const_math::ConstInt;

use std::fmt;
use std::error::Error;

pub fn eval_body_as_primval<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
    let limits = super::ResourceLimits::default();
    let mut ecx = EvalContext::<CompileTimeFunctionEvaluator>::new(tcx, limits, (), ());
    let cid = GlobalId { instance, promoted: None };
    if ecx.tcx.has_attr(instance.def_id(), "linkage") {
        return Err(ConstEvalError::NotConst("extern global".to_string()).into());
    }

    let mir = ecx.load_mir(instance.def)?;
    if !ecx.globals.contains_key(&cid) {
        ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
        let mutable = !mir.return_ty.is_freeze(
                ecx.tcx,
                ty::ParamEnv::empty(Reveal::All),
                mir.span);
        let mutability = if mutable {
            Mutability::Mutable
        } else {
            Mutability::Immutable
        };
        let cleanup = StackPopCleanup::MarkStatic(mutability);
        let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
        trace!("pushing stack frame for global: {}", name);
        ecx.push_stack_frame(
            instance,
            mir.span,
            mir,
            Lvalue::Global(cid),
            cleanup,
        )?;

        while ecx.step()? {}
    }
    let value = ecx.globals.get(&cid).expect("global not cached").value;
    Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
}

pub fn eval_body_as_integer<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, ConstInt> {
    let (prim, ty) = eval_body_as_primval(tcx, instance)?;
    let prim = prim.to_bytes()?;
    use syntax::ast::{IntTy, UintTy};
    use rustc::ty::TypeVariants::*;
    use rustc_const_math::{ConstIsize, ConstUsize};
    Ok(match ty.sty {
        TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
        TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
        TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
        TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
        TyUint(UintTy::U128) => ConstInt::U128(prim),
        TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
        _ => return Err(ConstEvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string()).into()),
    })
}

struct CompileTimeFunctionEvaluator;

impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
    fn into(self) -> EvalError<'tcx> {
        EvalError::MachineError(Box::new(self))
    }
}

#[derive(Clone, Debug)]
enum ConstEvalError {
    NeedsRfc(String),
    NotConst(String),
}

impl fmt::Display for ConstEvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(ref msg) =>
                write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
            NotConst(ref msg) =>
                write!(f, "Cannot evaluate within constants: \"{}\"", msg),
        }
    }
}

impl Error for ConstEvalError {
    fn description(&self) -> &str {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(_) =>
                "this feature needs an rfc before being allowed inside constants",
            NotConst(_) =>
                "this feature is not compatible with constant evaluation",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
    type Data = ();
    type MemoryData = ();
    fn call_missing_fn<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _instance: ty::Instance<'tcx>,
        _destination: Option<(Lvalue<'tcx>, mir::BasicBlock)>,
        _arg_operands: &[mir::Operand<'tcx>],
        _sig: ty::FnSig<'tcx>,
        path: String,
    ) -> EvalResult<'tcx> {
        // some simple things like `malloc` might get accepted in the future
        Err(ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)).into())
    }

    fn ptr_op<'a>(
        _ecx: &EvalContext<'a, 'tcx, Self>,
        _bin_op: mir::BinOp,
        _left: PrimVal,
        _left_ty: Ty<'tcx>,
        _right: PrimVal,
        _right_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
        Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
    }

    fn check_non_const_fn_call(instance: ty::Instance<'tcx>) -> EvalResult<'tcx> {
        return Err(ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into());
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_s3::{config, Client, Error, Region, RetryConfig, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The number of (re)tries.
    #[structopt(short, long, default_value = "2")]
    tries: u32,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Shows your buckets.
async fn show_num_buckets(client: &Client) -> Result<(), Error> {
    let resp = client.list_buckets().send().await?;
    let buckets = resp.buckets().unwrap_or_default();

    println!("Found {} buckets in all regions.", buckets.len());

    Ok(())
}

/// Displays how many Amazon S3 buckets you have.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-t TRIES]` - The number of times to (re)try the request.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();

    let Opt {
        region,
        tries,
        verbose,
    } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("S3 client version: {}", PKG_VERSION);
        println!(
            "Region:            {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!("Retries:           {}", &tries);
        println!();
    }

    assert_ne!(tries, 0, "You cannot set zero retries.");

    // snippet-start:[custom_retries.rust.set_retries]
    let shared_config = aws_config::from_env().region(region_provider).load().await;

    // Construct an S3 client with customized retry configuration.
    let client = Client::from_conf(
        // Start with the shared environment configuration.
        config::Builder::from(&shared_config)
            // Set max attempts.
            // If tries is 1, there are no retries.
            .retry_config(RetryConfig::default().with_max_attempts(tries))
            .build(),
    );
    // snippet-end:[custom_retries.rust.set_retries]

    show_num_buckets(&client).await
}
<commit_msg>0.49 bump<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_s3::{config, Client, Error, Region, RetryConfig, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The number of (re)tries.
    #[structopt(short, long, default_value = "2")]
    tries: u32,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Shows your buckets.
async fn show_num_buckets(client: &Client) -> Result<(), Error> {
    let resp = client.list_buckets().send().await?;
    let buckets = resp.buckets().unwrap_or_default();

    println!("Found {} buckets in all regions.", buckets.len());

    Ok(())
}

/// Displays how many Amazon S3 buckets you have.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-t TRIES]` - The number of times to (re)try the request.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();

    let Opt {
        region,
        tries,
        verbose,
    } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("S3 client version: {}", PKG_VERSION);
        println!(
            "Region:            {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!("Retries:           {}", &tries);
        println!();
    }

    assert_ne!(tries, 0, "You cannot set zero retries.");

    // snippet-start:[custom_retries.rust.set_retries]
    let shared_config = aws_config::from_env().region(region_provider).load().await;

    // Construct an S3 client with customized retry configuration.
    let client = Client::from_conf(
        // Start with the shared environment configuration.
        config::Builder::from(&shared_config)
            // Set max attempts.
            // If tries is 1, there are no retries.
            .retry_config(RetryConfig::standard().with_max_attempts(tries))
            .build(),
    );
    // snippet-end:[custom_retries.rust.set_retries]

    show_num_buckets(&client).await
}
<|endoftext|>


<commit_before>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;
use std::cmp;

mod draw;
use draw::draw;
use draw::get_absolute_draw_indices;
mod find;
use find::FindOptSubset;

extern crate ncurses;
use ncurses::*;

extern crate getopts;
use getopts::Options;

extern crate pest;
#[macro_use]
extern crate pest_derive;

use pest::Parser;

#[derive(Parser)]
#[grammar = "cmd.pest"]
struct IdentParser;

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

#[derive(PartialEq, Copy, Clone)]
pub enum Cursorstate {
    Leftnibble,
    Rightnibble,
    Asciichar,
}

fn main() {
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    let mut cstate: Cursorstate = Cursorstate::Leftnibble;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();
    let mut debug = String::new();

    // start ncursesw
    initscr();
    let screenheight = getmaxy(stdscr()) as usize;
    // ctrl+z and fg works with this
    cbreak();
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("v", "version", "print the version");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            println!("Usage: {} FILE [options]", program);
            endwin();
            return;
        }
    };
    if matches.opt_present("v") {
        println!("Version: {}", VERSION);
        endwin();
        return;
    }
    if matches.opt_present("h") {
        println!("Usage: {} FILE [options]", program);
        endwin();
        return;
    }

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

    let patharg = match matches.free.is_empty() {
        true => String::new(),
        false => matches.free[0].clone(),
    };
    let path = Path::new(&patharg);

    if patharg.is_empty() {
        endwin();
        println!("Patharg is empty!\n");
        return;
    }

    let mut file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(&path) {
        Err(why) => {
            println!("Could not open {}: {}", path.display(), why.to_string());
            endwin();
            return;
        }
        Ok(file) => file,
    };
    file.read_to_end(&mut buf).ok().expect(
        "File could not be read.",
    );

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
    draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);

    let mut quitnow = false;
    while quitnow == false {
        let key = std::char::from_u32(getch() as u32).unwrap();
        printw(&format!("   {:?}   ", key));
        command.push_str(&key.clone().to_string());

        let parsethisstring = command.clone();
        let commands = IdentParser::parse(Rule::cmd_list, &parsethisstring)
            .unwrap_or_else(|e| panic!("{}", e));

        let mut clear = true;
        let mut save = false;
        for cmd in commands {
            match cmd.as_rule() {
                Rule::down => {
                    printw(&format!("{:?}", cmd.as_rule()));
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN;
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                Rule::up => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                Rule::left => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos > 0 {
                            cursorpos -= 1;
                        }
                    } else if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    } else if cstate == Cursorstate::Leftnibble {
                        if cursorpos > 0 {
                            // not at start
                            cstate = Cursorstate::Rightnibble;
                            cursorpos -= 1;
                        }
                    }
                }
                Rule::right => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cursorpos += 1;
                        }
                    } else if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    } else if cstate == Cursorstate::Rightnibble {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cstate = Cursorstate::Leftnibble;
                            cursorpos += 1;
                        }
                    }
                }
                Rule::start => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    }
                }
                Rule::end => {
                    // check if no overflow
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // jump to end of line
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1);
                    } else {
                        // jump to end of line
                        cursorpos = buf.len() - 1
                    }
                    if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    }
                }
                Rule::top => {
                    cursorpos = 0;
                }
                Rule::bottom => {
                    cursorpos = buf.len() - 1;
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                }
                Rule::replace => {
                    // printw("next char will be the replacement!");
                    clear = false;
                }
                Rule::remove => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        // remove the current char
                        buf.remove(cursorpos);
                    }
                    // always perform the movement if possible
                    if cursorpos > 0 && cursorpos >= buf.len() {
                        cursorpos -= 1;
                    }
                }
                Rule::deleteline => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        // calculate start of line
                        let startofline = cursorpos - cursorpos % SPALTEN;
                        // calculate end of line
                        let mut endofline = cursorpos - (cursorpos % SPALTEN) + SPALTEN ;
                        endofline = cmp::min( endofline, buf.len() );
//                        debug.clear();
//                        debug.push_str(&format!("   cursorpos:{:?}", cursorpos));
//                        debug.push_str(&format!("   startofline:{:?}", startofline));
//                        debug.push_str(&format!("   endofline:{:?}", endofline));
                        // remove the current line
                        buf.drain(startofline..endofline);

                    }
                    // always perform the movement if possible
                    if cursorpos > SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                Rule::insert => {
                    printw("next chars will be inserted!");
                    clear = false;
                }
                Rule::jumpascii => {
                    if cstate == Cursorstate::Asciichar {
                        cstate = Cursorstate::Leftnibble;
                    } else {
                        cstate = Cursorstate::Asciichar;
                    }
                }
                Rule::helpfile => {
                    command.push_str("No helpfile yet");
                }
                Rule::backspace => {
                    command.pop();
                    command.pop();
                    clear = false;
                }
                Rule::saveandexit => {
                    save = true;
                    quitnow = true;
                }
                Rule::exit => quitnow = true,
                Rule::save => save = true,

                _ => (),
            }

            for inner_cmd in cmd.into_inner() {
                match inner_cmd.as_rule() {
                    Rule::replacement => {
                        // TODO: use inner_cmd and not just "key"
                        // printw(&format!("Replacement: {:?}", inner_cmd.as_str()));
                        if cstate == Cursorstate::Asciichar {
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // buf[cursorpos] = inner_cmd.as_str();
                            buf[cursorpos] = key as u8;
                        } else {
                            let mask = if cstate == Cursorstate::Leftnibble {
                                0x0F
                            } else {
                                0xF0
                            };
                            let shift = if cstate == Cursorstate::Leftnibble {
                                4
                            } else {
                                0
                            };
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // Change the selected nibble
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
                            }
                        }

                    }
                    // TODO: use inner_cmd and not just "key"
                    Rule::insertment => {
                        // printw(&format!("Inserted: {:?}", inner_cmd.as_str()));
                        command.pop(); // remove the just inserted thing
                        clear = false;

                        if cstate == Cursorstate::Leftnibble {
                            // Left nibble
                            if let Some(c) = (key as char).to_digit(16) {
                                buf.insert(cursorpos, (c as u8) << 4);
                                cstate = Cursorstate::Rightnibble;
                            }
                        } else if cstate == Cursorstate::Rightnibble {
                            // Right nibble
                            if cursorpos == buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            if let Some(c) = (key as char).to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & 0xF0 | c as u8;
                                cstate = Cursorstate::Leftnibble;
                                cursorpos += 1;
                            }
                        } else if cstate == Cursorstate::Asciichar {
                            buf.insert(cursorpos, key as u8);
                            cursorpos += 1;
                        }
                    }
                    Rule::searchstr => {
                        let search = inner_cmd.as_str().as_bytes();
                        let foundpos = TwoWaySearcher::new(&search);
                        cursorpos = foundpos.search_in(&buf).unwrap_or(cursorpos);
                    }
                    Rule::searchbytes => {
                        let search = inner_cmd.as_str().as_bytes();
                        let mut needle = vec![];
                        for i in 0..search.len() {
                            let nibble = match search[i] as u8 {
                                c @ 48...57 => c - 48, // Numbers from 0 to 9
                                b'x' => 0x10, // x is the wildcard
                                b'X' => 0x10, // X is the wildcard
                                c @ b'a'...b'f' => c - 87,
                                c @ b'A'...b'F' => c - 55,
                                _ => panic!("Should not get to this position!"),
                            };
                            needle.push(nibble);
                        }
                        cursorpos = buf.find_subset(&needle).unwrap_or(cursorpos);
                        // endwin(); println!("Searching for: {:?}", needle ); return;
                    }
                    Rule::linenumber => {
                        let linenr: usize = inner_cmd.as_str().parse().unwrap();
                        cursorpos = linenr * SPALTEN; // jump to the line
                        if cursorpos > buf.len() { // detect file end
                            cursorpos = buf.len();
                        }
                        cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    }
                    Rule::escape => (),
                    Rule::gatherone => clear = false,
                    _ => {
                        command.push_str(&format!("no rule for {:?} ", inner_cmd.as_rule()));
                        clear = false;
                    }
                };
            }
            if save {
                if path.exists() {
                    let mut file = match OpenOptions::new()
                        .read(true)
                        .write(true)
                        .create(true)
                        .open(&path) {
                        Err(why) => {
                            panic!(
                                "Could not open {}: {}",
                                path.display(),
                                Error::description(&why)
                            )
                        }
                        Ok(file) => file,
                    };
                    file.seek(SeekFrom::Start(0)).ok().expect(
                        "Filepointer could not be set to 0",
                    );
                    file.write_all(&mut buf).ok().expect(
                        "File could not be written.",
                    );
                    file.set_len(buf.len() as u64).ok().expect(
                        "File could not be set to correct lenght.",
                    );
                    command.push_str("File saved!");
                } else {
                    command.push_str("Careful, file could not be saved!");
                }
                // TODO: define filename during runtime
                save = false;
            }
            if clear {
                command.clear();
            }

            // Always move screen when cursor leaves screen
            if cursorpos > (screenheight + screenoffset - 1) * SPALTEN - 1 {
                screenoffset = 2 + cursorpos / SPALTEN - screenheight;
            }
            if cursorpos < screenoffset * SPALTEN {
                screenoffset = cursorpos / SPALTEN;
            }

        }

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
        draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);
    }

    refresh();
    endwin();
}
<commit_msg>Fix behaviour of 'dd'<commit_after>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;
use std::cmp;

mod draw;
use draw::draw;
use draw::get_absolute_draw_indices;
mod find;
use find::FindOptSubset;

extern crate ncurses;
use ncurses::*;

extern crate getopts;
use getopts::Options;

extern crate pest;
#[macro_use]
extern crate pest_derive;

use pest::Parser;

#[derive(Parser)]
#[grammar = "cmd.pest"]
struct IdentParser;

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

#[derive(PartialEq, Copy, Clone)]
pub enum Cursorstate {
    Leftnibble,
    Rightnibble,
    Asciichar,
}

fn main() {
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    let mut cstate: Cursorstate = Cursorstate::Leftnibble;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();
    let mut debug = String::new();

    // start ncursesw
    initscr();
    let screenheight = getmaxy(stdscr()) as usize;
    // ctrl+z and fg works with this
    cbreak();
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("v", "version", "print the version");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            println!("Usage: {} FILE [options]", program);
            endwin();
            return;
        }
    };
    if matches.opt_present("v") {
        println!("Version: {}", VERSION);
        endwin();
        return;
    }
    if matches.opt_present("h") {
        println!("Usage: {} FILE [options]", program);
        endwin();
        return;
    }

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

    let patharg = match matches.free.is_empty() {
        true => String::new(),
        false => matches.free[0].clone(),
    };
    let path = Path::new(&patharg);

    if patharg.is_empty() {
        endwin();
        println!("Patharg is empty!\n");
        return;
    }

    let mut file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(&path) {
        Err(why) => {
            println!("Could not open {}: {}", path.display(), why.to_string());
            endwin();
            return;
        }
        Ok(file) => file,
    };
    file.read_to_end(&mut buf).ok().expect(
        "File could not be read.",
    );

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
    draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);

    let mut quitnow = false;
    while quitnow == false {
        let key = std::char::from_u32(getch() as u32).unwrap();
        printw(&format!("   {:?}   ", key));
        command.push_str(&key.clone().to_string());

        let parsethisstring = command.clone();
        let commands = IdentParser::parse(Rule::cmd_list, &parsethisstring)
            .unwrap_or_else(|e| panic!("{}", e));

        let mut clear = true;
        let mut save = false;
        for cmd in commands {
            match cmd.as_rule() {
                Rule::down => {
                    printw(&format!("{:?}", cmd.as_rule()));
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN;
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                Rule::up => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                Rule::left => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos > 0 {
                            cursorpos -= 1;
                        }
                    } else if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    } else if cstate == Cursorstate::Leftnibble {
                        if cursorpos > 0 {
                            // not at start
                            cstate = Cursorstate::Rightnibble;
                            cursorpos -= 1;
                        }
                    }
                }
                Rule::right => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cursorpos += 1;
                        }
                    } else if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    } else if cstate == Cursorstate::Rightnibble {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cstate = Cursorstate::Leftnibble;
                            cursorpos += 1;
                        }
                    }
                }
                Rule::start => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    }
                }
                Rule::end => {
                    // check if no overflow
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // jump to end of line
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1);
                    } else {
                        // jump to end of line
                        cursorpos = buf.len() - 1
                    }
                    if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    }
                }
                Rule::top => {
                    cursorpos = 0;
                }
                Rule::bottom => {
                    cursorpos = buf.len() - 1;
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                }
                Rule::replace => {
                    // printw("next char will be the replacement!");
                    clear = false;
                }
                Rule::remove => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        // remove the current char
                        buf.remove(cursorpos);
                    }
                    // always perform the movement if possible
                    if cursorpos > 0 && cursorpos >= buf.len() {
                        cursorpos -= 1;
                    }
                }
                Rule::deleteline => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        let startofline = cursorpos - cursorpos % SPALTEN;
                        let mut endofline = cursorpos - (cursorpos % SPALTEN) + SPALTEN ;
                        endofline = cmp::min( endofline, buf.len() );
//                        debug.clear();
//                        debug.push_str(&format!("   cursorpos:{:?}", cursorpos));
//                        debug.push_str(&format!("   startofline:{:?}", startofline));
//                        debug.push_str(&format!("   endofline:{:?}", endofline));
                        buf.drain(startofline..endofline);
                    }
                    // move only in case last line just got deleted
                    if cursorpos >= buf.len() {
                        if ( cursorpos >= SPALTEN ) {
                            cursorpos -= SPALTEN;
                        }
                    }
                    // move to first char of line
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                }
                Rule::insert => {
                    printw("next chars will be inserted!");
                    clear = false;
                }
                Rule::jumpascii => {
                    if cstate == Cursorstate::Asciichar {
                        cstate = Cursorstate::Leftnibble;
                    } else {
                        cstate = Cursorstate::Asciichar;
                    }
                }
                Rule::helpfile => {
                    command.push_str("No helpfile yet");
                }
                Rule::backspace => {
                    command.pop();
                    command.pop();
                    clear = false;
                }
                Rule::saveandexit => {
                    save = true;
                    quitnow = true;
                }
                Rule::exit => quitnow = true,
                Rule::save => save = true,

                _ => (),
            }

            for inner_cmd in cmd.into_inner() {
                match inner_cmd.as_rule() {
                    Rule::replacement => {
                        // TODO: use inner_cmd and not just "key"
                        // printw(&format!("Replacement: {:?}", inner_cmd.as_str()));
                        if cstate == Cursorstate::Asciichar {
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // buf[cursorpos] = inner_cmd.as_str();
                            buf[cursorpos] = key as u8;
                        } else {
                            let mask = if cstate == Cursorstate::Leftnibble {
                                0x0F
                            } else {
                                0xF0
                            };
                            let shift = if cstate == Cursorstate::Leftnibble {
                                4
                            } else {
                                0
                            };
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // Change the selected nibble
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
                            }
                        }

                    }
                    // TODO: use inner_cmd and not just "key"
                    Rule::insertment => {
                        // printw(&format!("Inserted: {:?}", inner_cmd.as_str()));
                        command.pop(); // remove the just inserted thing
                        clear = false;

                        if cstate == Cursorstate::Leftnibble {
                            // Left nibble
                            if let Some(c) = (key as char).to_digit(16) {
                                buf.insert(cursorpos, (c as u8) << 4);
                                cstate = Cursorstate::Rightnibble;
                            }
                        } else if cstate == Cursorstate::Rightnibble {
                            // Right nibble
                            if cursorpos == buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            if let Some(c) = (key as char).to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & 0xF0 | c as u8;
                                cstate = Cursorstate::Leftnibble;
                                cursorpos += 1;
                            }
                        } else if cstate == Cursorstate::Asciichar {
                            buf.insert(cursorpos, key as u8);
                            cursorpos += 1;
                        }
                    }
                    Rule::searchstr => {
                        let search = inner_cmd.as_str().as_bytes();
                        let foundpos = TwoWaySearcher::new(&search);
                        cursorpos = foundpos.search_in(&buf).unwrap_or(cursorpos);
                    }
                    Rule::searchbytes => {
                        let search = inner_cmd.as_str().as_bytes();
                        let mut needle = vec![];
                        for i in 0..search.len() {
                            let nibble = match search[i] as u8 {
                                c @ 48...57 => c - 48, // Numbers from 0 to 9
                                b'x' => 0x10, // x is the wildcard
                                b'X' => 0x10, // X is the wildcard
                                c @ b'a'...b'f' => c - 87,
                                c @ b'A'...b'F' => c - 55,
                                _ => panic!("Should not get to this position!"),
                            };
                            needle.push(nibble);
                        }
                        cursorpos = buf.find_subset(&needle).unwrap_or(cursorpos);
                        // endwin(); println!("Searching for: {:?}", needle ); return;
                    }
                    Rule::linenumber => {
                        let linenr: usize = inner_cmd.as_str().parse().unwrap();
                        cursorpos = linenr * SPALTEN; // jump to the line
                        if cursorpos > buf.len() { // detect file end
                            cursorpos = buf.len();
                        }
                        cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    }
                    Rule::escape => (),
                    Rule::gatherone => clear = false,
                    _ => {
                        command.push_str(&format!("no rule for {:?} ", inner_cmd.as_rule()));
                        clear = false;
                    }
                };
            }
            if save {
                if path.exists() {
                    let mut file = match OpenOptions::new()
                        .read(true)
                        .write(true)
                        .create(true)
                        .open(&path) {
                        Err(why) => {
                            panic!(
                                "Could not open {}: {}",
                                path.display(),
                                Error::description(&why)
                            )
                        }
                        Ok(file) => file,
                    };
                    file.seek(SeekFrom::Start(0)).ok().expect(
                        "Filepointer could not be set to 0",
                    );
                    file.write_all(&mut buf).ok().expect(
                        "File could not be written.",
                    );
                    file.set_len(buf.len() as u64).ok().expect(
                        "File could not be set to correct lenght.",
                    );
                    command.push_str("File saved!");
                } else {
                    command.push_str("Careful, file could not be saved!");
                }
                // TODO: define filename during runtime
                save = false;
            }
            if clear {
                command.clear();
            }

            // Always move screen when cursor leaves screen
            if cursorpos > (screenheight + screenoffset - 1) * SPALTEN - 1 {
                screenoffset = 2 + cursorpos / SPALTEN - screenheight;
            }
            if cursorpos < screenoffset * SPALTEN {
                screenoffset = cursorpos / SPALTEN;
            }

        }

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
        draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);
    }

    refresh();
    endwin();
}
<|endoftext|>


<commit_before><commit_msg>simplifies the threads loop; starts checking from 0<commit_after><|endoftext|>


<commit_before>extern crate randomorg;

fn main() {
    use randomorg::Random;

    let r = Random::new("API KEY HERE");
    println!("Result: {:?}", r.generate_integers(-100, 100, 15, true));
}
<commit_msg>Use environment variable in the example<commit_after>extern crate randomorg;

fn main() {
    use std::env;
    use randomorg::Random;

    let r = Random::new(env::var("RANDOM_ORG_API_KEY").unwrap());
    println!("Result: {:?}", r.generate_integers(-100, 100, 15, true).unwrap());
}
<|endoftext|>


<commit_before>extern crate suppositions;
use std::cmp::min;
use suppositions::*;
use suppositions::generators::*;

// Run this with:
// ```
// cargo run --example die-hard
// ```
// You should see output of the form:
// ```
// thread 'main' panicked at 'Predicate failed for argument
// Ok([FillBigJug, BigToSmall, EmptySmallJug, BigToSmall, FillBigJug, BigToSmall]);
// check returned Ok(Err(State { big: 4, small: 3 }))', src/properties.rs:56:24
// ```

#[derive(Debug, Clone)]
pub enum Op {
    FillSmallJug,
    FillBigJug,
    EmptySmallJug,
    EmptyBigJug,
    SmallToBig,
    BigToSmall,
}

#[derive(Debug, Default, Clone)]
pub struct State {
    big: usize,
    small: usize,
}

impl State {
    fn apply(&mut self, op: &Op) {
        match op {
            &Op::FillSmallJug => {
                self.small = 3;
            }
            &Op::FillBigJug => self.big = 5,
            &Op::EmptySmallJug => self.small = 0,
            &Op::EmptyBigJug => self.big = 0,
            &Op::SmallToBig => {
                let old = self.clone();
                self.big = min(old.big + self.small, 5);
                self.small -= self.big - old.big
            }

            &Op::BigToSmall => {
                let old = self.clone();
                self.small = min(old.big + self.small, 3);
                self.big -= self.small - old.small
            }
        }
    }

    fn assert_invariants(&self) {
        assert!(self.big <= 5);
        assert!(self.small <= 3);
    }
    fn finished(&self) -> bool {
        self.big == 4
    }
}

fn ops() -> Box<Generator<Item = Op>> {
    let g = one_of(consts(Op::FillSmallJug))
        .or(consts(Op::FillBigJug))
        .or(consts(Op::EmptySmallJug))
        .or(consts(Op::EmptyBigJug))
        .or(consts(Op::SmallToBig))
        .or(consts(Op::BigToSmall));
    Box::new(g)
}

fn main() {
    property(vecs(ops()).mean_length(1000)).check(|xs| {
        let mut sts = Vec::new();
        let mut st = State::default();
        for o in xs.iter() {
            st.apply(o);
            sts.push((o.clone(), st.clone()));
            st.assert_invariants();
            if st.finished() {
                return Err(st);
            }
        }
        return Ok(());
    });

    panic!("No solution found")
}
<commit_msg>Enable logging in example.<commit_after>extern crate suppositions;
extern crate env_logger;
use std::cmp::min;
use suppositions::*;
use suppositions::generators::*;

// Run this with:
// ```
// cargo run --example die-hard
// ```
// You should see output of the form:
// ```
// thread 'main' panicked at 'Predicate failed for argument
// Ok([FillBigJug, BigToSmall, EmptySmallJug, BigToSmall, FillBigJug, BigToSmall]);
// check returned Ok(Err(State { big: 4, small: 3 }))', src/properties.rs:56:24
// ```

#[derive(Debug, Clone)]
pub enum Op {
    FillSmallJug,
    FillBigJug,
    EmptySmallJug,
    EmptyBigJug,
    SmallToBig,
    BigToSmall,
}

#[derive(Debug, Default, Clone)]
pub struct State {
    big: usize,
    small: usize,
}

impl State {
    fn apply(&mut self, op: &Op) {
        match op {
            &Op::FillSmallJug => {
                self.small = 3;
            }
            &Op::FillBigJug => self.big = 5,
            &Op::EmptySmallJug => self.small = 0,
            &Op::EmptyBigJug => self.big = 0,
            &Op::SmallToBig => {
                let old = self.clone();
                self.big = min(old.big + self.small, 5);
                self.small -= self.big - old.big
            }

            &Op::BigToSmall => {
                let old = self.clone();
                self.small = min(old.big + self.small, 3);
                self.big -= self.small - old.small
            }
        }
    }

    fn assert_invariants(&self) {
        assert!(self.big <= 5);
        assert!(self.small <= 3);
    }
    fn finished(&self) -> bool {
        self.big == 4
    }
}

fn ops() -> Box<Generator<Item = Op>> {
    let g = one_of(consts(Op::FillSmallJug))
        .or(consts(Op::FillBigJug))
        .or(consts(Op::EmptySmallJug))
        .or(consts(Op::EmptyBigJug))
        .or(consts(Op::SmallToBig))
        .or(consts(Op::BigToSmall));
    Box::new(g)
}

fn main() {
    env_logger::init().expect("env_logger::init");

    property(vecs(ops()).mean_length(1000)).check(|xs| {
        let mut sts = Vec::new();
        let mut st = State::default();
        for o in xs.iter() {
            st.apply(o);
            sts.push((o.clone(), st.clone()));
            st.assert_invariants();
            if st.finished() {
                return Err(st);
            }
        }
        return Ok(());
    });

    panic!("No solution found")
}
<|endoftext|>