<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#![feature(path_ext)]

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path;

fn run_metaflac(fname: &path::Path) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                         .arg("--show-min-blocksize")
                         .arg("--show-max-blocksize")
                         .arg("--show-min-framesize")
                         .arg("--show-max-framesize")
                         .arg("--show-sample-rate")
                         .arg("--show-channels")
                         .arg("--show-bps")
                         .arg("--show-total-samples")
                         .arg("--show-md5sum")
                         .arg(fname.to_str().expect("unsupported filename"))
                         .output().ok().expect("failed to run metaflac");
    String::from_utf8(output.stdout).ok().expect("metaflac wrote invalid UTF-8")
}

fn decode_file(fname: &path::Path) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                          .arg("--decode")
                          .arg(fname.to_str().expect("unsupported filename"))
                          .status().ok().expect("failed to run flac")
                          .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo(fname: &path::Path) -> String {
    use claxon::FlacStream;

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = FlacStream::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac(fname: &path::Path) {
    let metaflac = run_metaflac(fname);
    let streaminfo = read_streaminfo(fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    };
}

fn compare_decoded_stream(fname: &path::Path) {
    use std::fs::PathExt;

    let ref_fname = fname.with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_stream = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_reader = io::BufReader::new(try_file);
        let mut try_stream = claxon::FlacStream::new(try_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_stream.samples::<i32>();

        let samples = try_stream.streaminfo().samples.unwrap();
        let n_channels = try_stream.streaminfo().channels;
        let mut blocks = try_stream.blocks::<i32>();
        let mut sample = 0u64;
        let mut b = 0u64;

        while sample < samples {
            let block = blocks.read_next().unwrap();
            let mut channels: Vec<_> = (0 .. n_channels)
                                       .map(|i| block.channel(i).iter().cloned())
                                       .collect();
            for i in 0 .. block.len() {
                for ch in 0 .. n_channels as usize {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: reference is {} but decoded is {}",
                                 i, b, ch, ref_sample.unwrap(), try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.len() as u64;
            b = b + 1;
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac(path::Path::new("testsamples/p4.flac"));
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream(path::Path::new("testsamples/p4.flac"));
}
<commit_msg>do not use deprecated path_ext feature<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path;

fn run_metaflac(fname: &path::Path) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                         .arg("--show-min-blocksize")
                         .arg("--show-max-blocksize")
                         .arg("--show-min-framesize")
                         .arg("--show-max-framesize")
                         .arg("--show-sample-rate")
                         .arg("--show-channels")
                         .arg("--show-bps")
                         .arg("--show-total-samples")
                         .arg("--show-md5sum")
                         .arg(fname.to_str().expect("unsupported filename"))
                         .output().ok().expect("failed to run metaflac");
    String::from_utf8(output.stdout).ok().expect("metaflac wrote invalid UTF-8")
}

fn decode_file(fname: &path::Path) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                          .arg("--decode")
                          .arg(fname.to_str().expect("unsupported filename"))
                          .status().ok().expect("failed to run flac")
                          .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo(fname: &path::Path) -> String {
    use claxon::FlacStream;

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = FlacStream::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac(fname: &path::Path) {
    let metaflac = run_metaflac(fname);
    let streaminfo = read_streaminfo(fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    };
}

fn compare_decoded_stream(fname: &path::Path) {
    let ref_fname = fname.with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_stream = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_reader = io::BufReader::new(try_file);
        let mut try_stream = claxon::FlacStream::new(try_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_stream.samples::<i32>();

        let samples = try_stream.streaminfo().samples.unwrap();
        let n_channels = try_stream.streaminfo().channels;
        let mut blocks = try_stream.blocks::<i32>();
        let mut sample = 0u64;
        let mut b = 0u64;

        while sample < samples {
            let block = blocks.read_next().unwrap();
            let mut channels: Vec<_> = (0 .. n_channels)
                                       .map(|i| block.channel(i).iter().cloned())
                                       .collect();
            for i in 0 .. block.len() {
                for ch in 0 .. n_channels as usize {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: reference is {} but decoded is {}",
                                 i, b, ch, ref_sample.unwrap(), try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.len() as u64;
            b = b + 1;
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac(path::Path::new("testsamples/p4.flac"));
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream(path::Path::new("testsamples/p4.flac"));
}
<|endoftext|>


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

extern crate numeral;

use numeral::Cardinal;

macro_rules! test_call_on_min_max {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            <$numtype>::max_value().cardinal();
            <$numtype>::min_value().cardinal();
        }
    };
}

test_call_on_min_max!(call_on_min_max_i8, i8);
test_call_on_min_max!(call_on_min_max_u8, u8);
test_call_on_min_max!(call_on_min_max_i16, i16);
test_call_on_min_max!(call_on_min_max_u16, u16);
test_call_on_min_max!(call_on_min_max_i32, i32);
test_call_on_min_max!(call_on_min_max_u32, u32);
test_call_on_min_max!(call_on_min_max_i64, i64);
test_call_on_min_max!(call_on_min_max_u64, u64);
test_call_on_min_max!(call_on_min_max_isize, isize);
test_call_on_min_max!(call_on_min_max_usize, usize);

macro_rules! test_call_on_range {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            for n in (<$numtype>::min_value())..=(<$numtype>::max_value()) {
                n.cardinal();
            }
        }
    };
}

test_call_on_range!(call_on_range_i8, i8);
test_call_on_range!(call_on_range_u8, u8);
test_call_on_range!(call_on_range_i16, i16);
test_call_on_range!(call_on_range_u16, u16);

macro_rules! test_call_on_critical_ranges {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            for n in (<$numtype>::min_value())..=(<$numtype>::min_value()) + 130 {
                n.cardinal();
            }
            for n in (<$numtype>::max_value()) - 130..=(<$numtype>::max_value()) {
                n.cardinal();
            }
            if <$numtype>::min_value() != 0 {
                for n in -130..=130 {
                    n.cardinal();
                }
            }
        }
    };
}

test_call_on_critical_ranges!(call_on_critical_ranges_i32, i32);
test_call_on_critical_ranges!(call_on_critical_ranges_u32, u32);
test_call_on_critical_ranges!(call_on_critical_ranges_i64, i64);
test_call_on_critical_ranges!(call_on_critical_ranges_u64, u64);
test_call_on_critical_ranges!(call_on_critical_ranges_isize, isize);
test_call_on_critical_ranges!(call_on_critical_ranges_usize, usize);

#[test]
fn cardinal_value_m256_256() {
    let cardinals = std::fs::read_to_string("tests/cardinal_m256..=256.txt").unwrap();
    assert!(
        cardinals
            .lines()
            .eq((-256..=256).map(|n: i32| n.cardinal()))
    );
}

#[test]
fn cardinal_value_min_max_int() {
    let cardinals = std::fs::read_to_string("tests/cardinal_min_max.txt").unwrap();
    let mut lines = cardinals.lines();
    macro_rules! assert_eq_min_max {
        ($signed:ty, $unsigned:ty) => {
            assert_eq!(lines.next().unwrap(), <$signed>::min_value().cardinal());
            assert_eq!(lines.next().unwrap(), <$signed>::max_value().cardinal());
            assert_eq!(lines.next().unwrap(), <$unsigned>::max_value().cardinal());
        };
    }
    assert_eq!(lines.next().unwrap(), 0.cardinal());
    assert_eq_min_max!(i8, u8);
    assert_eq_min_max!(i16, u16);
    assert_eq_min_max!(i32, u32);
    assert_eq_min_max!(i64, u64);
}

#[test]
fn cardinal_value_min_max_ptr() {
    use std::mem::size_of;

    macro_rules! assert_eq_min_max_if_ptr_is {
        ($ptr:ty, $int:ty) => {
            if size_of::<$ptr>() == size_of::<$int>() {
                assert_eq!(<$ptr>::min_value().cardinal(), <$int>::min_value().cardinal());
                assert_eq!(<$ptr>::max_value().cardinal(), <$int>::max_value().cardinal());
            }
        };
    }
    assert_eq_min_max_if_ptr_is!(isize, i8);
    assert_eq_min_max_if_ptr_is!(isize, i16);
    assert_eq_min_max_if_ptr_is!(isize, i32);
    assert_eq_min_max_if_ptr_is!(isize, i64);
    assert_eq_min_max_if_ptr_is!(usize, u8);
    assert_eq_min_max_if_ptr_is!(usize, u16);
    assert_eq_min_max_if_ptr_is!(usize, u32);
    assert_eq_min_max_if_ptr_is!(usize, u64);
}
<commit_msg>rename call_on_range tests<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

extern crate numeral;

use numeral::Cardinal;

macro_rules! test_call_on_min_max {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            <$numtype>::max_value().cardinal();
            <$numtype>::min_value().cardinal();
        }
    };
}

test_call_on_min_max!(call_on_min_max_i8, i8);
test_call_on_min_max!(call_on_min_max_u8, u8);
test_call_on_min_max!(call_on_min_max_i16, i16);
test_call_on_min_max!(call_on_min_max_u16, u16);
test_call_on_min_max!(call_on_min_max_i32, i32);
test_call_on_min_max!(call_on_min_max_u32, u32);
test_call_on_min_max!(call_on_min_max_i64, i64);
test_call_on_min_max!(call_on_min_max_u64, u64);
test_call_on_min_max!(call_on_min_max_isize, isize);
test_call_on_min_max!(call_on_min_max_usize, usize);

macro_rules! test_call_on_full_range {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            for n in (<$numtype>::min_value())..=(<$numtype>::max_value()) {
                n.cardinal();
            }
        }
    };
}

