text:
// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Bounded version of Ukkonens DP algorithm for approximate pattern matching.
//! Complexity: O(n * k) on random texts.
//!
//! The algorithm finds all matches of a pattern in a text with up to k errors.
//! Idea is to use dynamic programming to column-wise explore the edit matrix, but to omit
//! parts of the matrix for which the error exceeds k. To achieve this, a value `lastk` is
//! maintained that provides the lower feasible boundary of the matrix.
//! Initially, lastk = min(k, m). In each iteration (over a column), lastk can increase by at most 1.
//!
//! # Example
//!
//! ```
//! use bio::pattern_matching::ukkonen::{Ukkonen, unit_cost};
//!
//! let mut ukkonen = Ukkonen::with_capacity(10, unit_cost);
//! let text = b"ACCGTGGATGAGCGCCATAG";
//! let pattern = b"TGAGCGA";
//! let occ: Vec<(usize, usize)> = ukkonen.find_all_end(pattern, text, 1).collect();
//! assert_eq!(occ, [(13, 1), (14, 1)]);
//! ```

use std::borrow::Borrow;
use std::cmp::min;
use std::iter;
use std::iter::repeat;

use utils::TextSlice;

/// Default cost function (unit costs).
pub fn unit_cost(a: u8, b: u8) -> u32 {
    (a != b) as u32
}

/// Ukkonens algorithm.
#[allow(non_snake_case)]
pub struct Ukkonen<F>
where
    F: Fn(u8, u8) -> u32,
{
    D: [Vec<usize>; 2],
    cost: F,
}

impl<F> Ukkonen<F>
where
    F: Fn(u8, u8) -> u32,
{
    /// Initialize algorithm with given capacity and cost function.
    pub fn with_capacity(m: usize, cost: F) -> Self {
        let get_vec = || Vec::with_capacity(m + 1);
        Ukkonen {
            D: [get_vec(), get_vec()],
            cost,
        }
    }

    /// Find all matches between pattern and text with up to k errors.
    /// Matches are returned as an iterator over pairs of end position and distance.
    pub fn find_all_end<'a, C, T>(
        &'a mut self,
        pattern: TextSlice<'a>,
        text: T,
        k: usize,
    ) -> Matches<F, C, T::IntoIter>
    where
        C: Borrow<u8>,
        T: IntoIterator<Item = C>,
    {
        let m = pattern.len();
        self.D[0].clear();
        self.D[0].extend(repeat(k + 1).take(m + 1));
        self.D[1].clear();
        self.D[1].extend(0..m + 1);
        Matches {
            ukkonen: self,
            pattern,
            text: text.into_iter().enumerate(),
            lastk: min(k, m),
            m,
            k,
        }
    }
}

/// Iterator over pairs of end positions and distance of matches.
pub struct Matches<'a, F, C, T>
where
    F: 'a + Fn(u8, u8) -> u32,
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    ukkonen: &'a mut Ukkonen<F>,
    pattern: TextSlice<'a>,
    text: iter::Enumerate<T>,
    lastk: usize,
    m: usize,
    k: usize,
}

impl<'a, F, C, T> Iterator for Matches<'a, F, C, T>
where
    F: 'a + Fn(u8, u8) -> u32,
    C: Borrow<u8>,
    T: Iterator<Item = C>,
{
    type Item = (usize, usize);

    fn next(&mut self) -> Option<(usize, usize)> {
        let cost = &self.ukkonen.cost;
        for (i, c) in &mut self.text {
            let col = i % 2;
            let prev = 1 - col;

            // start with zero edit distance (semi-global alignment)
            self.ukkonen.D[col][0] = 0;
            self.lastk = min(self.lastk + 1, self.m);
            // in each column, go at most one cell further than before
            // do not look at cells with too big k
            for j in 1..self.lastk + 1 {
                self.ukkonen.D[col][j] = min(
                    min(self.ukkonen.D[prev][j] + 1, self.ukkonen.D[col][j - 1] + 1),
                    self.ukkonen.D[prev][j - 1] + (cost)(self.pattern[j - 1], *c.borrow()) as usize,
                );
            }

            // reduce lastk as long as k is exceeded: while lastk can increase by at most 1, it can
            // decrease more in one iteration.
            while self.ukkonen.D[col][self.lastk] > self.k {
                self.lastk -= 1;
            }

            if self.lastk == self.m {
                return Some((i, self.ukkonen.D[col][self.m]));
            }
        }

        None
    }
}

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

    #[test]
    fn test_find_all_end() {
        let mut ukkonen = Ukkonen::with_capacity(10, unit_cost);
        let text = b"ACCGTGGATGAGCGCCATAG";
        let pattern = b"TGAGCGT";
        let occ: Vec<(usize, usize)> = ukkonen.find_all_end(pattern, text, 1).collect();
        assert_eq!(occ, [(13, 1), (14, 1)]);
    }

    #[test]
    fn test_find_start() {
        let mut u = Ukkonen::with_capacity(10, unit_cost);

        let pattern = b"ACCGT";
        // hit begins at 1st position
        let text1 = b"ACCGTGGATGAGCGCCATAG";
        // hit begins at 2nd position
        let text2 = b"AACCGTGGATGAGCGCCATAG";

        let occ: Vec<(usize, usize)> = u.find_all_end(pattern, text1, 1).collect();
        assert_eq!(occ, [(3, 1), (4, 0), (5, 1)]);
        let occ: Vec<(usize, usize)> = u.find_all_end(pattern, text2, 1).collect();
        assert_eq!(occ, [(4, 1), (5, 0), (6, 1)]);
    }
}


text:
//! Parser for MPD responses.

use nom::{
    branch::alt,
    bytes::streaming::{tag, take, take_while, take_while1},
    character::{
        is_alphabetic,
        streaming::{char, digit1, newline},
    },
    combinator::{cut, map, map_res, opt},
    sequence::{delimited, separated_pair, terminated, tuple},
    IResult,
};

use std::str::{self, from_utf8, FromStr};
use std::sync::Arc;

use crate::response::{Error, ResponseFieldCache};

#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ParsedComponent {
    EndOfFrame,
    EndOfResponse,
    Error(Error),
    Field { key: Arc<str>, value: String },
    BinaryField { data_length: usize },
}

#[derive(Debug, PartialEq, Eq)]
struct RawError<'raw> {
    code: u64,
    command_index: u64,
    current_command: Option<&'raw str>,
    message: &'raw str,
}

impl ParsedComponent {
    pub(crate) fn parse<'i>(
        i: &'i [u8],
        field_cache: &'_ mut ResponseFieldCache,
    ) -> IResult<&'i [u8], ParsedComponent> {
        alt((
            map(tag("OK\n"), |_| ParsedComponent::EndOfResponse),
            map(tag("list_OK\n"), |_| ParsedComponent::EndOfFrame),
            map(error, |e| ParsedComponent::Error(e.into_owned_error())),
            map(binary_field, |bin| ParsedComponent::BinaryField {
                data_length: bin.len(),
            }),
            map(key_value_field, |(k, v)| ParsedComponent::Field {
                key: field_cache.insert(k),
                value: String::from(v),
            }),
        ))(i)
    }
}

impl RawError<'_> {
    fn into_owned_error(self) -> Error {
        Error {
            code: self.code,
            command_index: self.command_index,
            current_command: self.current_command.map(Box::from),
            message: Box::from(self.message),
        }
    }
}

/// Recognize a server greeting, returning the protocol version.
pub(crate) fn greeting(i: &[u8]) -> IResult<&[u8], &str> {
    delimited(
        tag("OK MPD "),
        map_res(take_while1(|c| c != b'\n'), from_utf8),
        newline,
    )(i)
}

/// Recognize and parse an unsigned ASCII-encoded number
fn number<O: FromStr>(i: &[u8]) -> IResult<&[u8], O> {
    map_res(map_res(digit1, from_utf8), str::parse)(i)
}

/// Parse an error response.
fn error(i: &[u8]) -> IResult<&[u8], RawError<'_>> {
    let (remaining, ((code, index), command, message)) = delimited(
        tag("ACK "),
        tuple((
            terminated(error_code_and_index, char(' ')),
            terminated(error_current_command, char(' ')),
            map_res(take_while(|b| b != b'\n'), from_utf8),
        )),
        newline,
    )(i)?;

    Ok((
        remaining,
        RawError {
            code,
            message,
            command_index: index,
            current_command: command,
        },
    ))
}

/// Recognize `[<error code>@<command index>]`.
fn error_code_and_index(i: &[u8]) -> IResult<&[u8], (u64, u64)> {
    delimited(
        char('['),
        separated_pair(number, char('@'), number),
        char(']'),
    )(i)
}

/// Recognize the current command in an error, `None` if empty.
fn error_current_command(i: &[u8]) -> IResult<&[u8], Option<&str>> {
    delimited(
        char('{'),
        opt(map_res(
            take_while1(|b| is_alphabetic(b) || b == b'_'),
            from_utf8,
        )),
        char('}'),
    )(i)
}

/// Recognize a single key-value pair
fn key_value_field(i: &[u8]) -> IResult<&[u8], (&str, &str)> {
    separated_pair(
        map_res(
            take_while1(|b| is_alphabetic(b) || b == b'_' || b == b'-'),
            from_utf8,
        ),
        tag(": "),
        map_res(terminated(take_while(|b| b != b'\n'), newline), from_utf8),
    )(i)
}

/// Recognize the header of a binary section
fn binary_prefix(i: &[u8]) -> IResult<&[u8], usize> {
    delimited(tag("binary: "), number, newline)(i)
}

/// Recognize a binary field
fn binary_field(i: &[u8]) -> IResult<&[u8], &[u8]> {
    let (i, length) = binary_prefix(i)?;

    cut(terminated(take(length), newline))(i)
}

#[cfg(test)]
mod test {
    use super::*;
    use nom::{Err as NomErr, Needed};

    const EMPTY: &[u8] = &[];

    #[test]
    fn greeting() {
        assert_eq!(super::greeting(b"OK MPD 0.21.11\n"), Ok((EMPTY, "0.21.11")));
        assert!(super::greeting(b"OK MPD 0.21.11")
            .unwrap_err()
            .is_incomplete());
    }

    #[test]
    fn end_markers() {
        let keys = &mut ResponseFieldCache::new();

        assert_eq!(
            ParsedComponent::parse(b"OK\n", keys),
            Ok((EMPTY, ParsedComponent::EndOfResponse))
        );

        assert_eq!(
            ParsedComponent::parse(b"OK", keys),
            Err(NomErr::Incomplete(Needed::new(1)))
        );

        assert_eq!(
            ParsedComponent::parse(b"list_OK\n", keys),
            Ok((EMPTY, ParsedComponent::EndOfFrame))
        );

        assert_eq!(
            ParsedComponent::parse(b"list_OK", keys),
            Err(NomErr::Incomplete(Needed::new(1)))
        );
    }

    #[test]
    fn parse_error() {
        let keys = &mut ResponseFieldCache::new();
        let no_command = b"ACK [5@0] {} unknown command \"foo\"\n";
        let with_command = b"ACK [2@0] {random} Boolean (0/1) expected: foo\n";

        assert_eq!(
            ParsedComponent::parse(no_command, keys),
            Ok((
                EMPTY,
                ParsedComponent::Error(Error {
                    code: 5,
                    command_index: 0,
                    current_command: None,
                    message: Box::from("unknown command \"foo\""),
                })
            ))
        );

        assert_eq!(
            ParsedComponent::parse(with_command, keys),
            Ok((
                EMPTY,
                ParsedComponent::Error(Error {
                    code: 2,
                    command_index: 0,
                    current_command: Some(Box::from("random")),
                    message: Box::from("Boolean (0/1) expected: foo"),
                }),
            ))
        );
    }

    #[test]
    fn field() {
        let keys = &mut ResponseFieldCache::new();

        assert_eq!(
            ParsedComponent::parse(b"foo: OK\n", keys),
            Ok((
                EMPTY,
                ParsedComponent::Field {
                    key: Arc::from("foo"),
                    value: String::from("OK"),
                }
            ))
        );

        assert_eq!(
            ParsedComponent::parse(b"foo_bar: hello world list_OK\n", keys),
            Ok((
                EMPTY,
                ParsedComponent::Field {
                    key: Arc::from("foo_bar"),
                    value: String::from("hello world list_OK"),
                }
            ))
        );

        assert!(ParsedComponent::parse(b"asdf: fooo", keys)
            .unwrap_err()
            .is_incomplete());
    }