test_call_on_full_range!(call_on_full_range_i8, i8);
test_call_on_full_range!(call_on_full_range_u8, u8);
test_call_on_full_range!(call_on_full_range_i16, i16);
test_call_on_full_range!(call_on_full_range_u16, u16);

macro_rules! test_call_on_critical_ranges {
    ($fn_name:ident, $numtype:ty) => {
        #[test]
        fn $fn_name() {
            for n in (<$numtype>::min_value())..=(<$numtype>::min_value()) + 130 {
                n.cardinal();
            }
            for n in (<$numtype>::max_value()) - 130..=(<$numtype>::max_value()) {
                n.cardinal();
            }
            if <$numtype>::min_value() != 0 {
                for n in -130..=130 {
                    n.cardinal();
                }
            }
        }
    };
}

test_call_on_critical_ranges!(call_on_critical_ranges_i32, i32);
test_call_on_critical_ranges!(call_on_critical_ranges_u32, u32);
test_call_on_critical_ranges!(call_on_critical_ranges_i64, i64);
test_call_on_critical_ranges!(call_on_critical_ranges_u64, u64);
test_call_on_critical_ranges!(call_on_critical_ranges_isize, isize);
test_call_on_critical_ranges!(call_on_critical_ranges_usize, usize);

#[test]
fn cardinal_value_m256_256() {
    let cardinals = std::fs::read_to_string("tests/cardinal_m256..=256.txt").unwrap();
    assert!(
        cardinals
            .lines()
            .eq((-256..=256).map(|n: i32| n.cardinal()))
    );
}

#[test]
fn cardinal_value_min_max_int() {
    let cardinals = std::fs::read_to_string("tests/cardinal_min_max.txt").unwrap();
    let mut lines = cardinals.lines();
    macro_rules! assert_eq_min_max {
        ($signed:ty, $unsigned:ty) => {
            assert_eq!(lines.next().unwrap(), <$signed>::min_value().cardinal());
            assert_eq!(lines.next().unwrap(), <$signed>::max_value().cardinal());
            assert_eq!(lines.next().unwrap(), <$unsigned>::max_value().cardinal());
        };
    }
    assert_eq!(lines.next().unwrap(), 0.cardinal());
    assert_eq_min_max!(i8, u8);
    assert_eq_min_max!(i16, u16);
    assert_eq_min_max!(i32, u32);
    assert_eq_min_max!(i64, u64);
}

#[test]
fn cardinal_value_min_max_ptr() {
    use std::mem::size_of;

    macro_rules! assert_eq_min_max_if_ptr_is {
        ($ptr:ty, $int:ty) => {
            if size_of::<$ptr>() == size_of::<$int>() {
                assert_eq!(<$ptr>::min_value().cardinal(), <$int>::min_value().cardinal());
                assert_eq!(<$ptr>::max_value().cardinal(), <$int>::max_value().cardinal());
            }
        };
    }
    assert_eq_min_max_if_ptr_is!(isize, i8);
    assert_eq_min_max_if_ptr_is!(isize, i16);
    assert_eq_min_max_if_ptr_is!(isize, i32);
    assert_eq_min_max_if_ptr_is!(isize, i64);
    assert_eq_min_max_if_ptr_is!(usize, u8);
    assert_eq_min_max_if_ptr_is!(usize, u16);
    assert_eq_min_max_if_ptr_is!(usize, u32);
    assert_eq_min_max_if_ptr_is!(usize, u64);
}
<|endoftext|>


<commit_before>
/// A pointer to a descriptor table (IDT or GDT)
#[repr(C, packed)]
pub struct Pointer { pub limit: u16
                   , pub base: usize
                   }

/// A descriptor table (IDT or GDT)
pub trait DTable {
    unsafe fn load(&self);
}
<commit_msg>[x86_all] improve DTable docs a bit<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! x86 descriptor tables (IDT, GDT, or LDT)

use memory::PAddr;

/// A pointer to a descriptor table.
/// This is a format suitable
#[repr(C, packed)]
pub struct Pointer { /// the length of the descriptor table
                     pub limit: u16
                   , /// pointer to the region in memory
                     /// containing the descriptor table.
                     pub base: PAddr
                   }

/// A descriptor table (IDT or GDT)
pub trait DTable {
    unsafe fn load(&self);
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{types, types::ErrorDetails};
use aptos_rest_client::aptos_api_types::AptosErrorCode;
use aptos_rest_client::error::RestError;
use hex::FromHexError;
use move_deps::move_core_types::account_address::AccountAddressParseError;
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;
use warp::{http::StatusCode, reply::Reply};

pub type ApiResult<T> = Result<T, ApiError>;

#[derive(Debug, Deserialize, Serialize)]
pub enum ApiError {
    BlockParameterConflict,
    TransactionIsPending,
    NetworkIdentifierMismatch,
    ChainIdMismatch,
    DeserializationFailed(Option<String>),
    InvalidTransferOperations(Option<&'static str>),
    InvalidSignatureType,
    InvalidMaxGasFees,
    MaxGasFeeTooLow,
    InvalidGasMultiplier,
    GasEstimationFailed(Option<String>),
    InvalidOperations(Option<String>),
    MissingPayloadMetadata,
    UnsupportedCurrency(Option<String>),
    UnsupportedSignatureCount(Option<usize>),
    NodeIsOffline,
    TransactionParseError(Option<String>),
    InternalError(Option<String>),

    // Below here are codes directly from the REST API
    AccountNotFound(Option<String>),
    ResourceNotFound(Option<String>),
    ModuleNotFound(Option<String>),
    StructFieldNotFound(Option<String>),
    VersionNotFound(Option<String>),
    TransactionNotFound(Option<String>),
    TableItemNotFound(Option<String>),
    BlockNotFound(Option<String>),
    VersionPruned(Option<String>),
    BlockPruned(Option<String>),
    InvalidInput(Option<String>),
    InvalidTransactionUpdate(Option<String>),
    SequenceNumberTooOld(Option<String>),
    VmError(Option<String>),
    MempoolIsFull(Option<String>),
}

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

impl std::error::Error for ApiError {}

impl ApiError {
    pub fn all() -> Vec<ApiError> {
        use ApiError::*;
        vec![
            BlockParameterConflict,
            TransactionIsPending,
            NetworkIdentifierMismatch,
            ChainIdMismatch,
            DeserializationFailed(None),
            InvalidTransferOperations(None),
            InvalidSignatureType,
            InvalidMaxGasFees,
            MaxGasFeeTooLow,
            InvalidGasMultiplier,
            GasEstimationFailed(None),
            InvalidOperations(None),
            MissingPayloadMetadata,
            UnsupportedCurrency(None),
            UnsupportedSignatureCount(None),
            NodeIsOffline,
            TransactionParseError(None),
            InternalError(None),
            AccountNotFound(None),
            ResourceNotFound(None),
            ModuleNotFound(None),
            StructFieldNotFound(None),
            VersionNotFound(None),
            TransactionNotFound(None),
            TableItemNotFound(None),
            BlockNotFound(None),
            VersionPruned(None),
            BlockPruned(None),
            InvalidInput(None),
            InvalidTransactionUpdate(None),
            SequenceNumberTooOld(None),
            VmError(None),
            MempoolIsFull(None),
        ]
    }

    pub fn code(&self) -> u32 {
        use ApiError::*;
        match self {
            BlockParameterConflict => 0,
            TransactionIsPending => 1,
            NetworkIdentifierMismatch => 2,
            ChainIdMismatch => 3,
            DeserializationFailed(_) => 4,
            InvalidTransferOperations(_) => 5,
            InvalidSignatureType => 6,
            InvalidMaxGasFees => 7,
            MaxGasFeeTooLow => 8,
            InvalidGasMultiplier => 9,
            InvalidOperations(_) => 10,
            MissingPayloadMetadata => 11,
            UnsupportedCurrency(_) => 12,
            UnsupportedSignatureCount(_) => 13,
            NodeIsOffline => 14,
            TransactionParseError(_) => 15,
            GasEstimationFailed(_) => 16,
            InternalError(_) => 17,
            AccountNotFound(_) => 18,
            ResourceNotFound(_) => 19,
            ModuleNotFound(_) => 20,
            StructFieldNotFound(_) => 21,
            VersionNotFound(_) => 22,
            TransactionNotFound(_) => 23,
            TableItemNotFound(_) => 24,
            BlockNotFound(_) => 25,
            VersionPruned(_) => 26,
            BlockPruned(_) => 27,
            InvalidInput(_) => 28,
            InvalidTransactionUpdate(_) => 29,
            SequenceNumberTooOld(_) => 30,
            VmError(_) => 31,
            MempoolIsFull(_) => 32,
        }
    }

    pub fn retriable(&self) -> bool {
        use ApiError::*;
        matches!(
            self,
            AccountNotFound(_) | BlockNotFound(_) | MempoolIsFull(_) | GasEstimationFailed(_)
        )
    }

    pub fn status_code(&self) -> StatusCode {
        use ApiError::*;
        match self {
            AccountNotFound(_)
            | BlockNotFound(_)
            | ResourceNotFound(_)
            | ModuleNotFound(_)
            | VersionNotFound(_)
            | TransactionNotFound(_)
            | StructFieldNotFound(_)
            | TableItemNotFound(_) => StatusCode::NOT_FOUND,
            MempoolIsFull(_) => StatusCode::INSUFFICIENT_STORAGE,
            BlockPruned(_) | VersionPruned(_) => StatusCode::GONE,
            NodeIsOffline => StatusCode::METHOD_NOT_ALLOWED,
            GasEstimationFailed(_) => StatusCode::SERVICE_UNAVAILABLE,
            InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            _ => StatusCode::BAD_REQUEST,
        }
    }

    /// This value must be fixed, so it's all static strings
    pub fn message(&self) -> &'static str {
        match self {
            ApiError::BlockParameterConflict => {
                "Block parameter conflict. Must provide either hash or index but not both"
            }
            ApiError::TransactionIsPending => "Transaction is pending",
            ApiError::NetworkIdentifierMismatch => "Network identifier doesn't match",
            ApiError::ChainIdMismatch => "Chain Id doesn't match",
            ApiError::DeserializationFailed(_) => "Deserialization failed",
            ApiError::InvalidTransferOperations(_) => "Invalid operations for a transfer",
            ApiError::AccountNotFound(_) => "Account not found",
            ApiError::InvalidSignatureType => "Invalid signature type",
            ApiError::InvalidMaxGasFees => "Invalid max gas fee",
            ApiError::MaxGasFeeTooLow => "Max fee is lower than the estimated cost of the transaction",
            ApiError::InvalidGasMultiplier => "Invalid gas multiplier",
            ApiError::InvalidOperations(_) => "Invalid operations",
            ApiError::MissingPayloadMetadata => "Payload metadata is missing",
            ApiError::UnsupportedCurrency(_) => "Currency is unsupported",
            ApiError::UnsupportedSignatureCount(_) => "Number of signatures is not supported",
            ApiError::NodeIsOffline => "This API is unavailable for the node because he's offline",
            ApiError::BlockNotFound(_) => "Block is missing events",
            ApiError::TransactionParseError(_) => "Transaction failed to parse",
            ApiError::InternalError(_) => "Internal error",
            ApiError::ResourceNotFound(_) => "Resource not found",
            ApiError::ModuleNotFound(_) => "Module not found",
            ApiError::StructFieldNotFound(_) => "Struct field not found",
            ApiError::VersionNotFound(_) => "Version not found",
            ApiError::TransactionNotFound(_) => "Transaction not found",
            ApiError::TableItemNotFound(_) => "Table item not found",
            ApiError::VersionPruned(_) => "Version pruned",
            ApiError::BlockPruned(_) => "Block pruned",
            ApiError::InvalidInput(_) => "Invalid input",
            ApiError::InvalidTransactionUpdate(_) => "Invalid transaction update.  Can only update gas unit price",
            ApiError::SequenceNumberTooOld(_) => "Sequence number too old.  Please create a new transaction with an updated sequence number",
            ApiError::VmError(_) => "Transaction submission failed due to VM error",
            ApiError::MempoolIsFull(_) => "Mempool is full all accounts",
            ApiError::GasEstimationFailed(_) => "Gas estimation failed",
        }
    }