    #[test]
    fn binary_field() {
        let keys = &mut ResponseFieldCache::new();

        assert_eq!(
            ParsedComponent::parse(b"binary: 6\nFOOBAR\n", keys),
            Ok((EMPTY, ParsedComponent::BinaryField { data_length: 6 }))
        );

        assert_eq!(
            ParsedComponent::parse(b"binary: 6\nF", keys),
            Err(NomErr::Incomplete(Needed::new(5)))
        );

        assert_eq!(
            ParsedComponent::parse(b"binary: 12\n", keys),
            Err(NomErr::Incomplete(Needed::new(12)))
        );
    }
}

domain: rust


text:
// Copyright (c) 2017-present PyO3 Project and Contributors

use crate::{
    exceptions::{PyAttributeError, PyNotImplementedError},
    ffi,
    impl_::freelist::FreeList,
    pycell::PyCellLayout,
    pyclass_init::PyObjectInit,
    type_object::{PyLayout, PyTypeObject},
    PyClass, PyMethodDefType, PyNativeType, PyResult, PyTypeInfo, Python,
};
use std::{marker::PhantomData, os::raw::c_void, ptr::NonNull, thread};

/// This type is used as a "dummy" type on which dtolnay specializations are
/// applied to apply implementations from `#[pymethods]` & `#[pyproto]`
pub struct PyClassImplCollector<T>(PhantomData<T>);

impl<T> PyClassImplCollector<T> {
    pub fn new() -> Self {
        Self(PhantomData)
    }
}

impl<T> Default for PyClassImplCollector<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Clone for PyClassImplCollector<T> {
    fn clone(&self) -> Self {
        Self::new()
    }
}

impl<T> Copy for PyClassImplCollector<T> {}

/// Implements the underlying functionality of `#[pyclass]`, assembled by various proc macros.
///
/// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail
/// and may be changed at any time.
pub trait PyClassImpl: Sized {
    /// Class doc string
    const DOC: &'static str = "\0";

    /// #[pyclass(gc)]
    const IS_GC: bool = false;

    /// #[pyclass(subclass)]
    const IS_BASETYPE: bool = false;

    /// #[pyclass(extends=...)]
    const IS_SUBCLASS: bool = false;

    /// Layout
    type Layout: PyLayout<Self>;

    /// Base class
    type BaseType: PyTypeInfo + PyTypeObject + PyClassBaseType;

    /// This handles following two situations:
    /// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing.
    ///    This implementation is used by default. Compile fails if `T: !Send`.
    /// 2. In case `T` is `!Send`, `ThreadChecker` panics when `T` is accessed by another thread.
    ///    This implementation is used when `#[pyclass(unsendable)]` is given.
    ///    Panicking makes it safe to expose `T: !Send` to the Python interpreter, where all objects
    ///    can be accessed by multiple threads by `threading` module.
    type ThreadChecker: PyClassThreadChecker<Self>;

    fn for_each_method_def(_visitor: &mut dyn FnMut(&[PyMethodDefType])) {}
    fn get_new() -> Option<ffi::newfunc> {
        None
    }
    fn get_alloc() -> Option<ffi::allocfunc> {
        None
    }
    fn get_free() -> Option<ffi::freefunc> {
        None
    }
    fn for_each_proto_slot(_visitor: &mut dyn FnMut(&[ffi::PyType_Slot])) {}
    fn get_buffer() -> Option<&'static PyBufferProcs> {
        None
    }
}

// Traits describing known special methods.

pub trait PyClassNewImpl<T> {
    fn new_impl(self) -> Option<ffi::newfunc>;
}

impl<T> PyClassNewImpl<T> for &'_ PyClassImplCollector<T> {
    fn new_impl(self) -> Option<ffi::newfunc> {
        None
    }
}

macro_rules! slot_fragment_trait {
    ($trait_name:ident, $($default_method:tt)*) => {
        #[allow(non_camel_case_types)]
        pub trait $trait_name<T>: Sized {
            $($default_method)*
        }

        impl<T> $trait_name<T> for &'_ PyClassImplCollector<T> {}
    }
}

/// Macro which expands to three items
/// - Trait for a __setitem__ dunder
/// - Trait for the corresponding __delitem__ dunder
/// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders
macro_rules! define_pyclass_setattr_slot {
    (
        $set_trait:ident,
        $del_trait:ident,
        $set:ident,
        $del:ident,
        $set_error:expr,
        $del_error:expr,
        $generate_macro:ident,
        $slot:ident,
        $func_ty:ident,
    ) => {
        slot_fragment_trait! {
            $set_trait,

            /// # Safety: _slf and _attr must be valid non-null Python objects
            #[inline]
            unsafe fn $set(
                self,
                _py: Python,
                _slf: *mut ffi::PyObject,
                _attr: *mut ffi::PyObject,
                _value: NonNull<ffi::PyObject>,
            ) -> PyResult<()> {
                $set_error
            }
        }

        slot_fragment_trait! {
            $del_trait,

            /// # Safety: _slf and _attr must be valid non-null Python objects
            #[inline]
            unsafe fn $del(
                self,
                _py: Python,
                _slf: *mut ffi::PyObject,
                _attr: *mut ffi::PyObject,
            ) -> PyResult<()> {
                $del_error
            }
        }

        #[doc(hidden)]
        #[macro_export]
        macro_rules! $generate_macro {
            ($cls:ty) => {{
                unsafe extern "C" fn __wrap(
                    _slf: *mut $crate::ffi::PyObject,
                    attr: *mut $crate::ffi::PyObject,
                    value: *mut $crate::ffi::PyObject,
                ) -> ::std::os::raw::c_int {
                    use ::std::option::Option::*;
                    use $crate::callback::IntoPyCallbackOutput;
                    use $crate::class::impl_::*;
                    $crate::callback::handle_panic(|py| {
                        let collector = PyClassImplCollector::<$cls>::new();
                        if let Some(value) = ::std::ptr::NonNull::new(value) {
                            collector.$set(py, _slf, attr, value).convert(py)
                        } else {
                            collector.$del(py, _slf, attr).convert(py)
                        }
                    })
                }
                $crate::ffi::PyType_Slot {
                    slot: $crate::ffi::$slot,
                    pfunc: __wrap as $crate::ffi::$func_ty as _,
                }
            }};
        }
    };
}

define_pyclass_setattr_slot! {
    PyClass__setattr__SlotFragment,
    PyClass__delattr__SlotFragment,
    __setattr__,
    __delattr__,
    Err(PyAttributeError::new_err("can't set attribute")),
    Err(PyAttributeError::new_err("can't delete attribute")),
    generate_pyclass_setattr_slot,
    Py_tp_setattro,
    setattrofunc,
}

define_pyclass_setattr_slot! {
    PyClass__set__SlotFragment,
    PyClass__delete__SlotFragment,
    __set__,
    __delete__,
    Err(PyNotImplementedError::new_err("can't set descriptor")),
    Err(PyNotImplementedError::new_err("can't delete descriptor")),
    generate_pyclass_setdescr_slot,
    Py_tp_descr_set,
    descrsetfunc,
}

define_pyclass_setattr_slot! {
    PyClass__setitem__SlotFragment,
    PyClass__delitem__SlotFragment,
    __setitem__,
    __delitem__,
    Err(PyNotImplementedError::new_err("can't set item")),
    Err(PyNotImplementedError::new_err("can't delete item")),
    generate_pyclass_setitem_slot,
    Py_mp_ass_subscript,
    objobjargproc,
}

/// Macro which expands to three items
/// - Trait for a lhs dunder e.g. __add__
/// - Trait for the corresponding rhs e.g. __radd__
/// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders
macro_rules! define_pyclass_binary_operator_slot {
    (
        $lhs_trait:ident,
        $rhs_trait:ident,
        $lhs:ident,
        $rhs:ident,
        $generate_macro:ident,
        $slot:ident,
        $func_ty:ident,
    ) => {
        slot_fragment_trait! {
            $lhs_trait,

            /// # Safety: _slf and _other must be valid non-null Python objects
            #[inline]
            unsafe fn $lhs(
                self,
                _py: Python,
                _slf: *mut ffi::PyObject,
                _other: *mut ffi::PyObject,
            ) -> PyResult<*mut ffi::PyObject> {
                Ok(ffi::_Py_NewRef(ffi::Py_NotImplemented()))
            }
        }

        slot_fragment_trait! {
            $rhs_trait,

            /// # Safety: _slf and _other must be valid non-null Python objects
            #[inline]
            unsafe fn $rhs(
                self,
                _py: Python,
                _slf: *mut ffi::PyObject,
                _other: *mut ffi::PyObject,
            ) -> PyResult<*mut ffi::PyObject> {
                Ok(ffi::_Py_NewRef(ffi::Py_NotImplemented()))
            }
        }

        #[doc(hidden)]
        #[macro_export]
        macro_rules! $generate_macro {
            ($cls:ty) => {{
                unsafe extern "C" fn __wrap(
                    _slf: *mut $crate::ffi::PyObject,
                    _other: *mut $crate::ffi::PyObject,
                ) -> *mut $crate::ffi::PyObject {
                    $crate::callback::handle_panic(|py| {
                        use ::pyo3::class::impl_::*;
                        let collector = PyClassImplCollector::<$cls>::new();
                        let lhs_result = collector.$lhs(py, _slf, _other)?;
                        if lhs_result == $crate::ffi::Py_NotImplemented() {
                            $crate::ffi::Py_DECREF(lhs_result);
                            collector.$rhs(py, _other, _slf)
                        } else {
                            ::std::result::Result::Ok(lhs_result)
                        }
                    })
                }
                $crate::ffi::PyType_Slot {
                    slot: $crate::ffi::$slot,
                    pfunc: __wrap as $crate::ffi::$func_ty as _,
                }
            }};
        }
    };
}

define_pyclass_binary_operator_slot! {
    PyClass__add__SlotFragment,
    PyClass__radd__SlotFragment,
    __add__,
    __radd__,
    generate_pyclass_add_slot,
    Py_nb_add,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__sub__SlotFragment,
    PyClass__rsub__SlotFragment,
    __sub__,
    __rsub__,
    generate_pyclass_sub_slot,
    Py_nb_subtract,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__mul__SlotFragment,
    PyClass__rmul__SlotFragment,
    __mul__,
    __rmul__,
    generate_pyclass_mul_slot,
    Py_nb_multiply,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__mod__SlotFragment,
    PyClass__rmod__SlotFragment,
    __mod__,
    __rmod__,
    generate_pyclass_mod_slot,
    Py_nb_remainder,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__divmod__SlotFragment,
    PyClass__rdivmod__SlotFragment,
    __divmod__,
    __rdivmod__,
    generate_pyclass_divmod_slot,
    Py_nb_divmod,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__lshift__SlotFragment,
    PyClass__rlshift__SlotFragment,
    __lshift__,
    __rlshift__,
    generate_pyclass_lshift_slot,
    Py_nb_lshift,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__rshift__SlotFragment,
    PyClass__rrshift__SlotFragment,
    __rshift__,
    __rrshift__,
    generate_pyclass_rshift_slot,
    Py_nb_rshift,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__and__SlotFragment,
    PyClass__rand__SlotFragment,
    __and__,
    __rand__,
    generate_pyclass_and_slot,
    Py_nb_and,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__or__SlotFragment,
    PyClass__ror__SlotFragment,
    __or__,
    __ror__,
    generate_pyclass_or_slot,
    Py_nb_or,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__xor__SlotFragment,
    PyClass__rxor__SlotFragment,
    __xor__,
    __rxor__,
    generate_pyclass_xor_slot,
    Py_nb_xor,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__matmul__SlotFragment,
    PyClass__rmatmul__SlotFragment,
    __matmul__,
    __rmatmul__,
    generate_pyclass_matmul_slot,
    Py_nb_matrix_multiply,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__truediv__SlotFragment,
    PyClass__rtruediv__SlotFragment,
    __truediv__,
    __rtruediv__,
    generate_pyclass_truediv_slot,
    Py_nb_true_divide,
    binaryfunc,
}

define_pyclass_binary_operator_slot! {
    PyClass__floordiv__SlotFragment,
    PyClass__rfloordiv__SlotFragment,
    __floordiv__,
    __rfloordiv__,
    generate_pyclass_floordiv_slot,
    Py_nb_floor_divide,
    binaryfunc,
}

slot_fragment_trait! {
    PyClass__pow__SlotFragment,

    /// # Safety: _slf and _other must be valid non-null Python objects
    #[inline]
    unsafe fn __pow__(
        self,
        _py: Python,
        _slf: *mut ffi::PyObject,
        _other: *mut ffi::PyObject,
        _mod: *mut ffi::PyObject,
    ) -> PyResult<*mut ffi::PyObject> {
        Ok(ffi::_Py_NewRef(ffi::Py_NotImplemented()))
    }
}