    pub fn details(self) -> Option<ErrorDetails> {
        match self {
            ApiError::DeserializationFailed(inner) => inner,
            ApiError::InvalidTransferOperations(inner) => inner.map(|inner| inner.to_string()),
            ApiError::UnsupportedCurrency(inner) => inner,
            ApiError::UnsupportedSignatureCount(inner) => inner.map(|inner| inner.to_string()),
            ApiError::TransactionParseError(inner) => inner,
            ApiError::InvalidOperations(inner) => inner,
            ApiError::InternalError(inner) => inner,
            ApiError::AccountNotFound(inner) => inner,
            ApiError::ResourceNotFound(inner) => inner,
            ApiError::ModuleNotFound(inner) => inner,
            ApiError::StructFieldNotFound(inner) => inner,
            ApiError::VersionNotFound(inner) => inner,
            ApiError::TransactionNotFound(inner) => inner,
            ApiError::TableItemNotFound(inner) => inner,
            ApiError::BlockNotFound(inner) => inner,
            ApiError::VersionPruned(inner) => inner,
            ApiError::BlockPruned(inner) => inner,
            ApiError::InvalidInput(inner) => inner,
            ApiError::InvalidTransactionUpdate(inner) => inner,
            ApiError::SequenceNumberTooOld(inner) => inner,
            ApiError::VmError(inner) => inner,
            ApiError::MempoolIsFull(inner) => inner,
            ApiError::GasEstimationFailed(inner) => inner,
            _ => None,
        }
        .map(|details| ErrorDetails { details })
    }

    pub fn deserialization_failed(type_: &str) -> ApiError {
        ApiError::DeserializationFailed(Some(type_.to_string()))
    }