slot_fragment_trait! {
    PyClass__rpow__SlotFragment,

    /// # Safety: _slf and _other must be valid non-null Python objects
    #[inline]
    unsafe fn __rpow__(
        self,
        _py: Python,
        _slf: *mut ffi::PyObject,
        _other: *mut ffi::PyObject,
        _mod: *mut ffi::PyObject,
    ) -> PyResult<*mut ffi::PyObject> {
        Ok(ffi::_Py_NewRef(ffi::Py_NotImplemented()))
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! generate_pyclass_pow_slot {
    ($cls:ty) => {{
        unsafe extern "C" fn __wrap(
            _slf: *mut $crate::ffi::PyObject,
            _other: *mut $crate::ffi::PyObject,
            _mod: *mut $crate::ffi::PyObject,
        ) -> *mut $crate::ffi::PyObject {
            $crate::callback::handle_panic(|py| {
                use ::pyo3::class::impl_::*;
                let collector = PyClassImplCollector::<$cls>::new();
                let lhs_result = collector.__pow__(py, _slf, _other, _mod)?;
                if lhs_result == $crate::ffi::Py_NotImplemented() {
                    $crate::ffi::Py_DECREF(lhs_result);
                    collector.__rpow__(py, _other, _slf, _mod)
                } else {
                    ::std::result::Result::Ok(lhs_result)
                }
            })
        }
        $crate::ffi::PyType_Slot {
            slot: $crate::ffi::Py_nb_power,
            pfunc: __wrap as $crate::ffi::ternaryfunc as _,
        }
    }};
}

pub trait PyClassAllocImpl<T> {
    fn alloc_impl(self) -> Option<ffi::allocfunc>;
}

impl<T> PyClassAllocImpl<T> for &'_ PyClassImplCollector<T> {
    fn alloc_impl(self) -> Option<ffi::allocfunc> {
        None
    }
}

pub trait PyClassFreeImpl<T> {
    fn free_impl(self) -> Option<ffi::freefunc>;
}

impl<T> PyClassFreeImpl<T> for &'_ PyClassImplCollector<T> {
    fn free_impl(self) -> Option<ffi::freefunc> {
        None
    }
}

/// Implements a freelist.
///
/// Do not implement this trait manually. Instead, use `#[pyclass(freelist = N)]`
/// on a Rust struct to implement it.
pub trait PyClassWithFreeList: PyClass {
    fn get_free_list(py: Python) -> &mut FreeList<*mut ffi::PyObject>;
}

/// Implementation of tp_alloc for `freelist` classes.
///
/// # Safety
/// - `subtype` must be a valid pointer to the type object of T or a subclass.
/// - The GIL must be held.
pub unsafe extern "C" fn alloc_with_freelist<T: PyClassWithFreeList>(
    subtype: *mut ffi::PyTypeObject,
    nitems: ffi::Py_ssize_t,
) -> *mut ffi::PyObject {
    let py = Python::assume_gil_acquired();

    #[cfg(not(Py_3_8))]
    bpo_35810_workaround(py, subtype);

    let self_type = T::type_object_raw(py);
    // If this type is a variable type or the subtype is not equal to this type, we cannot use the
    // freelist
    if nitems == 0 && subtype == self_type {
        if let Some(obj) = T::get_free_list(py).pop() {
            ffi::PyObject_Init(obj, subtype);
            return obj as _;
        }
    }

    ffi::PyType_GenericAlloc(subtype, nitems)
}

/// Implementation of tp_free for `freelist` classes.
///
/// # Safety
/// - `obj` must be a valid pointer to an instance of T (not a subclass).
/// - The GIL must be held.
pub unsafe extern "C" fn free_with_freelist<T: PyClassWithFreeList>(obj: *mut c_void) {
    let obj = obj as *mut ffi::PyObject;
    debug_assert_eq!(
        T::type_object_raw(Python::assume_gil_acquired()),
        ffi::Py_TYPE(obj)
    );
    if let Some(obj) = T::get_free_list(Python::assume_gil_acquired()).insert(obj) {
        let ty = ffi::Py_TYPE(obj);

        // Deduce appropriate inverse of PyType_GenericAlloc
        let free = if ffi::PyType_IS_GC(ty) != 0 {
            ffi::PyObject_GC_Del
        } else {
            ffi::PyObject_Free
        };
        free(obj as *mut c_void);

        #[cfg(Py_3_8)]
        if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 {
            ffi::Py_DECREF(ty as *mut ffi::PyObject);
        }
    }
}

/// Workaround for Python issue 35810; no longer necessary in Python 3.8
#[inline]
#[cfg(not(Py_3_8))]
unsafe fn bpo_35810_workaround(_py: Python, ty: *mut ffi::PyTypeObject) {
    #[cfg(Py_LIMITED_API)]
    {
        // Must check version at runtime for abi3 wheels - they could run against a higher version
        // than the build config suggests.
        use crate::once_cell::GILOnceCell;
        static IS_PYTHON_3_8: GILOnceCell<bool> = GILOnceCell::new();

        if *IS_PYTHON_3_8.get_or_init(_py, || _py.version_info() >= (3, 8)) {
            // No fix needed - the wheel is running on a sufficiently new interpreter.
            return;
        }
    }

    ffi::Py_INCREF(ty as *mut ffi::PyObject);
}

// General methods implementation: either dtolnay specialization trait or inventory if
// multiple-pymethods feature is enabled.

macro_rules! methods_trait {
    ($name:ident, $function_name: ident) => {
        pub trait $name<T> {
            fn $function_name(self) -> &'static [PyMethodDefType];
        }

        impl<T> $name<T> for &'_ PyClassImplCollector<T> {
            fn $function_name(self) -> &'static [PyMethodDefType] {
                &[]
            }
        }
    };
}

/// Implementation detail. Only to be used through our proc macro code.
/// Method storage for `#[pyclass]`.
/// Allows arbitrary `#[pymethod]` blocks to submit their methods,
/// which are eventually collected by `#[pyclass]`.
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
pub trait PyMethodsInventory: inventory::Collect {
    /// Create a new instance
    fn new(methods: Vec<PyMethodDefType>, slots: Vec<ffi::PyType_Slot>) -> Self;

    /// Returns the methods for a single `#[pymethods] impl` block
    fn methods(&'static self) -> &'static [PyMethodDefType];

    /// Returns the slots for a single `#[pymethods] impl` block
    fn slots(&'static self) -> &'static [ffi::PyType_Slot];
}

/// Implemented for `#[pyclass]` in our proc macro code.
/// Indicates that the pyclass has its own method storage.
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
pub trait HasMethodsInventory {
    type Methods: PyMethodsInventory;
}

// Methods from #[pyo3(get, set)] on struct fields.
methods_trait!(PyClassDescriptors, py_class_descriptors);

// Methods from #[pymethods] if not using inventory.
#[cfg(not(feature = "multiple-pymethods"))]
methods_trait!(PyMethods, py_methods);

// All traits describing slots, as well as the fallback implementations for unimplemented protos
//
// Protos which are implemented use dtolnay specialization to implement for PyClassImplCollector<T>.
//
// See https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md

macro_rules! slots_trait {
    ($name:ident, $function_name: ident) => {
        #[allow(clippy::upper_case_acronyms)]
        pub trait $name<T> {
            fn $function_name(self) -> &'static [ffi::PyType_Slot];
        }

        impl<T> $name<T> for &'_ PyClassImplCollector<T> {
            fn $function_name(self) -> &'static [ffi::PyType_Slot] {
                &[]
            }
        }
    };
}

slots_trait!(PyObjectProtocolSlots, object_protocol_slots);
slots_trait!(PyDescrProtocolSlots, descr_protocol_slots);
slots_trait!(PyGCProtocolSlots, gc_protocol_slots);
slots_trait!(PyIterProtocolSlots, iter_protocol_slots);
slots_trait!(PyMappingProtocolSlots, mapping_protocol_slots);
slots_trait!(PyNumberProtocolSlots, number_protocol_slots);
slots_trait!(PyAsyncProtocolSlots, async_protocol_slots);
slots_trait!(PySequenceProtocolSlots, sequence_protocol_slots);
slots_trait!(PyBufferProtocolSlots, buffer_protocol_slots);


text:
use core::mem;
use core::ptr;
use core::slice;

use cstr_core::CString;
use cty::c_int;
use ndless::prelude::*;

use crate::get_error;
use crate::Rect;

pub use self::Color::{RGB, RGBA};

#[allow(non_camel_case_types)]
type c_float = f32;

pub mod ll {
	#![allow(non_camel_case_types)]

	use cty::{
		c_char as c_schar, c_int, c_uchar, c_uint, c_void, int32_t, uint16_t, uint32_t, uint8_t,
	};

	use crate::Rect;

	type c_float = f32;
	pub type SDL_Rect = Rect;

	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_RWops {
		pub seek: *mut uint8_t,
		pub read: *mut uint8_t,
		pub write: *mut uint8_t,
		pub close: *mut uint8_t,
		pub _type: uint32_t,
		_hidden: [c_uchar; 24],
	}

	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_Surface {
		pub flags: uint32_t,
		pub format: *mut SDL_PixelFormat,
		pub w: c_int,
		pub h: c_int,
		pub pitch: uint16_t,
		pub pixels: *mut c_void,
		pub offset: c_int,
		pub hwdata: *mut c_void,
		pub clip_rect: SDL_Rect,
		pub unused1: uint32_t,
		pub locked: uint32_t,
		pub map: *mut c_void,
		pub format_version: c_uint,
		pub refcount: c_int,
	}

	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_Color {
		pub r: uint8_t,
		pub g: uint8_t,
		pub b: uint8_t,
		pub unused: uint8_t,
	}

	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_Palette {
		pub ncolors: c_int,
		pub colors: *mut SDL_Color,
	}

	#[allow(non_snake_case)]
	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_PixelFormat {
		pub palette: *mut SDL_Palette,
		pub BitsPerPixel: uint8_t,
		pub BytesPerPixel: uint8_t,
		pub Rloss: uint8_t,
		pub Gloss: uint8_t,
		pub Bloss: uint8_t,
		pub Aloss: uint8_t,
		pub Rshift: uint8_t,
		pub Gshift: uint8_t,
		pub Bshift: uint8_t,
		pub Ashift: uint8_t,
		pub Rmask: uint32_t,
		pub Gmask: uint32_t,
		pub Bmask: uint32_t,
		pub Amask: uint32_t,
		pub colorkey: uint32_t,
		pub alpha: uint8_t,
	}

	#[repr(C)]
	#[derive(Copy, Clone)]
	pub struct SDL_VideoInfo {
		pub flags: uint32_t,
		// actually a set of packed fields
		pub video_mem: uint32_t,
		pub vfmt: *mut SDL_PixelFormat,
		pub current_w: c_int,
		pub current_h: c_int,
	}

	extern "C" {
		pub fn SDL_CreateRGBSurface(
			flags: uint32_t,
			width: c_int,
			height: c_int,
			depth: c_int,
			Rmask: uint32_t,
			Gmask: uint32_t,
			Bmask: uint32_t,
			Amask: uint32_t,
		) -> *mut SDL_Surface;
		pub fn SDL_CreateRGBSurfaceFrom(
			pixels: *mut c_void,
			width: c_int,
			height: c_int,
			depth: c_int,
			pitch: c_int,
			Rmask: uint32_t,
			Gmask: uint32_t,
			Bmask: uint32_t,
			Amask: uint32_t,
		) -> *mut SDL_Surface;
		pub fn SDL_FreeSurface(surface: *mut SDL_Surface);
		pub fn SDL_MapRGB(
			format: *const SDL_PixelFormat,
			r: uint8_t,
			g: uint8_t,
			b: uint8_t,
		) -> uint32_t;
		pub fn SDL_MapRGBA(
			format: *const SDL_PixelFormat,
			r: uint8_t,
			g: uint8_t,
			b: uint8_t,
			a: uint8_t,
		) -> uint32_t;
		pub fn SDL_GetRGB(
			pixel: uint32_t,
			fmt: *const SDL_PixelFormat,
			r: *mut uint8_t,
			g: *mut uint8_t,
			b: *mut uint8_t,
		);
		pub fn SDL_GetRGBA(
			pixel: uint32_t,
			fmt: *const SDL_PixelFormat,
			r: *mut uint8_t,
			g: *mut uint8_t,
			b: *mut uint8_t,
			a: *mut uint8_t,
		);
		pub fn SDL_SetVideoMode(
			width: c_int,
			height: c_int,
			bpp: c_int,
			flags: uint32_t,
		) -> *mut SDL_Surface;
		pub fn SDL_VideoModeOK(width: c_int, height: c_int, bpp: c_int, flags: uint32_t) -> c_int;
		pub fn SDL_GetVideoInfo() -> *const SDL_VideoInfo;
		pub fn SDL_GetVideoSurface() -> *mut SDL_Surface;
		pub fn SDL_UpdateRect(
			screen: *mut SDL_Surface,
			x: int32_t,
			y: int32_t,
			w: uint32_t,
			h: uint32_t,
		);
		pub fn SDL_UpdateRects(screen: *mut SDL_Surface, numrects: c_int, rects: *mut SDL_Rect);
		pub fn SDL_SetColors(
			surface: *mut SDL_Surface,
			colors: *mut SDL_Color,
			firstcolor: c_int,
			ncolors: c_int,
		) -> c_int;
		pub fn SDL_SetPalette(
			surface: *mut SDL_Surface,
			flags: c_int,
			colors: *mut SDL_Color,
			firstcolor: c_int,
			ncolors: c_int,
		) -> c_int;
		pub fn SDL_LockSurface(surface: *mut SDL_Surface) -> c_int;
		pub fn SDL_UnlockSurface(surface: *mut SDL_Surface);
		pub fn SDL_Flip(screen: *mut SDL_Surface) -> c_int;
		pub fn SDL_ConvertSurface(
			src: *mut SDL_Surface,
			fmt: *mut SDL_PixelFormat,
			flags: uint32_t,
		) -> *mut SDL_Surface;
		pub fn SDL_DisplayFormat(surface: *mut SDL_Surface) -> *mut SDL_Surface;
		pub fn SDL_DisplayFormatAlpha(surface: *mut SDL_Surface) -> *mut SDL_Surface;
		pub fn SDL_SetColorKey(surface: *mut SDL_Surface, flag: uint32_t, key: uint32_t) -> c_int;
		pub fn SDL_SetAlpha(surface: *mut SDL_Surface, flag: uint32_t, alpha: uint8_t) -> c_int;
		pub fn SDL_SetClipRect(surface: *mut SDL_Surface, rect: *const SDL_Rect);
		pub fn SDL_UpperBlit(
			src: *mut SDL_Surface,
			srcrect: *mut SDL_Rect,
			dst: *mut SDL_Surface,
			dstrect: *mut SDL_Rect,
		) -> c_int;
		pub fn SDL_FillRect(
			dst: *mut SDL_Surface,
			dstrect: *mut SDL_Rect,
			color: uint32_t,
		) -> c_int;
		pub fn SDL_SetGamma(r: c_float, g: c_float, b: c_float) -> c_int;
		pub fn SDL_SetGammaRamp(
			r: *const uint16_t,
			g: *const uint16_t,
			b: *const uint16_t,
		) -> c_int;
		pub fn SDL_GetGammaRamp(r: *mut uint16_t, g: *mut uint16_t, b: *mut uint16_t) -> c_int;
		pub fn SDL_RWFromFile(file: *const c_schar, mode: *const c_schar) -> *mut SDL_RWops;
		pub fn SDL_RWFromConstMem(mem: *const c_void, size: c_int) -> *mut SDL_RWops;
		pub fn SDL_LoadBMP_RW(src: *mut SDL_RWops, freesrc: c_int) -> *mut SDL_Surface;
		pub fn SDL_SaveBMP_RW(
			surface: *mut SDL_Surface,
			dst: *mut SDL_RWops,
			freedst: c_int,
		) -> c_int;
		pub fn SDL_GL_SwapBuffers();
	}
}

#[derive(Debug, PartialEq)]
pub struct Surface {
	pub raw: *mut ll::SDL_Surface,
	pub owned: bool,
}

fn wrap_surface(raw: *mut ll::SDL_Surface, owned: bool) -> Surface {
	Surface { raw, owned }
}

impl Drop for Surface {
	fn drop(&mut self) {
		unsafe {
			if self.owned {
				ll::SDL_FreeSurface(self.raw);
			}
		}
	}
}

#[derive(PartialEq, Copy, Clone, Debug)]
pub struct Palette {
	pub raw: *mut ll::SDL_Palette,
}

fn wrap_palette(palette: *mut ll::SDL_Palette) -> Option<Palette> {
	if palette.is_null() {
		None
	} else {
		Some(Palette { raw: palette })
	}
}

pub type PaletteColors<'a> = slice::Iter<'a, ll::SDL_Color>;

impl Palette {
	pub fn colors<'a>(&'a self) -> PaletteColors<'a> {
		use self::ll::SDL_Color;
		let colors = unsafe { (*self.raw).colors } as *const SDL_Color;
		let ncolors = unsafe { (*self.raw).ncolors } as usize;
		let colors: &'a [SDL_Color] = unsafe {
			&*(slice::from_raw_parts(&colors, ncolors) as *const [*const SDL_Color]
				as *const [SDL_Color])
		};
		colors.iter()
	}
}

#[derive(PartialEq, Debug)]
pub struct PixelFormat {
	pub palette: Option<Palette>,
	pub bpp: u8,
	pub r_loss: u8,
	pub g_loss: u8,
	pub b_loss: u8,
	pub a_loss: u8,
	pub r_shift: u8,
	pub g_shift: u8,
	pub b_shift: u8,
	pub a_shift: u8,
	pub r_mask: u32,
	pub g_mask: u32,
	pub b_mask: u32,
	pub a_mask: u32,
	pub color_key: u32,
	pub alpha: u8,
}

fn wrap_pixel_format(raw: *mut ll::SDL_PixelFormat) -> PixelFormat {
	let fmt = &unsafe { *raw };
	PixelFormat {
		palette: wrap_palette(fmt.palette),
		bpp: fmt.BitsPerPixel,
		r_loss: fmt.Rloss,
		g_loss: fmt.Gloss,
		b_loss: fmt.Bloss,
		a_loss: fmt.Aloss,
		r_shift: fmt.Rshift,
		g_shift: fmt.Gshift,
		b_shift: fmt.Bshift,
		a_shift: fmt.Ashift,
		r_mask: fmt.Rmask,
		g_mask: fmt.Gmask,
		b_mask: fmt.Bmask,
		a_mask: fmt.Amask,
		color_key: fmt.colorkey,
		alpha: fmt.alpha,
	}
}

fn unwrap_pixel_format(fmt: &PixelFormat) -> ll::SDL_PixelFormat {
	ll::SDL_PixelFormat {
		palette: match fmt.palette {
			None => ptr::null_mut(),
			Some(palette) => palette.raw,
		},
		BitsPerPixel: fmt.bpp,
		BytesPerPixel: fmt.bpp / 8,
		Rloss: fmt.r_loss,
		Gloss: fmt.g_loss,
		Bloss: fmt.b_loss,
		Aloss: fmt.a_loss,
		Rshift: fmt.r_shift,
		Gshift: fmt.g_shift,
		Bshift: fmt.b_shift,
		Ashift: fmt.a_shift,
		Rmask: fmt.r_mask,
		Gmask: fmt.g_mask,
		Bmask: fmt.b_mask,
		Amask: fmt.a_mask,
		colorkey: fmt.color_key,
		alpha: fmt.alpha,
	}
}

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Color {
	RGB(u8, u8, u8),
	RGBA(u8, u8, u8, u8),
}

impl Color {
	pub fn from_mapped(bit: u32, fmt: *const ll::SDL_PixelFormat) -> Color {
		let mut r = 0;
		let mut g = 0;
		let mut b = 0;
		let mut a = 0;

		unsafe { ll::SDL_GetRGBA(bit, fmt, &mut r, &mut g, &mut b, &mut a) }

		RGBA(r, g, b, a)
	}

	pub fn to_mapped(self, fmt: *const ll::SDL_PixelFormat) -> u32 {
		match self {
			RGB(r, g, b) => unsafe { ll::SDL_MapRGB(fmt, r, g, b) },
			RGBA(r, g, b, a) => unsafe { ll::SDL_MapRGBA(fmt, r, g, b, a) },
		}
	}

	pub fn from_struct(c: ll::SDL_Color) -> Color {
		RGB(c.r, c.g, c.b)
	}

	pub fn to_struct(self) -> ll::SDL_Color {
		match self {
			RGB(r, g, b) => ll::SDL_Color { r, g, b, unused: 0 },
			RGBA(r, g, b, _) => ll::SDL_Color { r, g, b, unused: 0 },
		}
	}
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum SurfaceFlag {
	SWSurface = 0x0000_0000,
	HWSurface = 0x0000_0001,
	AsyncBlit = 0x0000_0004,
	SrcColorKey = 0x0000_1000,
	SrcAlpha = 0x0001_0000,
	RLEAccel = 0x0000_4000,
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum VideoFlag {
	AnyFormat = 0x1000_0000,
	HWPalette = 0x2000_0000,
	DoubleBuf = 0x4000_0000,
	Fullscreen = 0x8000_0000usize as isize,
	// 0x8000_0000 > INT_MAX on i686
	OpenGL = 0x0000_0002,
	OpenGLBlit = 0x0000_000A,
	Resizable = 0x0000_0010,
	NoFrame = 0x0000_0020,
}

pub fn set_video_mode(
	w: isize,
	h: isize,
	bpp: isize,
	surface_flags: &[SurfaceFlag],
	video_flags: &[VideoFlag],
) -> Result<Surface, String> {
	let flags = surface_flags
		.iter()
		.fold(0u32, |flags, &flag| flags | flag as u32);
	let flags = video_flags
		.iter()
		.fold(flags, |flags, &flag| flags | flag as u32);

	unsafe {
		let raw = ll::SDL_SetVideoMode(w as c_int, h as c_int, bpp as c_int, flags);

		if raw.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(raw, false))
		}
	}
}