    pub fn into_error(self) -> types::Error {
        self.into()
    }
}

impl From<ApiError> for types::Error {
    fn from(error: ApiError) -> Self {
        let message = error.message().to_string();
        let code = error.code();
        let retriable = error.retriable();
        let details = error.details();
        types::Error {
            message,
            code,
            retriable,
            details,
        }
    }
}

impl From<RestError> for ApiError {
    fn from(err: RestError) -> Self {
        match err {
            RestError::Api(err) => match err.error.error_code {
                AptosErrorCode::AccountNotFound => {
                    ApiError::AccountNotFound(Some(err.error.message))
                }
                AptosErrorCode::ResourceNotFound => {
                    ApiError::ResourceNotFound(Some(err.error.message))
                }
                AptosErrorCode::ModuleNotFound => ApiError::ModuleNotFound(Some(err.error.message)),
                AptosErrorCode::StructFieldNotFound => {
                    ApiError::StructFieldNotFound(Some(err.error.message))
                }
                AptosErrorCode::VersionNotFound => {
                    ApiError::VersionNotFound(Some(err.error.message))
                }
                AptosErrorCode::TransactionNotFound => {
                    ApiError::TransactionNotFound(Some(err.error.message))
                }
                AptosErrorCode::TableItemNotFound => {
                    ApiError::TableItemNotFound(Some(err.error.message))
                }
                AptosErrorCode::BlockNotFound => ApiError::BlockNotFound(Some(err.error.message)),
                AptosErrorCode::VersionPruned => ApiError::VersionPruned(Some(err.error.message)),
                AptosErrorCode::BlockPruned => ApiError::BlockPruned(Some(err.error.message)),
                AptosErrorCode::InvalidInput => ApiError::InvalidInput(Some(err.error.message)),
                AptosErrorCode::InvalidTransactionUpdate => {
                    ApiError::InvalidInput(Some(err.error.message))
                }
                AptosErrorCode::SequenceNumberTooOld => {
                    ApiError::SequenceNumberTooOld(Some(err.error.message))
                }
                AptosErrorCode::VmError => ApiError::VmError(Some(err.error.message)),
                AptosErrorCode::HealthCheckFailed => {
                    ApiError::InternalError(Some(err.error.message))
                }
                AptosErrorCode::MempoolIsFull => ApiError::MempoolIsFull(Some(err.error.message)),
                AptosErrorCode::WebFrameworkError => {
                    ApiError::InternalError(Some(err.error.message))
                }
                AptosErrorCode::BcsNotSupported => ApiError::InvalidInput(Some(err.error.message)),
                AptosErrorCode::InternalError => ApiError::InternalError(Some(err.error.message)),
                AptosErrorCode::ApiDisabled => ApiError::InternalError(Some(err.error.message)),
            },
            RestError::Bcs(_) => ApiError::DeserializationFailed(None),
            RestError::Json(_) => ApiError::DeserializationFailed(None),
            RestError::WebClient(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::UrlParse(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::Timeout(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::Unknown(err) => ApiError::InternalError(Some(err.to_string())),
        }
    }
}

impl From<AccountAddressParseError> for ApiError {
    fn from(err: AccountAddressParseError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<FromHexError> for ApiError {
    fn from(err: FromHexError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<bcs::Error> for ApiError {
    fn from(err: bcs::Error) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<anyhow::Error> for ApiError {
    fn from(err: anyhow::Error) -> Self {
        ApiError::InternalError(Some(err.to_string()))
    }
}

impl From<std::num::ParseIntError> for ApiError {
    fn from(err: std::num::ParseIntError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl warp::reject::Reject for ApiError {}

impl Reply for ApiError {
    fn into_response(self) -> warp::reply::Response {
        warp::reply::json(&self.into_error()).into_response()
    }
}
<commit_msg>[aptos-rosetta] Make all errors 500s<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{types, types::ErrorDetails};
use aptos_rest_client::aptos_api_types::AptosErrorCode;
use aptos_rest_client::error::RestError;
use hex::FromHexError;
use move_deps::move_core_types::account_address::AccountAddressParseError;
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;
use warp::{http::StatusCode, reply::Reply};

pub type ApiResult<T> = Result<T, ApiError>;

#[derive(Debug, Deserialize, Serialize)]
pub enum ApiError {
    BlockParameterConflict,
    TransactionIsPending,
    NetworkIdentifierMismatch,
    ChainIdMismatch,
    DeserializationFailed(Option<String>),
    InvalidTransferOperations(Option<&'static str>),
    InvalidSignatureType,
    InvalidMaxGasFees,
    MaxGasFeeTooLow,
    InvalidGasMultiplier,
    GasEstimationFailed(Option<String>),
    InvalidOperations(Option<String>),
    MissingPayloadMetadata,
    UnsupportedCurrency(Option<String>),
    UnsupportedSignatureCount(Option<usize>),
    NodeIsOffline,
    TransactionParseError(Option<String>),
    InternalError(Option<String>),

    // Below here are codes directly from the REST API
    AccountNotFound(Option<String>),
    ResourceNotFound(Option<String>),
    ModuleNotFound(Option<String>),
    StructFieldNotFound(Option<String>),
    VersionNotFound(Option<String>),
    TransactionNotFound(Option<String>),
    TableItemNotFound(Option<String>),
    BlockNotFound(Option<String>),
    VersionPruned(Option<String>),
    BlockPruned(Option<String>),
    InvalidInput(Option<String>),
    InvalidTransactionUpdate(Option<String>),
    SequenceNumberTooOld(Option<String>),
    VmError(Option<String>),
    MempoolIsFull(Option<String>),
}

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

impl std::error::Error for ApiError {}

impl ApiError {
    pub fn all() -> Vec<ApiError> {
        use ApiError::*;
        vec![
            BlockParameterConflict,
            TransactionIsPending,
            NetworkIdentifierMismatch,
            ChainIdMismatch,
            DeserializationFailed(None),
            InvalidTransferOperations(None),
            InvalidSignatureType,
            InvalidMaxGasFees,
            MaxGasFeeTooLow,
            InvalidGasMultiplier,
            GasEstimationFailed(None),
            InvalidOperations(None),
            MissingPayloadMetadata,
            UnsupportedCurrency(None),
            UnsupportedSignatureCount(None),
            NodeIsOffline,
            TransactionParseError(None),
            InternalError(None),
            AccountNotFound(None),
            ResourceNotFound(None),
            ModuleNotFound(None),
            StructFieldNotFound(None),
            VersionNotFound(None),
            TransactionNotFound(None),
            TableItemNotFound(None),
            BlockNotFound(None),
            VersionPruned(None),
            BlockPruned(None),
            InvalidInput(None),
            InvalidTransactionUpdate(None),
            SequenceNumberTooOld(None),
            VmError(None),
            MempoolIsFull(None),
        ]
    }

    pub fn code(&self) -> u32 {
        use ApiError::*;
        match self {
            BlockParameterConflict => 0,
            TransactionIsPending => 1,
            NetworkIdentifierMismatch => 2,
            ChainIdMismatch => 3,
            DeserializationFailed(_) => 4,
            InvalidTransferOperations(_) => 5,
            InvalidSignatureType => 6,
            InvalidMaxGasFees => 7,
            MaxGasFeeTooLow => 8,
            InvalidGasMultiplier => 9,
            InvalidOperations(_) => 10,
            MissingPayloadMetadata => 11,
            UnsupportedCurrency(_) => 12,
            UnsupportedSignatureCount(_) => 13,
            NodeIsOffline => 14,
            TransactionParseError(_) => 15,
            GasEstimationFailed(_) => 16,
            InternalError(_) => 17,
            AccountNotFound(_) => 18,
            ResourceNotFound(_) => 19,
            ModuleNotFound(_) => 20,
            StructFieldNotFound(_) => 21,
            VersionNotFound(_) => 22,
            TransactionNotFound(_) => 23,
            TableItemNotFound(_) => 24,
            BlockNotFound(_) => 25,
            VersionPruned(_) => 26,
            BlockPruned(_) => 27,
            InvalidInput(_) => 28,
            InvalidTransactionUpdate(_) => 29,
            SequenceNumberTooOld(_) => 30,
            VmError(_) => 31,
            MempoolIsFull(_) => 32,
        }
    }

    pub fn retriable(&self) -> bool {
        use ApiError::*;
        matches!(
            self,
            AccountNotFound(_) | BlockNotFound(_) | MempoolIsFull(_) | GasEstimationFailed(_)
        )
    }

    pub fn status_code(&self) -> StatusCode {
        // Per Rosetta guidelines, all errors are 500s
        StatusCode::INTERNAL_SERVER_ERROR
    }

    /// This value must be fixed, so it's all static strings
    pub fn message(&self) -> &'static str {
        match self {
            ApiError::BlockParameterConflict => {
                "Block parameter conflict. Must provide either hash or index but not both"
            }
            ApiError::TransactionIsPending => "Transaction is pending",
            ApiError::NetworkIdentifierMismatch => "Network identifier doesn't match",
            ApiError::ChainIdMismatch => "Chain Id doesn't match",
            ApiError::DeserializationFailed(_) => "Deserialization failed",
            ApiError::InvalidTransferOperations(_) => "Invalid operations for a transfer",
            ApiError::AccountNotFound(_) => "Account not found",
            ApiError::InvalidSignatureType => "Invalid signature type",
            ApiError::InvalidMaxGasFees => "Invalid max gas fee",
            ApiError::MaxGasFeeTooLow => "Max fee is lower than the estimated cost of the transaction",
            ApiError::InvalidGasMultiplier => "Invalid gas multiplier",
            ApiError::InvalidOperations(_) => "Invalid operations",
            ApiError::MissingPayloadMetadata => "Payload metadata is missing",
            ApiError::UnsupportedCurrency(_) => "Currency is unsupported",
            ApiError::UnsupportedSignatureCount(_) => "Number of signatures is not supported",
            ApiError::NodeIsOffline => "This API is unavailable for the node because he's offline",
            ApiError::BlockNotFound(_) => "Block is missing events",
            ApiError::TransactionParseError(_) => "Transaction failed to parse",
            ApiError::InternalError(_) => "Internal error",
            ApiError::ResourceNotFound(_) => "Resource not found",
            ApiError::ModuleNotFound(_) => "Module not found",
            ApiError::StructFieldNotFound(_) => "Struct field not found",
            ApiError::VersionNotFound(_) => "Version not found",
            ApiError::TransactionNotFound(_) => "Transaction not found",
            ApiError::TableItemNotFound(_) => "Table item not found",
            ApiError::VersionPruned(_) => "Version pruned",
            ApiError::BlockPruned(_) => "Block pruned",
            ApiError::InvalidInput(_) => "Invalid input",
            ApiError::InvalidTransactionUpdate(_) => "Invalid transaction update.  Can only update gas unit price",
            ApiError::SequenceNumberTooOld(_) => "Sequence number too old.  Please create a new transaction with an updated sequence number",
            ApiError::VmError(_) => "Transaction submission failed due to VM error",
            ApiError::MempoolIsFull(_) => "Mempool is full all accounts",
            ApiError::GasEstimationFailed(_) => "Gas estimation failed",
        }
    }

    pub fn details(self) -> Option<ErrorDetails> {
        match self {
            ApiError::DeserializationFailed(inner) => inner,
            ApiError::InvalidTransferOperations(inner) => inner.map(|inner| inner.to_string()),
            ApiError::UnsupportedCurrency(inner) => inner,
            ApiError::UnsupportedSignatureCount(inner) => inner.map(|inner| inner.to_string()),
            ApiError::TransactionParseError(inner) => inner,
            ApiError::InvalidOperations(inner) => inner,
            ApiError::InternalError(inner) => inner,
            ApiError::AccountNotFound(inner) => inner,
            ApiError::ResourceNotFound(inner) => inner,
            ApiError::ModuleNotFound(inner) => inner,
            ApiError::StructFieldNotFound(inner) => inner,
            ApiError::VersionNotFound(inner) => inner,
            ApiError::TransactionNotFound(inner) => inner,
            ApiError::TableItemNotFound(inner) => inner,
            ApiError::BlockNotFound(inner) => inner,
            ApiError::VersionPruned(inner) => inner,
            ApiError::BlockPruned(inner) => inner,
            ApiError::InvalidInput(inner) => inner,
            ApiError::InvalidTransactionUpdate(inner) => inner,
            ApiError::SequenceNumberTooOld(inner) => inner,
            ApiError::VmError(inner) => inner,
            ApiError::MempoolIsFull(inner) => inner,
            ApiError::GasEstimationFailed(inner) => inner,
            _ => None,
        }
        .map(|details| ErrorDetails { details })
    }

    pub fn deserialization_failed(type_: &str) -> ApiError {
        ApiError::DeserializationFailed(Some(type_.to_string()))
    }

    pub fn into_error(self) -> types::Error {
        self.into()
    }
}

impl From<ApiError> for types::Error {
    fn from(error: ApiError) -> Self {
        let message = error.message().to_string();
        let code = error.code();
        let retriable = error.retriable();
        let details = error.details();
        types::Error {
            message,
            code,
            retriable,
            details,
        }
    }
}

impl From<RestError> for ApiError {
    fn from(err: RestError) -> Self {
        match err {
            RestError::Api(err) => match err.error.error_code {
                AptosErrorCode::AccountNotFound => {
                    ApiError::AccountNotFound(Some(err.error.message))
                }
                AptosErrorCode::ResourceNotFound => {
                    ApiError::ResourceNotFound(Some(err.error.message))
                }
                AptosErrorCode::ModuleNotFound => ApiError::ModuleNotFound(Some(err.error.message)),
                AptosErrorCode::StructFieldNotFound => {
                    ApiError::StructFieldNotFound(Some(err.error.message))
                }
                AptosErrorCode::VersionNotFound => {
                    ApiError::VersionNotFound(Some(err.error.message))
                }
                AptosErrorCode::TransactionNotFound => {
                    ApiError::TransactionNotFound(Some(err.error.message))
                }
                AptosErrorCode::TableItemNotFound => {
                    ApiError::TableItemNotFound(Some(err.error.message))
                }
                AptosErrorCode::BlockNotFound => ApiError::BlockNotFound(Some(err.error.message)),
                AptosErrorCode::VersionPruned => ApiError::VersionPruned(Some(err.error.message)),
                AptosErrorCode::BlockPruned => ApiError::BlockPruned(Some(err.error.message)),
                AptosErrorCode::InvalidInput => ApiError::InvalidInput(Some(err.error.message)),
                AptosErrorCode::InvalidTransactionUpdate => {
                    ApiError::InvalidInput(Some(err.error.message))
                }
                AptosErrorCode::SequenceNumberTooOld => {
                    ApiError::SequenceNumberTooOld(Some(err.error.message))
                }
                AptosErrorCode::VmError => ApiError::VmError(Some(err.error.message)),
                AptosErrorCode::HealthCheckFailed => {
                    ApiError::InternalError(Some(err.error.message))
                }
                AptosErrorCode::MempoolIsFull => ApiError::MempoolIsFull(Some(err.error.message)),
                AptosErrorCode::WebFrameworkError => {
                    ApiError::InternalError(Some(err.error.message))
                }
                AptosErrorCode::BcsNotSupported => ApiError::InvalidInput(Some(err.error.message)),
                AptosErrorCode::InternalError => ApiError::InternalError(Some(err.error.message)),
                AptosErrorCode::ApiDisabled => ApiError::InternalError(Some(err.error.message)),
            },
            RestError::Bcs(_) => ApiError::DeserializationFailed(None),
            RestError::Json(_) => ApiError::DeserializationFailed(None),
            RestError::WebClient(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::UrlParse(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::Timeout(err) => ApiError::InternalError(Some(err.to_string())),
            RestError::Unknown(err) => ApiError::InternalError(Some(err.to_string())),
        }
    }
}

impl From<AccountAddressParseError> for ApiError {
    fn from(err: AccountAddressParseError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<FromHexError> for ApiError {
    fn from(err: FromHexError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<bcs::Error> for ApiError {
    fn from(err: bcs::Error) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl From<anyhow::Error> for ApiError {
    fn from(err: anyhow::Error) -> Self {
        ApiError::InternalError(Some(err.to_string()))
    }
}

impl From<std::num::ParseIntError> for ApiError {
    fn from(err: std::num::ParseIntError) -> Self {
        ApiError::DeserializationFailed(Some(err.to_string()))
    }
}

impl warp::reject::Reject for ApiError {}

impl Reply for ApiError {
    fn into_response(self) -> warp::reply::Response {
        warp::reply::json(&self.into_error()).into_response()
    }
}
<|endoftext|>


<commit_before>//! In certain situations, rust automatically inserts derefs as necessary: for
//! example, field accesses `foo.bar` still work when `foo` is actually a
//! reference to a type with the field `bar`. This is an approximation of the
//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs).

use std::iter::successors;

use log::{info, warn};

use crate::{HirDatabase, Name, Resolver};
use super::{traits::Solution, Ty, Canonical};

pub(crate) fn autoderef<'a>(
    db: &'a impl HirDatabase,
    resolver: &'a Resolver,
    ty: Canonical<Ty>,
) -> impl Iterator<Item = Canonical<Ty>> + 'a {
    successors(Some(ty), move |ty| deref(db, resolver, ty))
}

pub(crate) fn deref(
    db: &impl HirDatabase,
    resolver: &Resolver,
    ty: &Canonical<Ty>,
) -> Option<Canonical<Ty>> {
    if let Some(derefed) = ty.value.builtin_deref() {
        Some(Canonical { value: derefed, num_vars: ty.num_vars })
    } else {
        deref_by_trait(db, resolver, ty)
    }
}

fn deref_by_trait(
    db: &impl HirDatabase,
    resolver: &Resolver,
    ty: &Canonical<Ty>,
) -> Option<Canonical<Ty>> {
    let krate = resolver.krate()?;
    let deref_trait = match db.lang_item(krate, "deref".into())? {
        crate::lang_item::LangItemTarget::Trait(t) => t,
        _ => return None,
    };
    let target = deref_trait.associated_type_by_name(db, Name::target())?;

    // FIXME we should check that Deref has no type parameters, because we assume it below
    // FIXME make the Canonical handling nicer

    let projection = super::traits::ProjectionPredicate {
        ty: Ty::Bound(0),
        projection_ty: super::ProjectionTy {
            associated_ty: target,
            parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
        },
    };

    let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: projection };

    let solution = db.normalize(krate, canonical)?;

    match &solution {
        Solution::Unique(vars) => {
            // FIXME: vars may contain solutions for any inference variables
            // that happened to be inside ty. To correctly handle these, we
            // would have to pass the solution up to the inference context, but
            // that requires a larger refactoring (especially if the deref
            // happens during method resolution). So for the moment, we just
            // check that we're not in the situation we're we would actually
            // need to handle the values of the additional variables, i.e.
            // they're just being 'passed through'. In the 'standard' case where
            // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be
            // the case.
            for i in 1..vars.0.num_vars {
                if vars.0.value[i] != Ty::Bound((i - 1) as u32) {
                    warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution);
                    return None;
                }
            }
            Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars })
        }
        Solution::Ambig(_) => {
            info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution);
            None
        }
    }
}
<commit_msg>Check that Deref has the right number of parameters<commit_after>//! In certain situations, rust automatically inserts derefs as necessary: for
//! example, field accesses `foo.bar` still work when `foo` is actually a
//! reference to a type with the field `bar`. This is an approximation of the
//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs).

use std::iter::successors;

use log::{info, warn};

use crate::{HirDatabase, Name, Resolver, HasGenericParams};
use super::{traits::Solution, Ty, Canonical};

pub(crate) fn autoderef<'a>(
    db: &'a impl HirDatabase,
    resolver: &'a Resolver,
    ty: Canonical<Ty>,
) -> impl Iterator<Item = Canonical<Ty>> + 'a {
    successors(Some(ty), move |ty| deref(db, resolver, ty))
}

pub(crate) fn deref(
    db: &impl HirDatabase,
    resolver: &Resolver,
    ty: &Canonical<Ty>,
) -> Option<Canonical<Ty>> {
    if let Some(derefed) = ty.value.builtin_deref() {
        Some(Canonical { value: derefed, num_vars: ty.num_vars })
    } else {
        deref_by_trait(db, resolver, ty)
    }
}

fn deref_by_trait(
    db: &impl HirDatabase,
    resolver: &Resolver,
    ty: &Canonical<Ty>,
) -> Option<Canonical<Ty>> {
    let krate = resolver.krate()?;
    let deref_trait = match db.lang_item(krate, "deref".into())? {
        crate::lang_item::LangItemTarget::Trait(t) => t,
        _ => return None,
    };
    let target = deref_trait.associated_type_by_name(db, Name::target())?;

    if target.generic_params(db).count_params_including_parent() != 1 {
        // the Target type + Deref trait should only have one generic parameter,
        // namely Deref's Self type
        return None;
    }

    // FIXME make the Canonical handling nicer

    let projection = super::traits::ProjectionPredicate {
        ty: Ty::Bound(0),
        projection_ty: super::ProjectionTy {
            associated_ty: target,
            parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
        },
    };

    let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: projection };

    let solution = db.normalize(krate, canonical)?;

    match &solution {
        Solution::Unique(vars) => {
            // FIXME: vars may contain solutions for any inference variables
            // that happened to be inside ty. To correctly handle these, we
            // would have to pass the solution up to the inference context, but
            // that requires a larger refactoring (especially if the deref
            // happens during method resolution). So for the moment, we just
            // check that we're not in the situation we're we would actually
            // need to handle the values of the additional variables, i.e.
            // they're just being 'passed through'. In the 'standard' case where
            // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be
            // the case.
            for i in 1..vars.0.num_vars {
                if vars.0.value[i] != Ty::Bound((i - 1) as u32) {
                    warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution);
                    return None;
                }
            }
            Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars })
        }
        Solution::Ambig(_) => {
            info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution);
            None
        }
    }
}
<|endoftext|>


<commit_before>//! Unix Domain Sockets for Tokio.
//!
//! This crate provides APIs for using Unix Domain Sockets with Tokio.

#![cfg(unix)]
#![doc(html_root_url = "https://docs.rs/tokio-uds/0.2.0")]
#![deny(missing_docs, warnings, missing_debug_implementations)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate iovec;
extern crate libc;
extern crate log;
extern crate mio;
extern crate mio_uds;
extern crate tokio_io;
extern crate tokio_reactor;

mod datagram;
mod incoming;
mod listener;
mod recv_dgram;
mod send_dgram;
mod stream;
mod ucred;

pub use datagram::UnixDatagram;
pub use incoming::Incoming;
pub use listener::UnixListener;
pub use recv_dgram::RecvDgram;
pub use send_dgram::SendDgram;
pub use stream::UnixStream;
pub use ucred::UCred;
<commit_msg>Reexport tokio_uds::ConnectFuture (#430)<commit_after>//! Unix Domain Sockets for Tokio.
//!
//! This crate provides APIs for using Unix Domain Sockets with Tokio.

#![cfg(unix)]
#![doc(html_root_url = "https://docs.rs/tokio-uds/0.2.0")]
#![deny(missing_docs, warnings, missing_debug_implementations)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate iovec;
extern crate libc;
extern crate log;
extern crate mio;
extern crate mio_uds;
extern crate tokio_io;
extern crate tokio_reactor;

mod datagram;
mod incoming;
mod listener;
mod recv_dgram;
mod send_dgram;
mod stream;
mod ucred;

pub use datagram::UnixDatagram;
pub use incoming::Incoming;
pub use listener::UnixListener;
pub use recv_dgram::RecvDgram;
pub use send_dgram::SendDgram;
pub use stream::{UnixStream, ConnectFuture};
pub use ucred::UCred;
<|endoftext|>


<commit_before>use wordy::answer;

#[test]
fn just_a_number() {
    let command = "What is 5?";
    assert_eq!(Some(5), answer(command));
}

#[test]
#[ignore]
fn addition() {
    let command = "What is 1 plus 1?";
    assert_eq!(Some(2), answer(command));
}

#[test]
#[ignore]
fn more_addition() {
    let command = "What is 53 plus 2?";
    assert_eq!(Some(55), answer(command));
}

#[test]
#[ignore]
fn addition_with_negative_numbers() {
    let command = "What is -1 plus -10?";
    assert_eq!(Some(-11), answer(command));
}

#[test]
#[ignore]
fn large_addition() {
    let command = "What is 123 plus 45678?";
    assert_eq!(Some(45801), answer(command));
}

#[test]
#[ignore]
fn subtraction() {
    let command = "What is 4 minus -12?";
    assert_eq!(Some(16), answer(command));
}

#[test]
#[ignore]
fn multiplication() {
    let command = "What is -3 multiplied by 25?";
    assert_eq!(Some(-75), answer(command));
}

#[test]
#[ignore]
fn division() {
    let command = "What is 33 divided by -3?";
    assert_eq!(Some(-11), answer(command));
}

#[test]
#[ignore]
fn multiple_additions() {
    let command = "What is 1 plus 1 plus 1?";
    assert_eq!(Some(3), answer(command));
}

#[test]
#[ignore]
fn addition_and_subtraction() {
    let command = "What is 1 plus 5 minus -2?";
    assert_eq!(Some(8), answer(command));
}

#[test]
#[ignore]
fn multiple_subtraction() {
    let command = "What is 20 minus 4 minus 13?";
    assert_eq!(Some(3), answer(command));
}

#[test]
#[ignore]
fn subtraction_then_addition() {
    let command = "What is 17 minus 6 plus 3?";
    assert_eq!(Some(14), answer(command));
}

#[test]
#[ignore]
fn multiple_multiplications() {
    let command = "What is 2 multiplied by -2 multiplied by 3?";
    assert_eq!(Some(-12), answer(command));
}

#[test]
#[ignore]
fn addition_and_multiplication() {
    let command = "What is -3 plus 7 multiplied by -2?";
    assert_eq!(Some(-8), answer(command));
}

#[test]
#[ignore]
fn multiple_divisions() {
    let command = "What is -12 divided by 2 divided by -3?";
    assert_eq!(Some(2), answer(command));
}

#[test]
#[ignore]
fn unknown_operation() {
    let command = "What is 52 cubed?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn non_math_question() {
    let command = "Who is the President of the United States?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_problem_missing_an_operand() {
    let command = "What is 1 plus?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_problem_with_no_operands_or_operators() {
    let command = "What is?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_two_operations_in_a_row() {
    let command = "What is 1 plus plus 2?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_two_numbers_in_a_row() {
    let command = "What is 1 plus 2 1?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_postfix_notation() {
    let command = "What is 1 2 plus?";
    assert!(answer(command).is_none());
}

#[test]
#[ignore]
fn reject_prefix_notation() {
    let command = "What is plus 1 2?";
    assert!(answer(command).is_none());
}
<commit_msg>Wordy: Prefer assert_eq!<commit_after>use wordy::answer;

#[test]
fn just_a_number() {
    let command = "What is 5?";
    assert_eq!(Some(5), answer(command));
}

#[test]
#[ignore]
fn addition() {
    let command = "What is 1 plus 1?";
    assert_eq!(Some(2), answer(command));
}

#[test]
#[ignore]
fn more_addition() {
    let command = "What is 53 plus 2?";
    assert_eq!(Some(55), answer(command));
}

#[test]
#[ignore]
fn addition_with_negative_numbers() {
    let command = "What is -1 plus -10?";
    assert_eq!(Some(-11), answer(command));
}

#[test]
#[ignore]
fn large_addition() {
    let command = "What is 123 plus 45678?";
    assert_eq!(Some(45801), answer(command));
}

#[test]
#[ignore]
fn subtraction() {
    let command = "What is 4 minus -12?";
    assert_eq!(Some(16), answer(command));
}

#[test]
#[ignore]
fn multiplication() {
    let command = "What is -3 multiplied by 25?";
    assert_eq!(Some(-75), answer(command));
}

#[test]
#[ignore]
fn division() {
    let command = "What is 33 divided by -3?";
    assert_eq!(Some(-11), answer(command));
}

#[test]
#[ignore]
fn multiple_additions() {
    let command = "What is 1 plus 1 plus 1?";
    assert_eq!(Some(3), answer(command));
}

#[test]
#[ignore]
fn addition_and_subtraction() {
    let command = "What is 1 plus 5 minus -2?";
    assert_eq!(Some(8), answer(command));
}

#[test]
#[ignore]
fn multiple_subtraction() {
    let command = "What is 20 minus 4 minus 13?";
    assert_eq!(Some(3), answer(command));
}

#[test]
#[ignore]
fn subtraction_then_addition() {
    let command = "What is 17 minus 6 plus 3?";
    assert_eq!(Some(14), answer(command));
}

#[test]
#[ignore]
fn multiple_multiplications() {
    let command = "What is 2 multiplied by -2 multiplied by 3?";
    assert_eq!(Some(-12), answer(command));
}

#[test]
#[ignore]
fn addition_and_multiplication() {
    let command = "What is -3 plus 7 multiplied by -2?";
    assert_eq!(Some(-8), answer(command));
}

#[test]
#[ignore]
fn multiple_divisions() {
    let command = "What is -12 divided by 2 divided by -3?";
    assert_eq!(Some(2), answer(command));
}

#[test]
#[ignore]
fn unknown_operation() {
    let command = "What is 52 cubed?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn non_math_question() {
    let command = "Who is the President of the United States?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_problem_missing_an_operand() {
    let command = "What is 1 plus?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_problem_with_no_operands_or_operators() {
    let command = "What is?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_two_operations_in_a_row() {
    let command = "What is 1 plus plus 2?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_two_numbers_in_a_row() {
    let command = "What is 1 plus 2 1?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_postfix_notation() {
    let command = "What is 1 2 plus?";
    assert_eq!(None, answer(command));
}

#[test]
#[ignore]
fn reject_prefix_notation() {
    let command = "What is plus 1 2?";
    assert_eq!(None, answer(command));
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate procrs;
use getopts::Options;
use std::env;
use std::collections::HashMap;
use procrs::*;

fn main() {
  let prog_opts = match parse_args() {
    Some(t) => { t }
    None => { return; }
  };
  let proc_query = match prog_opts.query {
    Some(ref q_text) => create_query(&q_text).unwrap(),
    None => ProcQuery::NoneQuery
  };
  match prog_opts.tree {
    false => {
      for proc_struct in ProcIter::new_query(proc_query).unwrap() {
        println!("{:?}", proc_struct);
      }
    },

    true => {
      let proc_map: HashMap<_, _> =
        ProcIter::new().unwrap()
        .map(|proc_struct|
          (proc_struct.status.pid, proc_struct)
        ).collect();

      let mut child_procs = HashMap::new();
      let mut proc_list = Vec::new();

      for (pid, proc_struct) in &proc_map {
        proc_list.push(pid);
        let ppid = proc_struct.status.ppid;
        child_procs.entry(ppid)
          .or_insert(Vec::new())
          .push(proc_struct);
      }
      proc_list.sort();
      let pid = prog_opts.query.and_then(|p| p.parse().ok()).unwrap_or(1);;
      let mut pid_procs = Vec::new();

      let start_procs = match proc_map.get(&pid) {
        Some(proc_struct) => {
          pid_procs.push(proc_struct);
          &pid_procs
        },
        None => child_procs.get(&pid).expect("Invalid pid")
      };

      print_tree(&child_procs, start_procs, "".to_string());
    }
  }
}

fn print_tree(child_procs: &HashMap<TaskId, Vec<&Proc>>,
              level_procs: &Vec<&Proc>, prefix: String) {
  let mut proc_list = level_procs.to_vec();
  proc_list.sort();
  for proc_struct in proc_list {
    let pid = &proc_struct.status.pid;

    println!("{}{}", prefix, proc_struct.status.name);
    let child_list = child_procs.get(pid);
    if let Some(v) = child_list {
      print_tree(child_procs, v, format!("{}{}", "  ", prefix));
    }
  }
}

struct ProgOpts {
  query: Option<String>,
  tree: bool
}

fn parse_args() -> Option<ProgOpts> {
  let args: Vec<String> = env::args().collect();
  let program = args[0].clone();
  let mut prog_opts = ProgOpts{
    query: None,
    tree: false
  };

  let mut opts = Options::new();
  opts.optflag("h", "help", "Print help");
  opts.optflag("t", "tree", "Print tree");

  let matches = match opts.parse(&args[1..]) {
    Ok(m) => {m}
    Err(f) => { panic!(f.to_string()) }
  };
  if matches.opt_present("h") {
    print_usage(&program, opts);
    return None;
  }
  if matches.opt_present("t") {
    prog_opts.tree = true;
  }
  if !matches.free.is_empty() {
    prog_opts.query = Some(matches.free[0].clone());
  };
  Some(prog_opts)
}

fn print_usage(program: &str, opts: Options) {
  let brief = format!("Usage: {} query [options]", program);
  print!("{}", opts.usage(&brief));
}
<commit_msg>Add basic psq list output<commit_after>extern crate getopts;
extern crate procrs;
use getopts::Options;
use std::env;
use std::collections::HashMap;
use procrs::*;

fn main() {
  let prog_opts = match parse_args() {
    Some(t) => { t }
    None => { return; }
  };
  let proc_query = match prog_opts.query {
    Some(ref q_text) => create_query(&q_text).unwrap(),
    None => ProcQuery::NoneQuery
  };
  match prog_opts.tree {
    false => {
      println!("Pid\tPpid\tName\tCmd");
      for proc_struct in ProcIter::new_query(proc_query).unwrap() {
        println!("{}\t{}\t{}\t{}", proc_struct.status.pid, proc_struct.status.ppid,
                 proc_struct.status.name, proc_struct.cmdline.join(" "));
      }
    },

    true => {
      let proc_map: HashMap<_, _> =
        ProcIter::new().unwrap()
        .map(|proc_struct|
          (proc_struct.status.pid, proc_struct)
        ).collect();

      let mut child_procs = HashMap::new();
      let mut proc_list = Vec::new();

      for (pid, proc_struct) in &proc_map {
        proc_list.push(pid);
        let ppid = proc_struct.status.ppid;
        child_procs.entry(ppid)
          .or_insert(Vec::new())
          .push(proc_struct);
      }
      proc_list.sort();
      let pid = prog_opts.query.and_then(|p| p.parse().ok()).unwrap_or(1);;
      let mut pid_procs = Vec::new();

      let start_procs = match proc_map.get(&pid) {
        Some(proc_struct) => {
          pid_procs.push(proc_struct);
          &pid_procs
        },
        None => child_procs.get(&pid).expect("Invalid pid")
      };

      print_tree(&child_procs, start_procs, "".to_string());
    }
  }
}

fn print_tree(child_procs: &HashMap<TaskId, Vec<&Proc>>,
              level_procs: &Vec<&Proc>, prefix: String) {
  let mut proc_list = level_procs.to_vec();
  proc_list.sort();
  for proc_struct in proc_list {
    let pid = &proc_struct.status.pid;

    println!("{}{}", prefix, proc_struct.status.name);
    let child_list = child_procs.get(pid);
    if let Some(v) = child_list {
      print_tree(child_procs, v, format!("{}{}", "  ", prefix));
    }
  }
}

struct ProgOpts {
  query: Option<String>,
  tree: bool
}

fn parse_args() -> Option<ProgOpts> {
  let args: Vec<String> = env::args().collect();
  let program = args[0].clone();
  let mut prog_opts = ProgOpts{
    query: None,
    tree: false
  };

  let mut opts = Options::new();
  opts.optflag("h", "help", "Print help");
  opts.optflag("t", "tree", "Print tree");

  let matches = match opts.parse(&args[1..]) {
    Ok(m) => {m}
    Err(f) => { panic!(f.to_string()) }
  };
  if matches.opt_present("h") {
    print_usage(&program, opts);
    return None;
  }
  if matches.opt_present("t") {
    prog_opts.tree = true;
  }
  if !matches.free.is_empty() {
    prog_opts.query = Some(matches.free[0].clone());
  };
  Some(prog_opts)
}

fn print_usage(program: &str, opts: Options) {
  let brief = format!("Usage: {} query [options]", program);
  print!("{}", opts.usage(&brief));
}
<|endoftext|>