pub fn is_video_mode_ok(
	w: isize,
	h: isize,
	bpp: isize,
	surface_flags: &[SurfaceFlag],
	video_flags: &[VideoFlag],
) -> Option<isize> {
	let flags = surface_flags
		.iter()
		.fold(0u32, |flags, &flag| flags | flag as u32);
	let flags = video_flags
		.iter()
		.fold(flags, |flags, &flag| flags | flag as u32);

	unsafe {
		let bpp = ll::SDL_VideoModeOK(w as c_int, h as c_int, bpp as c_int, flags);

		if bpp == 0 {
			None
		} else {
			Some(bpp as isize)
		}
	}
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
pub enum VideoInfoFlag {
	HWAvailable = 0x0000_0001,
	WMAvailable = 0x0000_0002,
	BlitHW = 0x0000_0200,
	BlitHWColorkey = 0x0000_0400,
	BlitHWAlpha = 0x0000_0800,
	BlitSW = 0x0000_1000,
	BlitSWColorkey = 0x0000_2000,
	BlitSWAlpha = 0x0000_4000,
	BlitFill = 0x0000_8000,
}

#[derive(Debug, PartialEq)]
pub struct VideoInfo {
	pub flags: Vec<VideoInfoFlag>,
	pub width: isize,
	pub height: isize,
	pub format: PixelFormat,
}

fn wrap_video_info_flags(bitflags: u32) -> Vec<VideoInfoFlag> {
	let flags = [
		VideoInfoFlag::HWAvailable,
		VideoInfoFlag::WMAvailable,
		VideoInfoFlag::BlitHW,
		VideoInfoFlag::BlitHWColorkey,
		VideoInfoFlag::BlitHWAlpha,
		VideoInfoFlag::BlitSW,
		VideoInfoFlag::BlitSWColorkey,
		VideoInfoFlag::BlitSWAlpha,
		VideoInfoFlag::BlitFill,
	];

	flags
		.iter()
		.filter_map(|&flag| {
			if bitflags & (flag as u32) != 0 {
				Some(flag)
			} else {
				None
			}
		})
		.collect()
}

pub fn get_video_info() -> VideoInfo {
	let raw = unsafe { ll::SDL_GetVideoInfo() };
	VideoInfo {
		flags: wrap_video_info_flags(unsafe { (*raw).flags } as u32),
		width: unsafe { (*raw).current_w } as isize,
		height: unsafe { (*raw).current_h } as isize,
		format: wrap_pixel_format(unsafe { (*raw).vfmt }),
	}
}

#[derive(Copy, Clone)]
pub enum PaletteType {
	Logical = 1,
	Physical,
}

pub fn get_video_surface() -> Result<Surface, String> {
	let raw = unsafe { ll::SDL_GetVideoSurface() };

	if raw.is_null() {
		Err(get_error())
	} else {
		Ok(wrap_surface(raw, false))
	}
}

// TODO: get_video_modes, get_video_driver_name
#[allow(clippy::too_many_arguments)]
impl Surface {
	pub fn new(
		surface_flags: &[SurfaceFlag],
		width: isize,
		height: isize,
		bpp: isize,
		rmask: u32,
		gmask: u32,
		bmask: u32,
		amask: u32,
	) -> Result<Surface, String> {
		let flags = surface_flags
			.iter()
			.fold(0u32, |flags, flag| flags | *flag as u32);

		unsafe {
			let raw = ll::SDL_CreateRGBSurface(
				flags,
				width as c_int,
				height as c_int,
				bpp as c_int,
				rmask,
				gmask,
				bmask,
				amask,
			);

			if raw.is_null() {
				Err(get_error())
			} else {
				Ok(Surface { raw, owned: true })
			}
		}
	}

	pub fn from_bmp(path: impl Into<String>) -> Result<Surface, String> {
		let path = path.into();
		let cpath = CString::new(path).unwrap();
		let mode = CString::new("rb").unwrap();
		let raw =
			unsafe { ll::SDL_LoadBMP_RW(ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()), 1) };

		if raw.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(raw, true))
		}
	}

	// TODO: from_data (hard because the pixel data has to stay alive)

	pub fn get_width(&self) -> u16 {
		unsafe { (*self.raw).w as u16 }
	}

	pub fn get_height(&self) -> u16 {
		unsafe { (*self.raw).h as u16 }
	}

	pub fn get_size(&self) -> (u16, u16) {
		(self.get_width(), self.get_height())
	}

	pub fn get_rect(&self) -> Rect {
		Rect {
			x: 0,
			y: 0,
			w: self.get_width(),
			h: self.get_height(),
		}
	}

	pub fn update_rect(&self, rect: Rect) {
		unsafe {
			ll::SDL_UpdateRect(
				self.raw,
				i32::from(rect.x),
				i32::from(rect.y),
				u32::from(rect.w),
				u32::from(rect.h),
			);
		}
	}

	pub fn update_rects(&self, rects: &[Rect]) {
		unsafe {
			ll::SDL_UpdateRects(self.raw, rects.len() as c_int, rects.as_ptr() as *mut Rect);
		}
	}

	pub fn set_colors(&self, colors: &[Color]) -> bool {
		let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();

		unsafe { ll::SDL_SetColors(self.raw, colors.as_mut_ptr(), 0, colors.len() as c_int) == 1 }
	}

	pub fn set_palette(&self, palettes: &[PaletteType], colors: &[Color]) -> bool {
		let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();
		let flags = palettes
			.iter()
			.fold(0 as c_int, |flags, &flag| flags | flag as c_int);

		unsafe {
			ll::SDL_SetPalette(
				self.raw,
				flags,
				colors.as_mut_ptr(),
				0,
				colors.len() as c_int,
			) == 1
		}
	}

	pub fn lock(&self) -> bool {
		unsafe { ll::SDL_LockSurface(self.raw) == 0 }
	}

	/// Locks a surface so that the pixels can be directly accessed safely.
	pub fn with_lock<F: Fn(&mut [u8]) -> bool>(&self, f: F) -> bool {
		unsafe {
			if ll::SDL_LockSurface(self.raw) != 0 {
				panic!("could not lock surface");
			}
			let len = (*self.raw).pitch as usize * ((*self.raw).h as usize);
			let pixels: &mut [u8] = mem::transmute(((*self.raw).pixels, len));
			let rv = f(pixels);
			ll::SDL_UnlockSurface(self.raw);
			rv
		}
	}

	pub fn unlock(&self) {
		unsafe {
			ll::SDL_UnlockSurface(self.raw);
		}
	}

	pub fn flip(&self) -> bool {
		unsafe { ll::SDL_Flip(self.raw) == 0 }
	}

	pub fn convert(&self, fmt: &PixelFormat, flags: &[SurfaceFlag]) -> Result<Surface, String> {
		let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);

		let mut rawfmt = unwrap_pixel_format(fmt);

		let new = unsafe { ll::SDL_ConvertSurface(self.raw, &mut rawfmt, flags) };
		if new.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(new, true))
		}
	}

	pub fn try_clone(&self) -> Result<Surface, String> {
		let new =
			unsafe { ll::SDL_ConvertSurface(self.raw, (*self.raw).format, (*self.raw).flags) };
		if new.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(new, true))
		}
	}

	pub fn display_format(&self) -> Result<Surface, String> {
		let raw = unsafe { ll::SDL_DisplayFormat(self.raw) };

		if raw.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(raw, true))
		}
	}

	pub fn display_format_alpha(&self) -> Result<Surface, String> {
		let raw = unsafe { ll::SDL_DisplayFormatAlpha(self.raw) };

		if raw.is_null() {
			Err(get_error())
		} else {
			Ok(wrap_surface(raw, true))
		}
	}

	pub fn save_bmp(&self, path: impl Into<String>) -> bool {
		let path = path.into();
		let cpath = CString::new(path).unwrap();
		let mode = CString::new("wb").unwrap();
		unsafe {
			ll::SDL_SaveBMP_RW(
				self.raw,
				ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()),
				1,
			) == 0
		}
	}

	pub fn set_alpha(&self, flags: &[SurfaceFlag], alpha: u8) -> bool {
		let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);

		unsafe { ll::SDL_SetAlpha(self.raw, flags, alpha) == 0 }
	}

	pub fn set_color_key(&self, flags: &[SurfaceFlag], color: Color) -> bool {
		let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);

		unsafe {
			ll::SDL_SetColorKey(
				self.raw,
				flags,
				color.to_mapped((*self.raw).format as *const _),
			) == 0
		}
	}

	pub fn set_clip_rect(&self, rect: Rect) {
		unsafe {
			ll::SDL_SetClipRect(self.raw, &rect);
		}
	}

	pub fn get_clip_rect(&self) -> Rect {
		let rect = Rect {
			x: 0,
			y: 0,
			w: 0,
			h: 0,
		};

		unsafe {
			ll::SDL_SetClipRect(self.raw, &rect as *const Rect);
		}

		rect
	}

	pub fn blit_rect(
		&self,
		src: &Surface,
		src_rect: Option<Rect>,
		dest_rect: Option<Rect>,
	) -> bool {
		unsafe {
			ll::SDL_UpperBlit(
				src.raw,
				match src_rect {
					Some(ref rect) => rect as *const Rect as *mut Rect,
					None => ptr::null_mut(),
				},
				self.raw,
				match dest_rect {
					Some(ref rect) => rect as *const Rect as *mut Rect,
					None => ptr::null_mut(),
				},
			) == 0
		}
	}

	pub fn blit(&self, src: &Surface) -> bool {
		self.blit_rect(src, None, None)
	}

	pub fn blit_at(&self, src: &Surface, x: i16, y: i16) -> bool {
		let (w, h) = src.get_size();

		self.blit_rect(src, None, Some(Rect { x, y, w, h }))
	}

	pub fn fill_rect(&self, rect: Option<Rect>, color: Color) -> bool {
		unsafe {
			ll::SDL_FillRect(
				self.raw,
				match rect {
					Some(ref rect) => rect as *const Rect as *mut Rect,
					None => ptr::null_mut(),
				},
				color.to_mapped((*self.raw).format as *const _),
			) == 0
		}
	}

	pub fn fill(&self, color: Color) -> bool {
		self.fill_rect(None, color)
	}

	pub fn clear(&self) -> bool {
		self.fill(RGB(0, 0, 0))
	}

	pub fn draw_str(&self, font: &crate::nsdl::Font, msg: &str, x: i32, y: i32) {
		font.draw(self.raw, msg, x, y)
	}
}

impl Clone for Surface {
	fn clone(&self) -> Self {
		self.try_clone().unwrap()
	}
}

pub fn set_gamma(r: f32, g: f32, b: f32) -> bool {
	unsafe { ll::SDL_SetGamma(r as c_float, g as c_float, b as c_float) != -1 }
}

pub fn set_gamma_ramp(r: Option<[u16; 256]>, g: Option<[u16; 256]>, b: Option<[u16; 256]>) -> bool {
	unsafe {
		ll::SDL_SetGammaRamp(
			match r {
				Some(r) => r.as_ptr(),
				None => ptr::null(),
			},
			match g {
				Some(g) => g.as_ptr(),
				None => ptr::null(),
			},
			match b {
				Some(b) => b.as_ptr(),
				None => ptr::null(),
			},
		) != -1
	}
}

pub fn get_gamma_ramp() -> ([u16; 256], [u16; 256], [u16; 256]) {
	let mut r = [0u16; 256];
	let mut g = [0u16; 256];
	let mut b = [0u16; 256];

	unsafe {
		ll::SDL_GetGammaRamp(r.as_mut_ptr(), g.as_mut_ptr(), b.as_mut_ptr());
	}

	(r, g, b)
}

pub fn swap_buffers() {
	unsafe {
		ll::SDL_GL_SwapBuffers();
	}
}

// TODO: YUV


text:
#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate reqwest;
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use rocket_contrib::{Json, Value};

#[derive(Serialize, Deserialize)]
struct PushData {
    digest: String,
    pushed_at: String,
    tag: String,
}
#[derive(Serialize, Deserialize)]
struct Repository {
    date_created: String,
    name: String,
    namespace: String,
    region: String,
    repo_authentication_type: String,
    repo_full_name: String,
    repo_origin_type: String,
    repo_type: String,
}
#[derive(Serialize, Deserialize)]
struct Image {
    push_data: PushData,
    repository: Repository,
}

#[post("/", format = "application/json", data = "<image>")]
fn index(image: Json<Image>) -> Json<Value> {
    let tag = image.push_data.tag.to_string();
    let client = reqwest::Client::new();
    let payload = json! ({
        "attachments": [
            {
                "color": "good",
                "pretext": "Docker image build success",
                "title": image.repository.repo_full_name.to_string() + ":" + &tag
            }
        ]
    });
    let res = client
        .post("SLACK-WEBHOOK-URL")
        .json(&payload)
        .send();
    Json(json! ({ "status": "ok" }))
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}


text:
// adapted from https://github.com/bodil/im-rs/blob/10.2.0/src/shared.rs

// 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/.

//! Automatic `Arc` wrapping.

use alloc::sync::Arc;

/// # Automatic `Arc` wrapping
///
/// The `Shared` trait provides automatic wrapping for things which
/// take [`Arc`][alloc::sync::Arc]s, meaning that anything which takes
/// an argument of type `Shared<A>` will accept either an `A` or an
/// `Arc<A>`.
///
/// Because everything stored in `im`'s persistent data structures is
/// wrapped in [`Arc`][alloc::sync::Arc]s, `Shared` makes you have to
/// worry less about whether what you've got is an `A` or an `Arc<A>`
/// or a reference to such - the compiler will just figure it out for
/// you, which is as it should be.
///
/// [alloc::sync::Arc]: https://doc.rust-lang.org/alloc/sync/struct.Arc.html
pub trait Shared<A> {
  /// Get a new Arc pointer for this value
  fn shared(self) -> Arc<A>;
}

impl<A> Shared<A> for A {
  fn shared(self) -> Arc<A> { Arc::new(self) }
}

impl<'a, A> Shared<A> for &'a A
where A: Clone
{
  fn shared(self) -> Arc<A> { Arc::new(self.clone()) }
}

impl<A> Shared<A> for Arc<A> {
  fn shared(self) -> Arc<A> { self }
}

impl<'a, A> Shared<A> for &'a Arc<A> {
  fn shared(self) -> Arc<A> { self.clone() }
}


text:
use clap::Clap;

/// This tool decrypts backup files created & encrypted by Titanium Backup on Android.
/// You provide the input file and the target output file.
/// The passphrase is read from shell, then the file is decoded and written to the output file.
#[derive(Clap)]
#[clap(version = "0.1", author = "Jan <misternerd@users.noreply.github.com>")]
pub struct CliOpts {
    /// The encrypted input file, as created by Titanium Backup
    #[clap(short, long)]
    pub input_file: String,
    /// The output file, where you'd like to store the decrypted result
    #[clap(short, long)]
    pub output_file: String,
}


text:
//! Small example of how to instantiate a wasm module that imports one function,
//! showing how you can fill in host functionality for a wasm module.

// You can execute this example with `cargo run --example hello`

use anyhow::Result;
use wasmtime::*;

fn main() -> Result<()> {
    // Configure the initial compilation environment, creating the global
    // `Store` structure. Note that you can also tweak configuration settings
    // with a `Config` and an `Engine` if desired.
    println!("Initializing...");
    let store = Store::default();

    // Compile the wasm binary into an in-memory instance of a `Module`.
    println!("Compiling module...");
    let module = Module::from_file(store.engine(), "examples/hello.wat")?;

    // Here we handle the imports of the module, which in this case is our
    // `HelloCallback` type and its associated implementation of `Callback.
    println!("Creating callback...");
    let hello_func = Func::wrap(&store, || {
        println!("Calling back...");
        println!("> Hello World!");
    });

    // Once we've got that all set up we can then move to the instantiation
    // phase, pairing together a compiled module as well as a set of imports.
    // Note that this is where the wasm `start` function, if any, would run.
    println!("Instantiating module...");
    let imports = [hello_func.into()];
    let instance = Instance::new(&store, &module, &imports)?;

    // Next we poke around a bit to extract the `run` function from the module.
    println!("Extracting export...");
    let run = instance.get_typed_func::<(), ()>("run")?;

    // And last but not least we can call it!
    println!("Calling export...");
    run.call(())?;

    println!("Done.");
    Ok(())
}


text:
/*
 * Copyright 2019 The Starlark in Rust Authors.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use gazebo::variants::VariantName;
use thiserror::Error;

use crate::{
    analysis::types::{LintT, LintWarning},
    codemap::{CodeMap, ResolvedFileSpan, Span, Spanned},
    syntax::{
        ast::{AstExpr, AstLiteral, AstStmt, Expr, Stmt},
        AstModule,
    },
};

#[derive(Error, Debug, VariantName)]
pub(crate) enum FlowIssue {
    #[error("`return` lacks expression, but function `{0}` at {1} seems to want one due to {2}")]
    MissingReturnExpression(String, ResolvedFileSpan, ResolvedFileSpan),
    #[error("No `return` at the end, but function `{0}` seems to want one due to {1}")]
    MissingReturn(String, ResolvedFileSpan),
    #[error("Unreachable statement `{0}`")]
    Unreachable(String),
    #[error("Redundant `return` at the end of a function")]
    RedundantReturn,
    #[error("Redundant `continue` at the end of a loop")]
    RedundantContinue,
    #[error("A `load` statement not at the top of the file")]
    MisplacedLoad,
}

impl LintWarning for FlowIssue {
    fn is_serious(&self) -> bool {
        match self {
            // Sometimes people add these to make flow clearer
            FlowIssue::RedundantContinue | FlowIssue::RedundantReturn => false,
            _ => true,
        }
    }
}

fn returns(x: &AstStmt) -> Vec<(Span, Option<&AstExpr>)> {
    fn f<'a>(x: &'a AstStmt, res: &mut Vec<(Span, Option<&'a AstExpr>)>) {
        match &**x {
            Stmt::Return(ret) => res.push((x.span, ret.as_ref())),
            Stmt::Def(..) => {} // Do not descend
            _ => x.visit_stmt(|x| f(x, res)),
        }
    }

    let mut res = Vec::new();
    f(x, &mut res);
    res
}

// fail is kind of like a return with error
fn is_fail(x: &AstExpr) -> bool {
    match &**x {
        Expr::Call(x, _) => match &***x {
            Expr::Identifier(name, _) => name.node == "fail",
            _ => false,
        },
        _ => false,
    }
}

fn final_return(x: &AstStmt) -> bool {
    match &**x {
        Stmt::Return(_) => true,
        Stmt::Expression(x) if is_fail(x) => true,
        Stmt::Statements(xs) => match xs.last() {
            None => false,
            Some(x) => final_return(x),
        },
        Stmt::IfElse(_, box (x, y)) => final_return(x) && final_return(y),
        _ => false,
    }
}

fn require_return_expression(ret_type: &Option<Box<AstExpr>>) -> Option<Span> {
    match ret_type {
        None => None,
        Some(x) => match &***x {
            Expr::Identifier(x, _) if x.node == "None" => None,
            _ => Some(x.span),
        },
    }
}

fn check_stmt(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
    match &**x {
        Stmt::Def(name, _params, ret_type, body, _payload) => {
            let rets = returns(body);

            // Do I require my return statements to have an expression
            let require_expression = require_return_expression(ret_type)
                .or_else(|| rets.iter().find(|x| x.1.is_some()).map(|x| x.0));
            if let Some(reason) = require_expression {
                if !final_return(body) {
                    res.push(LintT::new(
                        codemap,
                        x.span,
                        FlowIssue::MissingReturn(
                            // Statements often end with \n, so remove that to fit nicely
                            name.node.0.trim_end().to_owned(),
                            codemap.file_span(reason).resolve(),
                        ),
                    ));
                }
                for (span, ret) in rets {
                    if ret.is_none() {
                        res.push(LintT::new(
                            codemap,
                            span,
                            FlowIssue::MissingReturnExpression(
                                name.0.clone(),
                                codemap.file_span(x.span).resolve(),
                                codemap.file_span(reason).resolve(),
                            ),
                        ))
                    }
                }
            }
        }
        _ => {}
    }
}

fn stmt(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
    check_stmt(codemap, x, res);
    x.visit_stmt(|x| stmt(codemap, x, res));
}

// Returns true if the code aborts this sequence early, due to return, fail, break or continue
fn reachable(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) -> bool {
    match &**x {
        Stmt::Break | Stmt::Continue | Stmt::Return(_) => true,
        Stmt::Expression(x) => is_fail(x),
        Stmt::Statements(xs) => {
            let mut i = xs.iter();
            while let Some(x) = i.next() {
                let aborts = reachable(codemap, x, res);
                if aborts {
                    if let Some(nxt) = i.next() {
                        res.push(LintT::new(
                            codemap,
                            nxt.span,
                            FlowIssue::Unreachable(nxt.node.to_string().trim().to_owned()),
                        ))
                    }
                    // All the remaining statements are totally unreachable, but we declared that once
                    // so don't even bother looking at them
                    return aborts;
                }
            }
            false
        }
        Stmt::IfElse(_, box (x, y)) => {
            let abort1 = reachable(codemap, x, res);
            let abort2 = reachable(codemap, y, res);
            abort1 && abort2
        }
        // For all remaining constructs, visit their children to accumulate errors,
        // but even if they are present with returns, you don't guarantee the code with inner returns
        // gets executed.
        _ => {
            x.visit_stmt(|x| {
                reachable(codemap, x, res);
            });
            false
        }
    }
}

// If you have a definition which ends with return, or a loop which ends with continue
// that is a useless statement that just
fn redundant(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
    fn check(is_loop: bool, codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
        match &**x {
            Stmt::Continue if is_loop => {
                res.push(LintT::new(codemap, x.span, FlowIssue::RedundantContinue))
            }
            Stmt::Return(None) if !is_loop => {
                res.push(LintT::new(codemap, x.span, FlowIssue::RedundantReturn))
            }
            Stmt::Statements(xs) if !xs.is_empty() => {
                check(is_loop, codemap, xs.last().unwrap(), res)
            }
            Stmt::If(_, box x) => check(is_loop, codemap, x, res),
            Stmt::IfElse(_, box (x, y)) => {
                check(is_loop, codemap, x, res);
                check(is_loop, codemap, y, res);
            }
            _ => {}
        }
    }

    fn f(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
        match &**x {
            Stmt::For(_, box (_, body)) => check(true, codemap, body, res),
            Stmt::Def(_, _, _, body, _payload) => check(false, codemap, body, res),
            _ => {}
        }
        // We always want to look inside everything for other types of violation
        x.visit_stmt(|x| f(codemap, x, res))
    }

    x.visit_stmt(|x| f(codemap, x, res));
}

fn misplaced_load(codemap: &CodeMap, x: &AstStmt, res: &mut Vec<LintT<FlowIssue>>) {
    // accumulate all statements at the top-level
    fn top_statements<'a>(x: &'a AstStmt, stmts: &mut Vec<&'a AstStmt>) {
        match &**x {
            Stmt::Statements(xs) => {
                for x in xs {
                    top_statements(x, stmts);
                }
            }
            _ => stmts.push(x),
        }
    }

    let mut stmts = Vec::new();
    top_statements(x, &mut stmts);

    // We allow loads or documentation strings, but after that, no loads
    let mut allow_loads = true;
    for x in stmts {
        match &**x {
            Stmt::Load(..) => {
                if !allow_loads {
                    res.push(LintT::new(codemap, x.span, FlowIssue::MisplacedLoad))
                }
            }
            Stmt::Expression(Spanned {
                node: Expr::Literal(AstLiteral::String(_)),
                ..
            }) => {
                // Still allow loads after a literal string (probably documentation)
            }
            _ => allow_loads = false,
        }
    }
}

pub(crate) fn flow_issues(module: &AstModule) -> Vec<LintT<FlowIssue>> {
    let mut res = Vec::new();
    stmt(&module.codemap, &module.statement, &mut res);
    reachable(&module.codemap, &module.statement, &mut res);
    redundant(&module.codemap, &module.statement, &mut res);
    misplaced_load(&module.codemap, &module.statement, &mut res);
    res
}

#[cfg(test)]
mod tests {
    use gazebo::prelude::*;

    use super::*;
    use crate::syntax::Dialect;

    fn module(x: &str) -> AstModule {
        AstModule::parse("X", x.to_owned(), &Dialect::Extended).unwrap()
    }

    impl FlowIssue {
        fn about(&self) -> &String {
            match self {
                FlowIssue::MissingReturnExpression(x, _, _) => x,
                FlowIssue::MissingReturn(x, _) => x,
                FlowIssue::Unreachable(x) => x,
                _ => panic!("Should not be used on such issues in test code"),
            }
        }
    }

    #[test]
    fn test_lint_returns() {
        let m = module(
            r#"
def no1() -> "string":
    pass
def no2():
    if x:
        return 1
def no3():
    if x:
        return
    return 1
def ok():
    def no4() -> "int":
        no4()
    pass
def yes1():
    pass
def yes2() -> "string":
    yes1()
    if x:
        return "x"
    else:
        return "y"
def yes3():
    if x:
        return
    pass
def yes4() -> "string":
    fail("die")
"#,
        );
        let mut res = Vec::new();
        stmt(&m.codemap, &m.statement, &mut res);
        assert_eq!(
            res.map(|x| x.problem.about()),
            &["no1", "no2", "no3", "no4"]
        );
    }

    #[test]
    fn test_lint_unreachable() {
        let m = module(
            r#"
def test():
    return 1
    no1
def test2():
    if x:
        return 1
    yes
def test3():
    if x:
        return
    else:
        return
    no2
    ignored
def test4():
    for x in xs:
        continue
        no3
    reachable
def test5():
    for x in xs:
        if test:
            continue
        reachable
        return
    reachable
def test6():
    fail(1)
    no4
def f():
    def g():
        return 5
    reachable
"#,
        );
        let mut res = Vec::new();
        reachable(&m.codemap, &m.statement, &mut res);
        assert_eq!(
            res.map(|x| x.problem.about()),
            &["no1", "no2", "no3", "no4"]
        );
    }

    #[test]
    fn test_lint_redundant() {
        let m = module(
            r#"
def test(): # 1
    foo
    return # bad: 3
def test2(): # 4
    return
    foo
def test3(): # 7
    if x:
        return # bad: 9
    else:
        y + 1
def test4(): # 12
    def test5():
        for x in xs:
            test
            if x:
                return
            else:
                continue # bad: 19
    test5()
def test6():
    if x:
        return
    y + 1
def test7():
    for x in xs:
        if x:
            continue
        return
"#,
        );
        let mut res = Vec::new();
        redundant(&m.codemap, &m.statement, &mut res);
        assert_eq!(
            res.map(|x| x.location.resolve_span().begin_line),
            &[3, 9, 19]
        );
    }

    #[test]
    fn test_lint_misplaced_load() {
        let m = module(
            r#"
load("a", "a")
"""
this is some comment
over multiple lines
"""
load("b", "b")

x = 1
load("c", "b")
"#,
        );
        let mut res = Vec::new();
        misplaced_load(&m.codemap, &m.statement, &mut res);
        assert_eq!(res.len(), 1);
    }
}


text:
// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

//! Scheduler which schedules the execution of `storage::Command`s.
//!
//! There is one scheduler for each store. It receives commands from clients, executes them against
//! the MVCC layer storage engine.
//!
//! Logically, the data organization hierarchy from bottom to top is row -> region -> store ->
//! database. But each region is replicated onto N stores for reliability, the replicas form a Raft
//! group, one of which acts as the leader. When the client read or write a row, the command is
//! sent to the scheduler which is on the region leader's store.
//!
//! Scheduler runs in a single-thread event loop, but command executions are delegated to a pool of
//! worker thread.
//!
//! Scheduler keeps track of all the running commands and uses latches to ensure serialized access
//! to the overlapping rows involved in concurrent commands. But note that scheduler only ensures
//! serialized access to the overlapping rows at command level, but a transaction may consist of
//! multiple commands, therefore conflicts may happen at transaction level. Transaction semantics
//! is ensured by the transaction protocol implemented in the client library, which is transparent
//! to the scheduler.

use spin::Mutex;
use std::fmt::{self, Debug, Display, Formatter};
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::sync::Arc;
use std::u64;

use kvproto::kvrpcpb::CommandPri;
use prometheus::HistogramTimer;
use tikv_util::{collections::HashMap, time::SlowTimer};

use crate::storage::kv::{with_tls_engine, Result as EngineResult};
use crate::storage::lock_manager::{self, LockMgr};
use crate::storage::txn::latch::{Latches, Lock};
use crate::storage::txn::process::{execute_callback, Executor, MsgScheduler, ProcessResult, Task};
use crate::storage::txn::sched_pool::SchedPool;
use crate::storage::txn::Error;
use crate::storage::{metrics::*, Key};
use crate::storage::{Command, Engine, Error as StorageError, StorageCb};

const TASKS_SLOTS_NUM: usize = 1 << 12; // 4096 slots.

/// Message types for the scheduler event loop.
pub enum Msg {
    RawCmd {
        cmd: Command,
        cb: StorageCb,
    },
    ReadFinished {
        cid: u64,
        pr: ProcessResult,
        tag: CommandKind,
    },
    WriteFinished {
        cid: u64,
        pr: ProcessResult,
        result: EngineResult<()>,
        tag: CommandKind,
    },
    FinishedWithErr {
        cid: u64,
        err: Error,
        tag: CommandKind,
    },
    WaitForLock {
        cid: u64,
        start_ts: u64,
        pr: ProcessResult,
        lock: lock_manager::Lock,
        is_first_lock: bool,
        wait_timeout: i64,
    },
}

/// Debug for messages.
impl Debug for Msg {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self)
    }
}

/// Display for messages.
impl Display for Msg {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match *self {
            Msg::RawCmd { ref cmd, .. } => write!(f, "RawCmd {}", cmd),
            Msg::ReadFinished { cid, .. } => write!(f, "ReadFinished [cid={}]", cid),
            Msg::WriteFinished { cid, .. } => write!(f, "WriteFinished [cid={}]", cid),
            Msg::FinishedWithErr { cid, .. } => write!(f, "FinishedWithErr [cid={}]", cid),
            Msg::WaitForLock { cid, .. } => write!(f, "WaitForLock [cid={}]", cid),
        }
    }
}

// It stores context of a task.
struct TaskContext {
    task: Option<Task>,

    lock: Lock,
    cb: StorageCb,
    write_bytes: usize,
    tag: CommandKind,
    // How long it waits on latches.
    latch_timer: Option<HistogramTimer>,
    // Total duration of a command.
    _cmd_timer: HistogramTimer,
}

impl TaskContext {
    fn new(task: Task, latches: &Latches, cb: StorageCb) -> TaskContext {
        let tag = task.cmd().tag();
        let lock = gen_command_lock(latches, task.cmd());
        // Write command should acquire write lock.
        if !task.cmd().readonly() && !lock.is_write_lock() {
            panic!("write lock is expected for command {}", task.cmd());
        }
        let write_bytes = if lock.is_write_lock() {
            task.cmd().write_bytes()
        } else {
            0
        };

        TaskContext {
            task: Some(task),
            lock,
            cb,
            write_bytes,
            tag,
            latch_timer: Some(SCHED_LATCH_HISTOGRAM_VEC.get(tag).start_coarse_timer()),
            _cmd_timer: SCHED_HISTOGRAM_VEC_STATIC.get(tag).start_coarse_timer(),
        }
    }

    fn on_schedule(&mut self) {
        self.latch_timer.take();
    }
}

struct SchedulerInner<L: LockMgr> {
    // slot_id -> { cid -> `TaskContext` } in the slot.
    task_contexts: Vec<Mutex<HashMap<u64, TaskContext>>>,

    // cmd id generator
    id_alloc: AtomicU64,

    // write concurrency control
    latches: Latches,

    sched_pending_write_threshold: usize,

    // worker pool
    worker_pool: SchedPool,

    // high priority commands and system commands will be delivered to this pool
    high_priority_pool: SchedPool,

    // used to control write flow
    running_write_bytes: AtomicUsize,

    lock_mgr: Option<L>,
}

#[inline]
fn id_index(cid: u64) -> usize {
    cid as usize % TASKS_SLOTS_NUM
}

impl<L: LockMgr> SchedulerInner<L> {
    /// Generates the next command ID.
    #[inline]
    fn gen_id(&self) -> u64 {
        let id = self.id_alloc.fetch_add(1, Ordering::Relaxed);
        id + 1
    }

    fn dequeue_task(&self, cid: u64) -> Task {
        let mut tasks = self.task_contexts[id_index(cid)].lock();
        let task = tasks.get_mut(&cid).unwrap().task.take().unwrap();
        assert_eq!(task.cid, cid);
        task
    }

    fn enqueue_task(&self, task: Task, callback: StorageCb) {
        let cid = task.cid;
        let tctx = TaskContext::new(task, &self.latches, callback);

        let running_write_bytes = self
            .running_write_bytes
            .fetch_add(tctx.write_bytes, Ordering::AcqRel) as i64;
        SCHED_WRITING_BYTES_GAUGE.set(running_write_bytes + tctx.write_bytes as i64);
        SCHED_CONTEX_GAUGE.inc();

        let mut tasks = self.task_contexts[id_index(cid)].lock();
        if tasks.insert(cid, tctx).is_some() {
            panic!("TaskContext cid={} shouldn't exist", cid);
        }
    }

    fn dequeue_task_context(&self, cid: u64) -> TaskContext {
        let tctx = self.task_contexts[id_index(cid)]
            .lock()
            .remove(&cid)
            .unwrap();

        let running_write_bytes = self
            .running_write_bytes
            .fetch_sub(tctx.write_bytes, Ordering::AcqRel) as i64;
        SCHED_WRITING_BYTES_GAUGE.set(running_write_bytes - tctx.write_bytes as i64);
        SCHED_CONTEX_GAUGE.dec();

        tctx
    }

    fn too_busy(&self) -> bool {
        fail_point!("txn_scheduler_busy", |_| true);
        self.running_write_bytes.load(Ordering::Acquire) >= self.sched_pending_write_threshold
    }

    /// Tries to acquire all the required latches for a command.
    ///
    /// Returns `true` if successful; returns `false` otherwise.
    fn acquire_lock(&self, cid: u64) -> bool {
        let mut task_contexts = self.task_contexts[id_index(cid)].lock();
        let tctx = task_contexts.get_mut(&cid).unwrap();
        if self.latches.acquire(&mut tctx.lock, cid) {
            tctx.on_schedule();
            return true;
        }
        false
    }
}

/// Scheduler which schedules the execution of `storage::Command`s.
#[derive(Clone)]
pub struct Scheduler<E: Engine, L: LockMgr> {
    // `engine` is `None` means currently the program is in scheduler worker threads.
    engine: Option<E>,
    inner: Arc<SchedulerInner<L>>,
}

unsafe impl<E: Engine, L: LockMgr> Send for Scheduler<E, L> {}

impl<E: Engine, L: LockMgr> Scheduler<E, L> {
    /// Creates a scheduler.
    pub fn new(
        engine: E,
        lock_mgr: Option<L>,
        concurrency: usize,
        worker_pool_size: usize,
        sched_pending_write_threshold: usize,
    ) -> Self {
        // Add 2 logs records how long is need to initialize TASKS_SLOTS_NUM * 2048000 `Mutex`es.
        // In a 3.5G Hz machine it needs 1.3s, which is a notable duration during start-up.
        let t = SlowTimer::new();
        let mut task_contexts = Vec::with_capacity(TASKS_SLOTS_NUM);
        for _ in 0..TASKS_SLOTS_NUM {
            task_contexts.push(Mutex::new(Default::default()));
        }

        let inner = Arc::new(SchedulerInner {
            task_contexts,
            id_alloc: AtomicU64::new(0),
            latches: Latches::new(concurrency),
            running_write_bytes: AtomicUsize::new(0),
            sched_pending_write_threshold,
            worker_pool: SchedPool::new(engine.clone(), worker_pool_size, "sched-worker-pool"),
            high_priority_pool: SchedPool::new(
                engine.clone(),
                std::cmp::max(1, worker_pool_size / 2),
                "sched-high-pri-pool",
            ),
            lock_mgr,
        });

        slow_log!(t, "initialized the transaction scheduler");
        Scheduler {
            engine: Some(engine),
            inner,
        }
    }

    pub fn run_cmd(&self, cmd: Command, callback: StorageCb) {
        self.on_receive_new_cmd(cmd, callback);
    }
}

impl<E: Engine, L: LockMgr> Scheduler<E, L> {
    fn fetch_executor(&self, priority: CommandPri, is_sys_cmd: bool) -> Executor<E, Self, L> {
        let pool = if priority == CommandPri::High || is_sys_cmd {
            self.inner.high_priority_pool.clone()
        } else {
            self.inner.worker_pool.clone()
        };
        let scheduler = Scheduler {
            engine: None,
            inner: Arc::clone(&self.inner),
        };
        Executor::new(scheduler, pool, self.inner.lock_mgr.clone())
    }

    /// Releases all the latches held by a command.
    fn release_lock(&self, lock: &Lock, cid: u64) {
        let wakeup_list = self.inner.latches.release(lock, cid);
        for wcid in wakeup_list {
            self.try_to_wake_up(wcid);
        }
    }

    fn schedule_command(&self, cmd: Command, callback: StorageCb) {
        let cid = self.inner.gen_id();
        debug!("received new command"; "cid" => cid, "cmd" => ?cmd);

        let tag = cmd.tag();
        let priority_tag = cmd.priority_tag();
        let task = Task::new(cid, cmd);
        // TODO: enqueue_task should return an reference of the tctx.
        self.inner.enqueue_task(task, callback);
        self.try_to_wake_up(cid);
        SCHED_STAGE_COUNTER_VEC.get(tag).new.inc();
        SCHED_COMMANDS_PRI_COUNTER_VEC_STATIC
            .get(priority_tag)
            .inc();
    }

    /// Tries to acquire all the necessary latches. If all the necessary latches are acquired,
    /// the method initiates a get snapshot operation for further processing.
    fn try_to_wake_up(&self, cid: u64) {
        if self.inner.acquire_lock(cid) {
            self.get_snapshot(cid);
        }
    }

    fn on_receive_new_cmd(&self, cmd: Command, callback: StorageCb) {
        // write flow control
        if cmd.need_flow_control() && self.inner.too_busy() {
            SCHED_TOO_BUSY_COUNTER_VEC.get(cmd.tag()).inc();
            execute_callback(
                callback,
                ProcessResult::Failed {
                    err: StorageError::SchedTooBusy,
                },
            );
            return;
        }
        self.schedule_command(cmd, callback);
    }

    /// Initiates an async operation to get a snapshot from the storage engine, then posts a
    /// `SnapshotFinished` message back to the event loop when it finishes.
    fn get_snapshot(&self, cid: u64) {
        let task = self.inner.dequeue_task(cid);
        let tag = task.tag;
        let ctx = task.context().clone();
        let executor = self.fetch_executor(task.priority(), task.cmd().is_sys_cmd());

        let cb = Box::new(move |(cb_ctx, snapshot)| {
            executor.execute(cb_ctx, snapshot, task);
        });

        let f = |engine: &E| {
            if let Err(e) = engine.async_snapshot(&ctx, cb) {
                SCHED_STAGE_COUNTER_VEC.get(tag).async_snapshot_err.inc();

                info!("engine async_snapshot failed"; "err" => ?e);
                self.finish_with_err(cid, e.into());
            } else {
                SCHED_STAGE_COUNTER_VEC.get(tag).snapshot.inc();
            }
        };

        if let Some(engine) = self.engine.as_ref() {
            f(engine)
        } else {
            // The program is currently in scheduler worker threads.
            // Safety: `self.inner.worker_pool` should ensure that a TLS engine exists.
            unsafe { with_tls_engine(f) }
        }
    }

    /// Calls the callback with an error.
    fn finish_with_err(&self, cid: u64, err: Error) {
        debug!("write command finished with error"; "cid" => cid);
        let tctx = self.inner.dequeue_task_context(cid);

        SCHED_STAGE_COUNTER_VEC.get(tctx.tag).error.inc();

        let pr = ProcessResult::Failed {
            err: StorageError::from(err),
        };
        execute_callback(tctx.cb, pr);

        self.release_lock(&tctx.lock, cid);
    }

    /// Event handler for the success of read.
    ///
    /// If a next command is present, continues to execute; otherwise, delivers the result to the
    /// callback.
    fn on_read_finished(&self, cid: u64, pr: ProcessResult, tag: CommandKind) {
        SCHED_STAGE_COUNTER_VEC.get(tag).read_finish.inc();

        debug!("read command finished"; "cid" => cid);
        let tctx = self.inner.dequeue_task_context(cid);
        if let ProcessResult::NextCommand { cmd } = pr {
            SCHED_STAGE_COUNTER_VEC.get(tag).next_cmd.inc();
            self.schedule_command(cmd, tctx.cb);
        } else {
            execute_callback(tctx.cb, pr);
        }

        self.release_lock(&tctx.lock, cid);
    }

    /// Event handler for the success of write.
    fn on_write_finished(
        &self,
        cid: u64,
        pr: ProcessResult,
        result: EngineResult<()>,
        tag: CommandKind,
    ) {
        SCHED_STAGE_COUNTER_VEC.get(tag).write_finish.inc();

        debug!("write command finished"; "cid" => cid);
        let tctx = self.inner.dequeue_task_context(cid);
        let pr = match result {
            Ok(()) => pr,
            Err(e) => ProcessResult::Failed {
                err: StorageError::from(e),
            },
        };
        if let ProcessResult::NextCommand { cmd } = pr {
            SCHED_STAGE_COUNTER_VEC.get(tag).next_cmd.inc();
            self.schedule_command(cmd, tctx.cb);
        } else {
            execute_callback(tctx.cb, pr);
        }

        self.release_lock(&tctx.lock, cid);
    }

    /// Event handler for the request of waiting for lock
    fn on_wait_for_lock(
        &self,
        cid: u64,
        start_ts: u64,
        pr: ProcessResult,
        lock: lock_manager::Lock,
        is_first_lock: bool,
        wait_timeout: i64,
    ) {
        debug!("command waits for lock released"; "cid" => cid);
        let tctx = self.inner.dequeue_task_context(cid);
        SCHED_STAGE_COUNTER_VEC.get(tctx.tag).lock_wait.inc();
        self.inner.lock_mgr.as_ref().unwrap().wait_for(
            start_ts,
            tctx.cb,
            pr,
            lock,
            is_first_lock,
            wait_timeout,
        );
        self.release_lock(&tctx.lock, cid);
    }
}

impl<E: Engine, L: LockMgr> MsgScheduler for Scheduler<E, L> {
    fn on_msg(&self, task: Msg) {
        match task {
            Msg::ReadFinished { cid, tag, pr } => self.on_read_finished(cid, pr, tag),
            Msg::WriteFinished {
                cid,
                tag,
                pr,
                result,
            } => self.on_write_finished(cid, pr, result, tag),
            Msg::FinishedWithErr { cid, err, .. } => self.finish_with_err(cid, err),
            Msg::WaitForLock {
                cid,
                start_ts,
                pr,
                lock,
                is_first_lock,
                wait_timeout,
            } => self.on_wait_for_lock(cid, start_ts, pr, lock, is_first_lock, wait_timeout),
            _ => unreachable!(),
        }
    }
}

fn gen_command_lock(latches: &Latches, cmd: &Command) -> Lock {
    match *cmd {
        Command::Prewrite { ref mutations, .. } => {
            let keys: Vec<&Key> = mutations.iter().map(|x| x.key()).collect();
            latches.gen_lock(&keys)
        }
        Command::ResolveLock { ref key_locks, .. } => {
            let keys: Vec<&Key> = key_locks.iter().map(|x| &x.0).collect();
            latches.gen_lock(&keys)
        }
        Command::AcquirePessimisticLock { ref keys, .. } => {
            let keys: Vec<&Key> = keys.iter().map(|x| &x.0).collect();
            latches.gen_lock(&keys)
        }
        Command::ResolveLockLite {
            ref resolve_keys, ..
        } => latches.gen_lock(resolve_keys),
        Command::Commit { ref keys, .. }
        | Command::Rollback { ref keys, .. }
        | Command::PessimisticRollback { ref keys, .. } => latches.gen_lock(keys),
        Command::Cleanup { ref key, .. } => latches.gen_lock(&[key]),
        Command::Pause { ref keys, .. } => latches.gen_lock(keys),
        Command::TxnHeartBeat {
            ref primary_key, ..
        } => latches.gen_lock(&[primary_key]),
        Command::CheckTxnStatus {
            ref primary_key, ..
        } => latches.gen_lock(&[primary_key]),

        // Avoid using wildcard _ here to avoid forgetting add new commands here.
        Command::ScanLock { .. }
        | Command::DeleteRange { .. }
        | Command::MvccByKey { .. }
        | Command::MvccByStartTs { .. } => Lock::new(vec![]),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::storage::mvcc;
    use crate::storage::txn::latch::*;
    use crate::storage::{Command, Key, Mutation, Options};
    use kvproto::kvrpcpb::Context;
    use tikv_util::collections::HashMap;

    #[test]
    fn test_command_latches() {
        let mut temp_map = HashMap::default();
        temp_map.insert(10, 20);
        let readonly_cmds = vec![
            Command::ScanLock {
                ctx: Context::default(),
                max_ts: 5,
                start_key: None,
                limit: 0,
            },
            Command::ResolveLock {
                ctx: Context::default(),
                txn_status: temp_map.clone(),
                scan_key: None,
                key_locks: vec![],
            },
            Command::MvccByKey {
                ctx: Context::default(),
                key: Key::from_raw(b"k"),
            },
            Command::MvccByStartTs {
                ctx: Context::default(),
                start_ts: 25,
            },
        ];
        let write_cmds = vec![
            Command::Prewrite {
                ctx: Context::default(),
                mutations: vec![Mutation::Put((Key::from_raw(b"k"), b"v".to_vec()))],
                primary: b"k".to_vec(),
                start_ts: 10,
                options: Options::default(),
            },
            Command::AcquirePessimisticLock {
                ctx: Context::default(),
                keys: vec![(Key::from_raw(b"k"), false)],
                primary: b"k".to_vec(),
                start_ts: 10,
                options: Options::default(),
            },
            Command::Commit {
                ctx: Context::default(),
                keys: vec![Key::from_raw(b"k")],
                lock_ts: 10,
                commit_ts: 20,
            },
            Command::Cleanup {
                ctx: Context::default(),
                key: Key::from_raw(b"k"),
                start_ts: 10,
                current_ts: 20,
            },
            Command::Rollback {
                ctx: Context::default(),
                keys: vec![Key::from_raw(b"k")],
                start_ts: 10,
            },
            Command::PessimisticRollback {


text:
use hacspec_lib::prelude::*;

mod test_util;
use test_util::*;

#[test]
fn test_public_array_u32() {
    array!(TestSeq, 64, u32);

    both_arrays!(PublicState, State, 73, U32, u32);
    let x = PublicState::new();
    let y: State = State::from_public(x);
    let _z: PublicState = PublicState::from_secret_declassify(y);
}

// ==== Test Array Numeric Implementation ==== //

#[test]
fn test_ops_u8() {
    array!(Array55, 55, u8);
    let x = Array55::from_native_slice(&get_random_vec_u8(55));
    let y = Array55::from_native_slice(&get_random_vec_u8(55));
    let z1 = x + y;
    let z2 = x - z1;
    let mut z3 = x * z2;
    for i in 0..z3.len() {
        if z3[i] == 0 {
            z3[i] = 1
        }
    }
    let _z = x / z3;
}

#[test]
fn test_ops_u16() {
    array!(Array55, 55, u16);
    let x = Array55::from_native_slice(&get_random_vec_u16(55));
    let y = Array55::from_native_slice(&get_random_vec_u16(55));
    let z1 = x + y;
    let z2 = x - z1;
    let mut z3 = x * z2;
    for i in 0..z3.len() {
        if z3[i] == 0 {
            z3[i] = 1
        }
    }
    let _z = x / z3;
}

#[test]
fn test_ops_u32() {
    array!(Array55, 55, u32);
    let x = Array55::from_native_slice(&get_random_vec_u32(55));
    let y = Array55::from_native_slice(&get_random_vec_u32(55));
    let z1 = x + y;
    let z2 = x - z1;
    let mut z3 = x * z2;
    for i in 0..z3.len() {
        if z3[i] == 0 {
            z3[i] = 1
        }
    }
    let _z = x / z3;
}

#[test]
fn test_ops_u64() {
    array!(Array55, 55, u64);
    let x = Array55::from_native_slice(&get_random_vec_u64(55));
    let y = Array55::from_native_slice(&get_random_vec_u64(55));
    let z1 = x + y;
    let z2 = x - z1;
    let mut z3 = x * z2;
    for i in 0..z3.len() {
        if z3[i] == 0 {
            z3[i] = 1
        }
    }
    let _z = x / z3;
}

#[test]
fn test_ops_u128() {
    array!(Array55, 55, u128);
    let x = Array55::from_native_slice(&get_random_vec_u128(55));
    let y = Array55::from_native_slice(&get_random_vec_u128(55));
    let z1 = x + y;
    let z2 = x - z1;
    let mut z3 = x * z2;
    for i in 0..z3.len() {
        if z3[i] == 0 {
            z3[i] = 1
        }
    }
    let _z = x / z3;
}


text:
use pyo3::types::PyModule;
use pyo3::{pyclass, pyfunction, pymodule, FromPyObject};
use pyo3::{wrap_pyfunction, Py, PyResult, Python};
use tokio::runtime::Builder;

use hyperqueue::transfer::connection::ClientConnection;

use crate::job::{submit_job_impl, JobDescription};
use crate::server::{connect_to_server_impl, stop_server_impl};
use crate::utils::run_future;

mod job;
mod marshal;
mod server;
mod utils;

/// Opaque object that is returned by `connect_to_server` and then passed from the Python side
/// to various Rust functions.
#[pyclass]
struct HqContext {
    connection: ClientConnection,
}

type ContextPtr = Py<HqContext>;

#[pyfunction]
fn connect_to_server(py: Python, directory: Option<String>) -> PyResult<ContextPtr> {
    connect_to_server_impl(py, directory)
}

#[pyfunction]
fn stop_server(py: Python, ctx: ContextPtr) -> PyResult<()> {
    stop_server_impl(py, ctx)
}

#[pyfunction]
fn submit_job(py: Python, ctx: ContextPtr, job: JobDescription) -> PyResult<u32> {
    submit_job_impl(py, ctx, job)
}

#[pymodule]
fn hyperqueue(_py: Python, m: &PyModule) -> PyResult<()> {
    // Use a single-threaded Tokio runtime for all Rust async operations
    let mut builder = Builder::new_current_thread();
    builder.enable_all();
    pyo3_asyncio::tokio::init(builder);

    m.add_class::<HqContext>()?;
    m.add_function(wrap_pyfunction!(connect_to_server, m)?)?;
    m.add_function(wrap_pyfunction!(stop_server, m)?)?;
    m.add_function(wrap_pyfunction!(submit_job, m)?)?;
    Ok(())
}


text:
use super::*;
use crate::util::random;

#[derive(Debug)]
pub struct DevRandom;

impl INode for DevRandom {
    fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result<usize> {
        random::get_random(buf).map_err(|_| FsError::Again)?;
        Ok(buf.len())
    }

    fn write_at(&self, offset: usize, buf: &[u8]) -> vfs::Result<usize> {
        Err(FsError::PermError)
    }

    fn poll(&self) -> vfs::Result<vfs::PollStatus> {
        Ok(vfs::PollStatus {
            read: true,
            write: false,
            error: false,
        })
    }

    fn metadata(&self) -> vfs::Result<Metadata> {
        Ok(Metadata {
            dev: 1,
            inode: 0,
            size: 0,
            blk_size: 0,
            blocks: 0,
            atime: Timespec { sec: 0, nsec: 0 },
            mtime: Timespec { sec: 0, nsec: 0 },
            ctime: Timespec { sec: 0, nsec: 0 },
            type_: vfs::FileType::CharDevice,
            mode: 0o444,
            nlinks: 1,
            uid: 0,
            gid: 0,
            rdev: 0,
        })
    }

    fn as_any_ref(&self) -> &dyn Any {
        self
    }
}