<commit_before>use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::reflect::error::ReflectError;
use crate::reflect::field::FieldDescriptorImpl;
use crate::reflect::file::common::FileDescriptorCommon;
use crate::reflect::file::dynamic::DynamicFileDescriptor;
use crate::reflect::file::fds::FdsBuilder;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::name::protobuf_name_starts_with_package;
use crate::reflect::service::ServiceDescriptor;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::GeneratedFileDescriptor;
use crate::reflect::MessageDescriptor;
use crate::reflect::Syntax;

pub(crate) mod building;
pub(crate) mod common;
pub(crate) mod dynamic;
pub(crate) mod fds;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod syntax;

#[derive(Clone, Debug)]
pub(crate) enum FileDescriptorImpl {
    Generated(&'static GeneratedFileDescriptor),
    Dynamic(Arc<DynamicFileDescriptor>),
}

impl PartialEq for FileDescriptorImpl {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (FileDescriptorImpl::Generated(a), FileDescriptorImpl::Generated(b)) => {
                *a as *const GeneratedFileDescriptor == *b as *const GeneratedFileDescriptor
            }
            (FileDescriptorImpl::Dynamic(a), FileDescriptorImpl::Dynamic(b)) => Arc::ptr_eq(a, b),
            _ => false,
        }
    }
}

impl Hash for FileDescriptorImpl {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            FileDescriptorImpl::Generated(g) => {
                Hash::hash(&(*g as *const GeneratedFileDescriptor), state)
            }
            FileDescriptorImpl::Dynamic(a) => {
                Hash::hash(&(&**a as *const DynamicFileDescriptor), state)
            }
        }
    }
}

impl Eq for FileDescriptorImpl {}

/// Reflection for objects defined in `.proto` file (messages, enums, etc).
///
/// The object is refcounted: clone is shallow.
///
/// The equality performs pointer comparison: two clones of the same `FileDescriptor`
/// objects are equal, but two `FileDescriptor` objects created from the same `FileDescriptorProto`
/// objects are **not** equal.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct FileDescriptor {
    pub(crate) imp: FileDescriptorImpl,
}

impl FileDescriptor {
    pub(crate) fn index(&self) -> &FileDescriptorCommon {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.common,
            FileDescriptorImpl::Dynamic(d) => &d.common,
        }
    }

    pub(crate) fn message_index_entry(&self, index: usize) -> &FileIndexMessageEntry {
        &self.index().index.messages[index]
    }

    pub(crate) fn message_proto(&self, index: usize) -> &DescriptorProto {
        self.message_index_entry(index)
            .path
            .eval(self.proto())
            .unwrap()
    }

    /// Syntax of current file.
    pub fn syntax(&self) -> Syntax {
        Syntax::parse(self.proto().syntax()).unwrap_or(Syntax::Proto2)
    }

    /// Get top-level messages.
    pub fn messages(&self) -> Vec<MessageDescriptor> {
        self.index()
            .index
            .top_level_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.clone(), *i))
            .collect()
    }

    /// Get top-level enums.
    pub fn enums(&self) -> Vec<EnumDescriptor> {
        self.proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.clone(), i))
            .collect()
    }

    /// Get services defined in `.proto` file.
    pub fn services(&self) -> Vec<ServiceDescriptor> {
        self.proto()
            .service
            .iter()
            .enumerate()
            .map(|(i, _)| ServiceDescriptor::new(self.clone(), i))
            .collect()
    }

    /// Extension fields.
    pub fn extensions(&self) -> Vec<FieldDescriptor> {
        (0..self.index().extensions.len())
            .map(move |index| FieldDescriptor {
                imp: FieldDescriptorImpl::ExtensionInFile(self.clone(), index),
            })
            .collect()
    }

    /// Find message by name relative to the package.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn message_by_package_relative_name(&self, name: &str) -> Option<MessageDescriptor> {
        self.index()
            .index
            .message_by_name_to_package
            .get(name)
            .map(|&index| MessageDescriptor::new(self.clone(), index))
    }

    /// Find message by name relative to the package.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn enum_by_package_relative_name(&self, name: &str) -> Option<EnumDescriptor> {
        self.index()
            .index
            .enums_by_name_to_package
            .get(name)
            .map(|&index| EnumDescriptor::new(self.clone(), index))
    }

    /// Find message by fully-qualified name.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn message_by_full_name(&self, name: &str) -> Option<MessageDescriptor> {
        if let Some(name_to_package) =
            protobuf_name_starts_with_package(name, self.proto().package())
        {
            self.message_by_package_relative_name(name_to_package)
        } else {
            None
        }
    }

    /// Find enum by name fully-qualified name.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn enum_by_full_name(&self, name: &str) -> Option<EnumDescriptor> {
        if let Some(name_to_package) =
            protobuf_name_starts_with_package(name, self.proto().package())
        {
            self.enum_by_package_relative_name(name_to_package)
        } else {
            None
        }
    }

    /// This function is called from generated code, it is not stable, and should not be called.
    #[doc(hidden)]
    // TODO: rename
    pub fn new_generated_2(generated: &'static GeneratedFileDescriptor) -> FileDescriptor {
        FileDescriptor {
            imp: FileDescriptorImpl::Generated(generated),
        }
    }

    /// Dynamic message created from [`FileDescriptorProto`] without generated files.
    pub fn new_dynamic(
        proto: FileDescriptorProto,
        dependencies: Vec<FileDescriptor>,
    ) -> crate::Result<FileDescriptor> {
        // remove undeclared dependencies
        let dependencies_index: HashMap<_, &FileDescriptor> =
            dependencies.iter().map(|d| (d.proto().name(), d)).collect();

        if dependencies_index.len() != dependencies.len() {
            return Err(ReflectError::NonUniqueDependencies(
                dependencies
                    .iter()
                    .map(|d| d.proto().name())
                    .collect::<Vec<_>>()
                    .join(", "),
            )
            .into());
        }

        let dependencies: Vec<FileDescriptor> = proto
            .dependency
            .iter()
            .map(|d| {
                let dep = dependencies_index.get(d.as_str());
                match dep {
                    Some(dep) => Ok((*dep).clone()),
                    None => Err(ReflectError::DependencyNotFound(
                        d.clone(),
                        proto.name().to_owned(),
                        dependencies
                            .iter()
                            .map(|d| d.proto().name())
                            .collect::<Vec<_>>()
                            .join(", "),
                    )
                    .into()),
                }
            })
            .collect::<crate::Result<Vec<_>>>()?;

        Ok(FileDescriptor {
            imp: FileDescriptorImpl::Dynamic(Arc::new(DynamicFileDescriptor::new(
                proto,
                dependencies,
            )?)),
        })
    }

    /// Create a set of file descriptors from individual file descriptors.
    pub fn new_dynamic_fds(protos: Vec<FileDescriptorProto>) -> crate::Result<Vec<FileDescriptor>> {
        FdsBuilder::build(protos)
    }

    /// `.proto` data for this file.
    pub fn proto(&self) -> &FileDescriptorProto {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.proto,
            FileDescriptorImpl::Dynamic(d) => &d.proto,
        }
    }

    /// Direct dependencies of this file.
    pub fn deps(&self) -> &[FileDescriptor] {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.common.dependencies,
            FileDescriptorImpl::Dynamic(d) => &d.common.dependencies,
        }
    }

    /// Subset of dependencies which are public
    pub fn public_deps(&self) -> Vec<FileDescriptor> {
        self.proto()
            .public_dependency
            .iter()
            .map(|&i| self.deps()[i as usize].clone())
            .collect()
    }

    fn _all_files(&self) -> Vec<&FileDescriptor> {
        let mut r = Vec::new();
        let mut visited = HashSet::new();

        let mut stack = Vec::new();
        stack.push(self);
        while let Some(file) = stack.pop() {
            if !visited.insert(file) {
                continue;
            }

            r.push(file);
            stack.extend(file.deps());
        }

        r
    }
}

#[cfg(test)]
mod test {
    use crate::descriptor;

    #[test]
    #[cfg_attr(miri, ignore)] // TODO: figure out why this test hangs on Miri.
    fn eq() {
        assert!(descriptor::file_descriptor() == descriptor::file_descriptor().clone());
    }
}
<commit_msg>Return iterator from reflection<commit_after>use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::reflect::error::ReflectError;
use crate::reflect::field::FieldDescriptorImpl;
use crate::reflect::file::common::FileDescriptorCommon;
use crate::reflect::file::dynamic::DynamicFileDescriptor;
use crate::reflect::file::fds::FdsBuilder;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::name::protobuf_name_starts_with_package;
use crate::reflect::service::ServiceDescriptor;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::GeneratedFileDescriptor;
use crate::reflect::MessageDescriptor;
use crate::reflect::Syntax;

pub(crate) mod building;
pub(crate) mod common;
pub(crate) mod dynamic;
pub(crate) mod fds;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod syntax;

#[derive(Clone, Debug)]
pub(crate) enum FileDescriptorImpl {
    Generated(&'static GeneratedFileDescriptor),
    Dynamic(Arc<DynamicFileDescriptor>),
}

impl PartialEq for FileDescriptorImpl {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (FileDescriptorImpl::Generated(a), FileDescriptorImpl::Generated(b)) => {
                *a as *const GeneratedFileDescriptor == *b as *const GeneratedFileDescriptor
            }
            (FileDescriptorImpl::Dynamic(a), FileDescriptorImpl::Dynamic(b)) => Arc::ptr_eq(a, b),
            _ => false,
        }
    }
}

impl Hash for FileDescriptorImpl {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            FileDescriptorImpl::Generated(g) => {
                Hash::hash(&(*g as *const GeneratedFileDescriptor), state)
            }
            FileDescriptorImpl::Dynamic(a) => {
                Hash::hash(&(&**a as *const DynamicFileDescriptor), state)
            }
        }
    }
}

impl Eq for FileDescriptorImpl {}

/// Reflection for objects defined in `.proto` file (messages, enums, etc).
///
/// The object is refcounted: clone is shallow.
///
/// The equality performs pointer comparison: two clones of the same `FileDescriptor`
/// objects are equal, but two `FileDescriptor` objects created from the same `FileDescriptorProto`
/// objects are **not** equal.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct FileDescriptor {
    pub(crate) imp: FileDescriptorImpl,
}

impl FileDescriptor {
    pub(crate) fn index(&self) -> &FileDescriptorCommon {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.common,
            FileDescriptorImpl::Dynamic(d) => &d.common,
        }
    }

    pub(crate) fn message_index_entry(&self, index: usize) -> &FileIndexMessageEntry {
        &self.index().index.messages[index]
    }

    pub(crate) fn message_proto(&self, index: usize) -> &DescriptorProto {
        self.message_index_entry(index)
            .path
            .eval(self.proto())
            .unwrap()
    }

    /// Syntax of current file.
    pub fn syntax(&self) -> Syntax {
        Syntax::parse(self.proto().syntax()).unwrap_or(Syntax::Proto2)
    }

    // TODO: return iterator.
    /// Get top-level messages.
    pub fn messages(&self) -> Vec<MessageDescriptor> {
        self.index()
            .index
            .top_level_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.clone(), *i))
            .collect()
    }

    /// Get top-level enums.
    pub fn enums(&self) -> Vec<EnumDescriptor> {
        self.proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.clone(), i))
            .collect()
    }

    /// Get services defined in `.proto` file.
    pub fn services(&self) -> Vec<ServiceDescriptor> {
        self.proto()
            .service
            .iter()
            .enumerate()
            .map(|(i, _)| ServiceDescriptor::new(self.clone(), i))
            .collect()
    }

    /// Extension fields.
    pub fn extensions(&self) -> Vec<FieldDescriptor> {
        (0..self.index().extensions.len())
            .map(move |index| FieldDescriptor {
                imp: FieldDescriptorImpl::ExtensionInFile(self.clone(), index),
            })
            .collect()
    }

    /// Find message by name relative to the package.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn message_by_package_relative_name(&self, name: &str) -> Option<MessageDescriptor> {
        self.index()
            .index
            .message_by_name_to_package
            .get(name)
            .map(|&index| MessageDescriptor::new(self.clone(), index))
    }

    /// Find message by name relative to the package.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn enum_by_package_relative_name(&self, name: &str) -> Option<EnumDescriptor> {
        self.index()
            .index
            .enums_by_name_to_package
            .get(name)
            .map(|&index| EnumDescriptor::new(self.clone(), index))
    }

    /// Find message by fully-qualified name.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn message_by_full_name(&self, name: &str) -> Option<MessageDescriptor> {
        if let Some(name_to_package) =
            protobuf_name_starts_with_package(name, self.proto().package())
        {
            self.message_by_package_relative_name(name_to_package)
        } else {
            None
        }
    }

    /// Find enum by name fully-qualified name.
    ///
    /// Only search in the current file, not in any dependencies.
    pub fn enum_by_full_name(&self, name: &str) -> Option<EnumDescriptor> {
        if let Some(name_to_package) =
            protobuf_name_starts_with_package(name, self.proto().package())
        {
            self.enum_by_package_relative_name(name_to_package)
        } else {
            None
        }
    }

    /// This function is called from generated code, it is not stable, and should not be called.
    #[doc(hidden)]
    // TODO: rename
    pub fn new_generated_2(generated: &'static GeneratedFileDescriptor) -> FileDescriptor {
        FileDescriptor {
            imp: FileDescriptorImpl::Generated(generated),
        }
    }

    /// Dynamic message created from [`FileDescriptorProto`] without generated files.
    pub fn new_dynamic(
        proto: FileDescriptorProto,
        dependencies: Vec<FileDescriptor>,
    ) -> crate::Result<FileDescriptor> {
        // remove undeclared dependencies
        let dependencies_index: HashMap<_, &FileDescriptor> =
            dependencies.iter().map(|d| (d.proto().name(), d)).collect();

        if dependencies_index.len() != dependencies.len() {
            return Err(ReflectError::NonUniqueDependencies(
                dependencies
                    .iter()
                    .map(|d| d.proto().name())
                    .collect::<Vec<_>>()
                    .join(", "),
            )
            .into());
        }

        let dependencies: Vec<FileDescriptor> = proto
            .dependency
            .iter()
            .map(|d| {
                let dep = dependencies_index.get(d.as_str());
                match dep {
                    Some(dep) => Ok((*dep).clone()),
                    None => Err(ReflectError::DependencyNotFound(
                        d.clone(),
                        proto.name().to_owned(),
                        dependencies
                            .iter()
                            .map(|d| d.proto().name())
                            .collect::<Vec<_>>()
                            .join(", "),
                    )
                    .into()),
                }
            })
            .collect::<crate::Result<Vec<_>>>()?;

        Ok(FileDescriptor {
            imp: FileDescriptorImpl::Dynamic(Arc::new(DynamicFileDescriptor::new(
                proto,
                dependencies,
            )?)),
        })
    }

    /// Create a set of file descriptors from individual file descriptors.
    pub fn new_dynamic_fds(protos: Vec<FileDescriptorProto>) -> crate::Result<Vec<FileDescriptor>> {
        FdsBuilder::build(protos)
    }

    /// `.proto` data for this file.
    pub fn proto(&self) -> &FileDescriptorProto {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.proto,
            FileDescriptorImpl::Dynamic(d) => &d.proto,
        }
    }

    /// Direct dependencies of this file.
    pub fn deps(&self) -> &[FileDescriptor] {
        match &self.imp {
            FileDescriptorImpl::Generated(g) => &g.common.dependencies,
            FileDescriptorImpl::Dynamic(d) => &d.common.dependencies,
        }
    }

    /// Subset of dependencies which are public
    pub fn public_deps(&self) -> Vec<FileDescriptor> {
        self.proto()
            .public_dependency
            .iter()
            .map(|&i| self.deps()[i as usize].clone())
            .collect()
    }

    fn _all_files(&self) -> Vec<&FileDescriptor> {
        let mut r = Vec::new();
        let mut visited = HashSet::new();

        let mut stack = Vec::new();
        stack.push(self);
        while let Some(file) = stack.pop() {
            if !visited.insert(file) {
                continue;
            }

            r.push(file);
            stack.extend(file.deps());
        }

        r
    }
}

#[cfg(test)]
mod test {
    use crate::descriptor;

    #[test]
    #[cfg_attr(miri, ignore)] // TODO: figure out why this test hangs on Miri.
    fn eq() {
        assert!(descriptor::file_descriptor() == descriptor::file_descriptor().clone());
    }
}
<|endoftext|>


<commit_before>
fn main() {}
<commit_msg>Bandwidth server many up example, unfinished<commit_after>extern crate libmodbus_rs;

mod unit_test_config;

use libmodbus_rs::{Modbus, ModbusMapping, ModbusServer, ModbusTCP, ModbusRTU};
use std::env;
use std::io::Error;
use unit_test_config::*;

const NB_CONNECTION: i32 = 5;

fn run() -> Result<(), std::io::Error> {
    let mut modbus = Modbus::new_tcp("127.0.0.1", 1502).expect("Could not create modbus TCP context");

    let mut mb_mapping = ModbusMapping::new(Modbus::MAX_READ_BITS, 0,
                                            Modbus::MAX_READ_REGISTERS, 0).expect("Failed to allocate the mapping");

    let mut server_socket = modbus.tcp_listen(NB_CONNECTION).expect("Unable to listen TCP connection");

    Ok(())
}

fn main() {
    if let Err(ref err) = run() {
        println!("{}", Modbus::strerror(err.raw_os_error().unwrap()));

        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>use crate::{Pointable, Pointer};
use eyre::{bail, Result};
use node_address::Address;
use node_dispatch::dispatch_work;
use stencila_schema::*;

impl Pointable for CreativeWorkTypes {
    /// Resolve an [`Address`] into a node [`Pointer`].
    ///
    /// `CreativeWorkTypes` is one of the pointer variants so return a `Pointer::Work` if
    /// the address is empty. Otherwise dispatch to variant.
    fn resolve(&mut self, address: &mut Address) -> Result<Pointer> {
        match address.is_empty() {
            true => Ok(Pointer::Work(self)),
            false => dispatch_work!(self, resolve, address),
        }
    }

    /// Find a node based on its `id` and return a [`Pointer`] to it.
    ///
    /// Dispatch to variant and if it returns `Pointer::Some` then rewrite to `Pointer::Work`
    fn find(&mut self, id: &str) -> Pointer {
        match dispatch_work!(self, find, id) {
            Pointer::Some => Pointer::Work(self),
            _ => Pointer::None,
        }
    }
}

// Implementations for `CreativeWork` structs. Presently none of the descendants of these
// works are made pointable but they may be done in the future.

pointable_struct!(Article);
pointable_struct!(AudioObject);
pointable_struct!(Claim);
pointable_struct!(Collection);
pointable_struct!(Comment);
pointable_struct!(CreativeWork);
pointable_struct!(Datatable);
pointable_struct!(Figure);
pointable_struct!(ImageObject);
pointable_struct!(MediaObject);
pointable_struct!(Periodical);
pointable_struct!(PublicationIssue);
pointable_struct!(PublicationVolume);
pointable_struct!(Review);
pointable_struct!(SoftwareApplication);
pointable_struct!(SoftwareSourceCode);
pointable_struct!(Table);
pointable_struct!(VideoObject);
<commit_msg>fix(Node pointers): Add fields containing nodes that need to be pointed to<commit_after>use crate::{Pointable, Pointer};
use eyre::{bail, Result};
use node_address::Address;
use node_dispatch::dispatch_work;
use stencila_schema::*;

impl Pointable for CreativeWorkTypes {
    /// Resolve an [`Address`] into a node [`Pointer`].
    ///
    /// `CreativeWorkTypes` is one of the pointer variants so return a `Pointer::Work` if
    /// the address is empty. Otherwise dispatch to variant.
    fn resolve(&mut self, address: &mut Address) -> Result<Pointer> {
        match address.is_empty() {
            true => Ok(Pointer::Work(self)),
            false => dispatch_work!(self, resolve, address),
        }
    }

    /// Find a node based on its `id` and return a [`Pointer`] to it.
    ///
    /// Dispatch to variant and if it returns `Pointer::Some` then rewrite to `Pointer::Work`
    fn find(&mut self, id: &str) -> Pointer {
        match dispatch_work!(self, find, id) {
            Pointer::Some => Pointer::Work(self),
            _ => Pointer::None,
        }
    }
}

// Implementations for `CreativeWork` structs. For descendants of these
// works to be pointable they must be within one of the listed properties e.g. `Article.content`.

pointable_struct!(Article, content);
pointable_struct!(AudioObject);
pointable_struct!(Claim, content);
pointable_struct!(Collection, parts);
pointable_struct!(Comment);
pointable_struct!(CreativeWork);
pointable_struct!(Datatable);
pointable_struct!(Figure);
pointable_struct!(ImageObject);
pointable_struct!(MediaObject);
pointable_struct!(Periodical);
pointable_struct!(PublicationIssue);
pointable_struct!(PublicationVolume);
pointable_struct!(Review);
pointable_struct!(SoftwareApplication);
pointable_struct!(SoftwareSourceCode);
pointable_struct!(Table, caption, rows);
pointable_struct!(VideoObject);
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Serialize structure into specific format.
//! Currently support only json.
//! This module is a pack of superstructures over serde `Serializer's`\\`Deserializer's`

use encoding::Field;
use messages::MessageWriter;
use super::Offset;

pub use hex::{FromHexError, ToHex, FromHex, encode as encode_hex, decode as decode_hex};

/// implement exonum serialization\deserialization based on serde `Serialize`\ `Deserialize`
///
/// Item should implement:
///
/// - `serde::Serialize`
/// - `serde::Deserialize`
/// - `exonum::encoding::Field`
///
/// **Beware, this macros probably implement traits in not optimal way.**
#[macro_export]
macro_rules! implement_exonum_serializer {
    ($name:ident) => {
        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            fn deserialize(value: &$crate::encoding::serialize::json::reexport::Value)
                                                        -> Result<$name, Box<::std::error::Error>> {
                use $crate::encoding::serialize::json::reexport::from_value;
                Ok(from_value(value.clone())?)
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B>(
                value: &$crate::encoding::serialize::json::reexport::Value,
                                                        buffer: &mut B,
                                                        from: $crate::encoding::Offset,
                                                        to: $crate::encoding::Offset)
                                                        -> Result<(), Box<::std::error::Error>>
            where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::reexport::from_value;
                let value: $name = from_value(value.clone())?;
                buffer.write(from, to, value);
                Ok(())
            }

            fn serialize_field(&self) ->
                Result<$crate::encoding::serialize::json::reexport::Value,
                        Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::reexport::to_value;
                Ok(to_value(self)?)
            }
        }

    };
}

/// implement serializing wrappers and methods for json
#[macro_use]
pub mod json;

/// `WriteBufferWrapper` is a trait specific for writing fields in place.
#[doc(hidden)]
pub trait WriteBufferWrapper {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T);
}

impl WriteBufferWrapper for MessageWriter {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T) {
        self.write(val, from, to)
    }
}

impl WriteBufferWrapper for Vec<u8> {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T) {
        val.write(self, from, to)
    }
}

/// Reexport of `serde` specific traits, this reexports
/// provide compatibility layer with important `serde` version.
pub mod reexport {
    pub use serde::{Serializer, Deserializer, Serialize, Deserialize};
    pub use serde::de::Error as DeError;
    pub use serde::ser::Error as SerError;
    pub use serde::ser::SerializeStruct;
}
<commit_msg>Fix implement_exonum_serializer! to match ExonumJson<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Serialize structure into specific format.
//! Currently support only json.
//! This module is a pack of superstructures over serde `Serializer's`\\`Deserializer's`

use encoding::Field;
use messages::MessageWriter;
use super::Offset;

pub use hex::{FromHexError, ToHex, FromHex, encode as encode_hex, decode as decode_hex};

/// implement exonum serialization\deserialization based on serde `Serialize`\ `Deserialize`
///
/// Item should implement:
///
/// - `serde::Serialize`
/// - `serde::Deserialize`
/// - `exonum::encoding::Field`
///
/// **Beware, this macros probably implement traits in not optimal way.**
#[macro_export]
macro_rules! implement_exonum_serializer {
    ($name:ident) => {
        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            fn deserialize(value: &$crate::encoding::serialize::json::reexport::Value)
                                                        -> Result<$name, Box<::std::error::Error>> {
                use $crate::encoding::serialize::json::reexport::from_value;
                Ok(from_value(value.clone())?)
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B>(
                value: &$crate::encoding::serialize::json::reexport::Value,
                                                        buffer: &mut B,
                                                        from: $crate::encoding::Offset,
                                                        to: $crate::encoding::Offset)
                                                        -> Result<(), Box<::std::error::Error>>
            where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::reexport::from_value;
                let value: $name = from_value(value.clone())?;
                buffer.write(from, to, value);
                Ok(())
            }

            fn serialize_field(&self) ->
                Result<$crate::encoding::serialize::json::reexport::Value,
                        Box<::std::error::Error + Send + Sync>>
            {
                use $crate::encoding::serialize::json::reexport::to_value;
                Ok(to_value(self)?)
            }
        }

    };
}

/// implement serializing wrappers and methods for json
#[macro_use]
pub mod json;

/// `WriteBufferWrapper` is a trait specific for writing fields in place.
#[doc(hidden)]
pub trait WriteBufferWrapper {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T);
}

impl WriteBufferWrapper for MessageWriter {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T) {
        self.write(val, from, to)
    }
}

impl WriteBufferWrapper for Vec<u8> {
    fn write<'a, T: Field<'a>>(&'a mut self, from: Offset, to: Offset, val: T) {
        val.write(self, from, to)
    }
}

/// Reexport of `serde` specific traits, this reexports
/// provide compatibility layer with important `serde` version.
pub mod reexport {
    pub use serde::{Serializer, Deserializer, Serialize, Deserialize};
    pub use serde::de::Error as DeError;
    pub use serde::ser::Error as SerError;
    pub use serde::ser::SerializeStruct;
}
<|endoftext|>


<commit_before>use types::*;

use cookie_factory::*;

/* TODO: use AMQP types and call gen_type when something like call!() is available */

pub fn gen_value<'a>(x: (&'a mut [u8], usize), v: &AMQPValue) -> Result<(&'a mut [u8], usize), GenError> {
    match *v {
        AMQPValue::Boolean(ref b)        => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_boolean(b)),
//        AMQPValue::ShortShortInt(ref i)  => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_short_int(i)),
        AMQPValue::ShortShortUInt(ref u) => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_short_uint(u)),
//        AMQPValue::ShortInt(ref i)       => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_int(i)),
        AMQPValue::ShortUInt(ref u)      => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_uint(u)),
//        AMQPValue::LongInt(ref i)        => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_int(i)),
        AMQPValue::LongUInt(ref u)       => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_uint(u)),
//        AMQPValue::LongLongInt(ref i)    => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_long_int(i)),
        AMQPValue::LongLongUInt(ref u)   => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_long_uint(u)),
//        AMQPValue::Float(ref f)          => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_float(f)),
//        AMQPValue::Double(ref d)         => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_double(d)),
        AMQPValue::DecimalValue(ref d)   => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_decimal_value(d)),
        AMQPValue::ShortString(ref s)    => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_string(s)),
        AMQPValue::LongString(ref s)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_string(s)),
        AMQPValue::FieldArray(ref a)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_field_array(a)),
        AMQPValue::Timestamp(ref t)      => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_timestamp(t)),
//        AMQPValue::FieldTable(ref t)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_field_table(t)),
        AMQPValue::Void                  => gen_be_u8!(x, v.get_type().get_id() as u8),
        _                                => Err(GenError::CustomError(42))
    }
}

pub fn gen_type<'a>(x: (&'a mut [u8], usize), t: &AMQPType) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, t.get_id() as u8)
}

pub fn gen_boolean<'a>(x: (&'a mut [u8], usize), b: &Boolean) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, if *b { 1 } else { 0 })
}

/*
pub fn gen_short_short_int<'a>(x: (&'a mut [u8], usize), i: &ShortShortInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i8!(x, *i)
}
*/

pub fn gen_short_short_uint<'a>(x: (&'a mut [u8], usize), u: &ShortShortUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, *u)
}

/*
pub fn gen_short_int<'a>(x: (&'a mut [u8], usize), i: &ShortInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i16!(x, *i)
}
*/

pub fn gen_short_uint<'a>(x: (&'a mut [u8], usize), u: &ShortUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u16!(x, *u)
}

/*
pub fn gen_long_int<'a>(x: (&'a mut [u8], usize), i: &LongInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i32!(x, *i)
}
*/

pub fn gen_long_uint<'a>(x: (&'a mut [u8], usize), u: &LongUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u32!(x, *u)
}

/*
pub fn gen_long_long_int<'a>(x: (&'a mut [u8], usize), i: &LongLongInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i64!(x, *i)
}
*/

pub fn gen_long_long_uint<'a>(x: (&'a mut [u8], usize), u: &LongLongUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u64!(x, *u)
}

/* TODO: Float, Double */

pub fn gen_decimal_value<'a>(x: (&'a mut [u8], usize), d: &DecimalValue) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u8!(d.scale) >> gen_be_u32!(d.value))
}

pub fn gen_short_string<'a>(x: (&'a mut [u8], usize), s: &ShortString) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u8!(s.len() as u8) >> gen_slice!(s.as_bytes()))
}

pub fn gen_long_string<'a>(x: (&'a mut [u8], usize), s: &LongString) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u32!(s.len() as u32) >> gen_slice!(s.as_bytes()))
}

pub fn gen_field_array<'a>(x: (&'a mut [u8], usize), a: &FieldArray) -> Result<(&'a mut [u8], usize), GenError> {
    let (x1, index1) = x;
    gen_many_ref!((x1, index1 + 4), a, gen_value).and_then(|(x2, index2)| {
        gen_be_u32!((x2, index1), index2 - index1 - 4).and_then(|(x3, _)| Ok((x3, index2)))
    })
}

pub fn gen_timestamp<'a>(x: (&'a mut [u8], usize), t: &Timestamp) -> Result<(&'a mut [u8], usize), GenError> {
    gen_long_long_uint(x, t)
}

/* TODO: FieldTable */
<commit_msg>types: generate FieldTable<commit_after>use types::*;

use cookie_factory::*;

/* TODO: use AMQP types and call gen_type when something like call!() is available */

pub fn gen_value<'a>(x: (&'a mut [u8], usize), v: &AMQPValue) -> Result<(&'a mut [u8], usize), GenError> {
    match *v {
        AMQPValue::Boolean(ref b)        => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_boolean(b)),
//        AMQPValue::ShortShortInt(ref i)  => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_short_int(i)),
        AMQPValue::ShortShortUInt(ref u) => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_short_uint(u)),
//        AMQPValue::ShortInt(ref i)       => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_int(i)),
        AMQPValue::ShortUInt(ref u)      => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_uint(u)),
//        AMQPValue::LongInt(ref i)        => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_int(i)),
        AMQPValue::LongUInt(ref u)       => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_uint(u)),
//        AMQPValue::LongLongInt(ref i)    => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_long_int(i)),
        AMQPValue::LongLongUInt(ref u)   => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_long_uint(u)),
//        AMQPValue::Float(ref f)          => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_float(f)),
//        AMQPValue::Double(ref d)         => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_double(d)),
        AMQPValue::DecimalValue(ref d)   => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_decimal_value(d)),
        AMQPValue::ShortString(ref s)    => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_short_string(s)),
        AMQPValue::LongString(ref s)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_long_string(s)),
        AMQPValue::FieldArray(ref a)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_field_array(a)),
        AMQPValue::Timestamp(ref t)      => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_timestamp(t)),
        AMQPValue::FieldTable(ref t)     => do_gen!(x, gen_be_u8!(v.get_type().get_id() as u8) >> gen_field_table(t)),
        AMQPValue::Void                  => gen_be_u8!(x, v.get_type().get_id() as u8),
        _                                => Err(GenError::CustomError(42))
    }
}

pub fn gen_type<'a>(x: (&'a mut [u8], usize), t: &AMQPType) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, t.get_id() as u8)
}

pub fn gen_boolean<'a>(x: (&'a mut [u8], usize), b: &Boolean) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, if *b { 1 } else { 0 })
}

/*
pub fn gen_short_short_int<'a>(x: (&'a mut [u8], usize), i: &ShortShortInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i8!(x, *i)
}
*/

pub fn gen_short_short_uint<'a>(x: (&'a mut [u8], usize), u: &ShortShortUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u8!(x, *u)
}

/*
pub fn gen_short_int<'a>(x: (&'a mut [u8], usize), i: &ShortInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i16!(x, *i)
}
*/

pub fn gen_short_uint<'a>(x: (&'a mut [u8], usize), u: &ShortUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u16!(x, *u)
}

/*
pub fn gen_long_int<'a>(x: (&'a mut [u8], usize), i: &LongInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i32!(x, *i)
}
*/

pub fn gen_long_uint<'a>(x: (&'a mut [u8], usize), u: &LongUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u32!(x, *u)
}

/*
pub fn gen_long_long_int<'a>(x: (&'a mut [u8], usize), i: &LongLongInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_i64!(x, *i)
}
*/

pub fn gen_long_long_uint<'a>(x: (&'a mut [u8], usize), u: &LongLongUInt) -> Result<(&'a mut [u8], usize), GenError> {
    gen_be_u64!(x, *u)
}

/* TODO: Float, Double */

pub fn gen_decimal_value<'a>(x: (&'a mut [u8], usize), d: &DecimalValue) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u8!(d.scale) >> gen_be_u32!(d.value))
}

pub fn gen_short_string<'a>(x: (&'a mut [u8], usize), s: &ShortString) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u8!(s.len() as u8) >> gen_slice!(s.as_bytes()))
}

pub fn gen_long_string<'a>(x: (&'a mut [u8], usize), s: &LongString) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_be_u32!(s.len() as u32) >> gen_slice!(s.as_bytes()))
}

pub fn gen_field_array<'a>(x: (&'a mut [u8], usize), a: &FieldArray) -> Result<(&'a mut [u8], usize), GenError> {
    let (x1, index1) = x;
    gen_many_ref!((x1, index1 + 4), a, gen_value).and_then(|(x2, index2)| {
        gen_be_u32!((x2, index1), index2 - index1 - 4).and_then(|(x3, _)| Ok((x3, index2)))
    })
}

pub fn gen_timestamp<'a>(x: (&'a mut [u8], usize), t: &Timestamp) -> Result<(&'a mut [u8], usize), GenError> {
    gen_long_long_uint(x, t)
}

pub fn gen_field_table<'a>(x: (&'a mut [u8], usize), t: &FieldTable) -> Result<(&'a mut [u8], usize), GenError> {
    let (x1, index1) = x;
    gen_many_ref!((x1, index1 + 4), t, gen_field_entry).and_then(|(x2, index2)| {
        gen_be_u32!((x2, index1), index2 - index1 - 4).and_then(|(x3, _)| Ok((x3, index2)))
    })
}

pub fn gen_field_entry<'a>(x: (&'a mut [u8], usize), e: &(&ShortString, &AMQPValue)) -> Result<(&'a mut [u8], usize), GenError> {
    do_gen!(x, gen_short_string(e.0) >> gen_value(e.1))
}
<|endoftext|>


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

use freetype::freetype::FT_Add_Default_Modules;
use freetype::freetype::FT_Done_Library;
use freetype::freetype::FT_Library;
use freetype::freetype::FT_Memory;
use freetype::freetype::FT_MemoryRec_;
use freetype::freetype::FT_New_Library;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_allocator::usable_size;
use std::mem;
use std::os::raw::{c_long, c_void};
use std::ptr;
use std::rc::Rc;

// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
// record the memory usage of each FreeType instance.
pub struct User {
    size: usize,
}

// FreeType doesn't require any particular alignment for allocations.
const FT_ALIGNMENT: usize = 1;

extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
    assert!(FT_ALIGNMENT == 1);
    let mut vec = Vec::<u8>::with_capacity(req_size as usize);
    let ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += actual_size;
    }

    ptr
}

extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size -= actual_size;

        assert!(FT_ALIGNMENT == 1);
        mem::drop(Vec::<u8>::from_raw_parts(ptr as *mut u8, actual_size, 0))
    }
}

extern fn ft_realloc(mem: FT_Memory, old_size: c_long, new_req_size: c_long,
                     old_ptr: *mut c_void) -> *mut c_void {
    let old_actual_size;
    let mut vec;
    unsafe {
        old_actual_size = usable_size(old_ptr as *const _);
        let old_size = old_size as usize;
        vec = Vec::<u8>::from_raw_parts(old_ptr as *mut u8, old_size, old_size);
    };

    let new_req_size = new_req_size as usize;
    if new_req_size > old_actual_size {
        vec.reserve_exact(new_req_size - old_actual_size)
    } else if new_req_size < old_actual_size {
        vec.truncate(new_req_size);
        vec.shrink_to_fit()
    }

    let new_ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let new_actual_size = usable_size(new_ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += new_actual_size;
        (*user).size -= old_actual_size;
    }

    new_ptr
}

// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
// rustc. But using a typedef avoids this, so...
pub type UserPtr = *mut User;

// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
// FontContextHandle.
#[derive(Clone, Debug)]
pub struct FreeTypeLibraryHandle {
    pub ctx: FT_Library,
    mem: FT_Memory,
    user: UserPtr,
}

impl Drop for FreeTypeLibraryHandle {
    fn drop(&mut self) {
        assert!(!self.ctx.is_null());
        unsafe {
            FT_Done_Library(self.ctx);
            Box::from_raw(self.mem);
            Box::from_raw(self.user);
        }
    }
}

impl MallocSizeOf for FreeTypeLibraryHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        unsafe {
            (*self.user).size +
                ops.malloc_size_of(self.ctx as *const _) +
                ops.malloc_size_of(self.mem as *const _) +
                ops.malloc_size_of(self.user as *const _)
        }
    }
}

#[derive(Clone, Debug)]
pub struct FontContextHandle {
    // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
    // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
    // once, otherwise we'll get crashes. Yuk.
    pub ctx: Rc<FreeTypeLibraryHandle>,
}

impl MallocSizeOf for FontContextHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        self.ctx.size_of(ops)
    }
}

impl FontContextHandle {
    pub fn new() -> FontContextHandle {
        let user = Box::into_raw(Box::new(User {
            size: 0,
        }));
        let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
            user: user as *mut c_void,
            alloc: Some(ft_alloc),
            free: Some(ft_free),
            realloc: Some(ft_realloc),
        }));
        unsafe {
            let mut ctx: FT_Library = ptr::null_mut();

            let result = FT_New_Library(mem, &mut ctx);
            if !result.succeeded() { panic!("Unable to initialize FreeType library"); }

            FT_Add_Default_Modules(ctx);

            FontContextHandle {
                ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
            }
        }
    }
}
<commit_msg>Use actual size for old allocation in ft_realloc.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use freetype::freetype::FT_Add_Default_Modules;
use freetype::freetype::FT_Done_Library;
use freetype::freetype::FT_Library;
use freetype::freetype::FT_Memory;
use freetype::freetype::FT_MemoryRec_;
use freetype::freetype::FT_New_Library;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_allocator::usable_size;
use std::mem;
use std::os::raw::{c_long, c_void};
use std::ptr;
use std::rc::Rc;

// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
// record the memory usage of each FreeType instance.
pub struct User {
    size: usize,
}

// FreeType doesn't require any particular alignment for allocations.
const FT_ALIGNMENT: usize = 1;

extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
    assert!(FT_ALIGNMENT == 1);
    let mut vec = Vec::<u8>::with_capacity(req_size as usize);
    let ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += actual_size;
    }

    ptr
}

extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size -= actual_size;

        assert!(FT_ALIGNMENT == 1);
        mem::drop(Vec::<u8>::from_raw_parts(ptr as *mut u8, actual_size, 0))
    }
}

extern fn ft_realloc(mem: FT_Memory, _old_size: c_long, new_req_size: c_long,
                     old_ptr: *mut c_void) -> *mut c_void {
    let old_actual_size;
    let mut vec;
    unsafe {
        old_actual_size = usable_size(old_ptr as *const _);
        let old_size = old_actual_size as usize;
        vec = Vec::<u8>::from_raw_parts(old_ptr as *mut u8, old_size, old_size);
    };

    let new_req_size = new_req_size as usize;
    if new_req_size > old_actual_size {
        vec.reserve_exact(new_req_size - old_actual_size)
    } else if new_req_size < old_actual_size {
        vec.truncate(new_req_size);
        vec.shrink_to_fit()
    }

    let new_ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let new_actual_size = usable_size(new_ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += new_actual_size;
        (*user).size -= old_actual_size;
    }

    new_ptr
}

// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
// rustc. But using a typedef avoids this, so...
pub type UserPtr = *mut User;

// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
// FontContextHandle.
#[derive(Clone, Debug)]
pub struct FreeTypeLibraryHandle {
    pub ctx: FT_Library,
    mem: FT_Memory,
    user: UserPtr,
}

impl Drop for FreeTypeLibraryHandle {
    fn drop(&mut self) {
        assert!(!self.ctx.is_null());
        unsafe {
            FT_Done_Library(self.ctx);
            Box::from_raw(self.mem);
            Box::from_raw(self.user);
        }
    }
}

impl MallocSizeOf for FreeTypeLibraryHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        unsafe {
            (*self.user).size +
                ops.malloc_size_of(self.ctx as *const _) +
                ops.malloc_size_of(self.mem as *const _) +
                ops.malloc_size_of(self.user as *const _)
        }
    }
}

#[derive(Clone, Debug)]
pub struct FontContextHandle {
    // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
    // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
    // once, otherwise we'll get crashes. Yuk.
    pub ctx: Rc<FreeTypeLibraryHandle>,
}

impl MallocSizeOf for FontContextHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        self.ctx.size_of(ops)
    }
}

impl FontContextHandle {
    pub fn new() -> FontContextHandle {
        let user = Box::into_raw(Box::new(User {
            size: 0,
        }));
        let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
            user: user as *mut c_void,
            alloc: Some(ft_alloc),
            free: Some(ft_free),
            realloc: Some(ft_realloc),
        }));
        unsafe {
            let mut ctx: FT_Library = ptr::null_mut();

            let result = FT_New_Library(mem, &mut ctx);
            if !result.succeeded() { panic!("Unable to initialize FreeType library"); }

            FT_Add_Default_Modules(ctx);

            FontContextHandle {
                ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Simple basic model of the C-AST
//!
//! This is the skeleton of the final decompiled output. However, further stages maybe added to
//! make the decompiled output easier to read and add more sugaring.

use petgraph::graph::{Graph, NodeIndex};
use std::default;

pub type Ty = String;

#[derive(Clone, Debug)]
enum CASTNode {
    FunctionHeader,
    Conditional,
    Declaration(Ty),
    Loop,
    Goto(String),
    Label(String),
    Break,
    ExpressionNode(Expr),
    Var(String),
}

#[derive(Clone, Debug)]
pub enum Expr {
    Eq,
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Shr,
    Shl,
}

#[derive(Clone, Debug)]
enum ASTEdge {
    StatementOrd(u64),
    OpOrd(u8),
}

#[derive(Clone, Debug)]
pub struct CAST {
    ast: Graph<CASTNode, ASTEdge>,
    eidx: u64,
}

impl default::Default for CAST {
    fn default() -> CAST {
        let mut ast = CAST {
            ast: Graph::new(),
            eidx: 0,
        };
        ast.ast.add_node(CASTNode::FunctionHeader);
        ast
    }
}

lazy_static! {
    static ref FN_HEAD: NodeIndex = NodeIndex::new(0);
}

impl CAST {
    fn next_edge_idx(&mut self) -> u64 {
        self.eidx += 1;
        self.eidx - 1
    }

    fn replace_incoming_edges(node: NodeIndex, by: NodeIndex) {
        unimplemented!()
    }

    pub fn expr(&mut self, operator: Expr, operands: &[NodeIndex]) -> NodeIndex {
        let operator = self.ast.add_node(CASTNode::ExpressionNode(operator));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, operator, ASTEdge::StatementOrd(idx));
        for (i, n) in operands.iter().enumerate() {
            self.ast.add_edge(operator, *n, ASTEdge::OpOrd(i as u8));
        }
        operator
    }

    pub fn new_loop(&mut self, loop_header: NodeIndex, loop_body: NodeIndex) -> NodeIndex {
        let e1 = self.ast.find_edge(*FN_HEAD, loop_header).expect("This cannot be `None`");
        let e2 = self.ast.find_edge(*FN_HEAD, loop_body).expect("This cannot be `None`");
        let loop_h = self.ast.add_node(CASTNode::Loop);
        let idx = if let ASTEdge::StatementOrd(idx) = self.ast[e1] {
            idx
        } else {
            panic!()
        };
        self.ast.remove_edge(e2);
        self.ast.remove_edge(e1);
        self.ast.add_edge(*FN_HEAD, loop_h, ASTEdge::StatementOrd(idx));
        self.ast.add_edge(loop_h, loop_header, ASTEdge::OpOrd(0));
        self.ast.add_edge(loop_h, loop_body, ASTEdge::OpOrd(1));
        loop_h
    }

    pub fn new_conditional(&mut self, condition: NodeIndex, body: NodeIndex, else_condition: Option<NodeIndex>) -> NodeIndex {
        let e1 = self.ast.find_edge(*FN_HEAD, condition).expect("This cannot be `None`");
        let e2 = self.ast.find_edge(*FN_HEAD, body).expect("This cannot be `None`");
        let e3 = if let Some(else_c) = else_condition {
            self.ast.find_edge(*FN_HEAD, else_c)
        } else {
            None
        };
        let idx = if let ASTEdge::StatementOrd(idx) = self.ast[e1] {
            idx
        } else {
            panic!()
        };

        let conditional = self.ast.add_node(CASTNode::Conditional);
        self.ast.remove_edge(e1);
        self.ast.remove_edge(e2);
        if let Some(e3) = e3 {
            self.ast.remove_edge(e3);
        }

        self.ast.add_edge(*FN_HEAD, conditional, ASTEdge::StatementOrd(idx));
        self.ast.add_edge(conditional, condition, ASTEdge::OpOrd(0));
        self.ast.add_edge(conditional, body, ASTEdge::OpOrd(1));
        if let Some(else_condition) = else_condition {
            self.ast.add_edge(conditional, else_condition, ASTEdge::OpOrd(2));
        }
        conditional
    }

    pub fn goto(&mut self, label: String) {
        let goto_n = self.ast.add_node(CASTNode::Goto(label));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, goto_n, ASTEdge::StatementOrd(idx));
    }

    pub fn label(label: String) {
        let label = self.ast.add_node(CASTNode::Label(label));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, label, ASTEdge::StatementOrd(idx));
    }

    pub fn insert_break(after: NodeIndex) {
        let break_n = self.ast.add_node(CASTNode::Label(label));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, break_n, ASTEdge::StatementOrd(idx));
    }

    pub fn print() -> String {
        unimplemented!()
    }
}

#[cfg(test)]
mod test {

    #[test]
    fn c_ast_basic_test() {
        unimplemented!()
    }
}
<commit_msg>Starts implementation of priting C-AST<commit_after>//! Simple basic model of the C-AST
//!
//! This is the skeleton of the final decompiled output. However, further
//! stages maybe added to
//! make the decompiled output easier to read and add more sugaring.

use petgraph::graph::{Graph, NodeIndex};
use petgraph::EdgeDirection;
use std::default;
use std::iter;

pub type Ty = String;

#[derive(Clone, Debug)]
enum CASTNode {
    FunctionHeader,
    Conditional,
    Declaration(Ty),
    Loop,
    Goto(String),
    Label(String),
    Break,
    ExpressionNode(Expr),
    Var(String),
}

#[derive(Clone, Debug)]
pub enum Expr {
    Eq,
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Shr,
    Shl,
}

#[derive(Clone, Debug)]
enum ASTEdge {
    StatementOrd(u64),
    OpOrd(u8),
}

#[derive(Clone, Debug)]
pub struct CAST {
    ast: Graph<CASTNode, ASTEdge>,
    eidx: u64,
}

impl default::Default for CAST {
    fn default() -> CAST {
        let mut ast = CAST {
            ast: Graph::new(),
            eidx: 0,
        };
        ast.ast.add_node(CASTNode::FunctionHeader);
        ast
    }
}

lazy_static! {
    static ref FN_HEAD: NodeIndex = NodeIndex::new(0);
}

fn format_with_indent(string: &str, depth: usize) -> String {
    iter::repeat(' ').take(depth).collect::<String>() + string
}

impl CAST {
    fn next_edge_idx(&mut self) -> u64 {
        self.eidx += 1;
        self.eidx - 1
    }

    pub fn expr(&mut self, operator: Expr, operands: &[NodeIndex]) -> NodeIndex {
        let operator = self.ast.add_node(CASTNode::ExpressionNode(operator));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, operator, ASTEdge::StatementOrd(idx));
        for (i, n) in operands.iter().enumerate() {
            self.ast.add_edge(operator, *n, ASTEdge::OpOrd(i as u8));
        }
        operator
    }

    pub fn new_loop(&mut self, loop_header: NodeIndex, loop_body: NodeIndex) -> NodeIndex {
        let e1 = self.ast.find_edge(*FN_HEAD, loop_header).expect("This cannot be `None`");
        let e2 = self.ast.find_edge(*FN_HEAD, loop_body).expect("This cannot be `None`");
        let loop_h = self.ast.add_node(CASTNode::Loop);
        let idx = if let ASTEdge::StatementOrd(idx) = self.ast[e1] {
            idx
        } else {
            panic!()
        };
        self.ast.remove_edge(e2);
        self.ast.remove_edge(e1);
        self.ast.add_edge(*FN_HEAD, loop_h, ASTEdge::StatementOrd(idx));
        self.ast.add_edge(loop_h, loop_header, ASTEdge::OpOrd(0));
        self.ast.add_edge(loop_h, loop_body, ASTEdge::OpOrd(1));
        loop_h
    }

    pub fn new_conditional(&mut self,
                           condition: NodeIndex,
                           body: NodeIndex,
                           else_condition: Option<NodeIndex>)
                           -> NodeIndex {
        let e1 = self.ast.find_edge(*FN_HEAD, condition).expect("This cannot be `None`");
        let e2 = self.ast.find_edge(*FN_HEAD, body).expect("This cannot be `None`");
        let e3 = if let Some(else_c) = else_condition {
            self.ast.find_edge(*FN_HEAD, else_c)
        } else {
            None
        };
        let idx = if let ASTEdge::StatementOrd(idx) = self.ast[e1] {
            idx
        } else {
            panic!()
        };

        let conditional = self.ast.add_node(CASTNode::Conditional);
        self.ast.remove_edge(e1);
        self.ast.remove_edge(e2);
        if let Some(e3) = e3 {
            self.ast.remove_edge(e3);
        }

        self.ast.add_edge(*FN_HEAD, conditional, ASTEdge::StatementOrd(idx));
        self.ast.add_edge(conditional, condition, ASTEdge::OpOrd(0));
        self.ast.add_edge(conditional, body, ASTEdge::OpOrd(1));
        if let Some(else_condition) = else_condition {
            self.ast.add_edge(conditional, else_condition, ASTEdge::OpOrd(2));
        }
        conditional
    }

    pub fn goto(&mut self, label: String) {
        let goto_n = self.ast.add_node(CASTNode::Goto(label));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, goto_n, ASTEdge::StatementOrd(idx));
    }

    pub fn label(&mut self, label: String) {
        let label = self.ast.add_node(CASTNode::Label(label));
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, label, ASTEdge::StatementOrd(idx));
    }

    pub fn insert_break(&mut self, after: NodeIndex) {
        let break_n = self.ast.add_node(CASTNode::Break);
        let idx = self.next_edge_idx();
        self.ast.add_edge(*FN_HEAD, break_n, ASTEdge::StatementOrd(idx));
    }

    fn emit_c(&self, node: &NodeIndex, indent: usize) -> String {
        match self.ast[*node] {
            CASTNode::FunctionHeader => unimplemented!(),
            CASTNode::Conditional => {
                // Get the arguments -> condition, body, else branch.
                let arg1: NodeIndex = panic!();
                let arg2: NodeIndex = panic!();
                let arg3: Option<NodeIndex> = None;
                let condition = format!("{}\n{}",
                                        format_with_indent("if ( {} ) {{", indent),
                                        self.emit_c(&arg1, indent));
                let true_body = self.emit_c(&arg2, indent + 1);
                let false_body = if let Some(arg3) = arg3 {
                    let fbody = self.emit_c(&arg3, indent + 1);
                    if let CASTNode::Conditional = self.ast[arg3] {
                        // Else-If case
                        format_with_indent("}} else ", indent) + &fbody
                    } else {
                        // Plain Else case.
                        format_with_indent("}} else {{", indent) + &fbody
                    }
                } else {
                    "".to_owned()
                };

                format!("{}\n{}\n{}\n{}",
                        condition,
                        true_body,
                        false_body,
                        format_with_indent("}", indent))
            }
            CASTNode::Declaration(ref ty) => {
                unimplemented!()
            }
            CASTNode::Loop => {
                unimplemented!()
            }
            CASTNode::Goto(ref label) => {
                unimplemented!()
            }
            CASTNode::Label(ref label) => {
                unimplemented!()
            }
            CASTNode::Break => {
                unimplemented!()
            }
            CASTNode::ExpressionNode(ref expr) => {
                unimplemented!()
            }
            CASTNode::Var(ref ident) => {
                unimplemented!()
            }
        }
    }

    pub fn print(&self) -> String {
        // Get all the edges from the function header.
        // Take them in order
        // Traverse the subtree and print out accordingly.
        let mut result = String::new();
        let mut edges = self.ast
                            .edges_directed(*FN_HEAD, EdgeDirection::Outgoing)
                            .collect::<Vec<_>>();
        edges.sort_by(|a, b| {
            let idx1 = if let ASTEdge::StatementOrd(idx) = *a.1 {
                idx
            } else {
                u64::max_value()
            };

            let idx2 = if let ASTEdge::StatementOrd(idx) = *b.1 {
                idx
            } else {
                u64::max_value()
            };

            idx1.cmp(&idx2)
        });

        for &(ref node, _) in &edges {
            result.push_str(&self.emit_c(node, 0));
        }

        result
    }
}

#[cfg(test)]
mod test {

    #[test]
    fn c_ast_basic_test() {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>//! Completes keywords.

use syntax::{SyntaxKind, T};

use crate::{
    context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
    CompletionItemKind, CompletionKind, Completions,
};

pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if ctx.token.kind() == SyntaxKind::COMMENT {
        cov_mark::hit!(no_keyword_completion_in_comments);
        return;
    }
    if matches!(ctx.completion_location, Some(ImmediateLocation::RecordExpr(_))) {
        cov_mark::hit!(no_keyword_completion_in_record_lit);
        return;
    }
    if ctx.attribute_under_caret.is_some() {
        cov_mark::hit!(no_keyword_completion_in_attr_of_expr);
        return;
    }

    // Suggest .await syntax for types that implement Future trait
    if let Some(receiver) = ctx.dot_receiver() {
        if let Some(ty) = ctx.sema.type_of_expr(receiver) {
            if ty.impls_future(ctx.db) {
                let mut item =
                    CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
                item.kind(CompletionItemKind::Keyword).detail("expr.await");
                item.add_to(acc);
            }
        };
    }

    let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);

    let expects_assoc_item = ctx.expects_assoc_item();
    let has_block_expr_parent = ctx.has_block_expr_parent();
    let expects_item = ctx.expects_item();

    if ctx.has_impl_or_trait_prev_sibling() {
        add_keyword("where", "where ");
        if ctx.has_impl_prev_sibling() {
            add_keyword("for", "for ");
        }
        return;
    }
    if ctx.previous_token_is(T![unsafe]) {
        if expects_item || expects_assoc_item || has_block_expr_parent {
            add_keyword("fn", "fn $1($2) {\n    $0\n}")
        }

        if expects_item || has_block_expr_parent {
            add_keyword("trait", "trait $1 {\n    $0\n}");
            add_keyword("impl", "impl $1 {\n    $0\n}");
        }

        return;
    }

    if !ctx.has_visibility_prev_sibling()
        && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
    {
        add_keyword("pub(crate)", "pub(crate) ");
        add_keyword("pub", "pub ");
    }

    if expects_item || expects_assoc_item || has_block_expr_parent {
        add_keyword("unsafe", "unsafe ");
        add_keyword("fn", "fn $1($2) {\n    $0\n}");
        add_keyword("const", "const $0");
        add_keyword("type", "type $0");
    }

    if expects_item || has_block_expr_parent {
        if !ctx.has_visibility_prev_sibling() {
            add_keyword("impl", "impl $1 {\n    $0\n}");
            add_keyword("extern", "extern $0");
        }
        add_keyword("use", "use $0");
        add_keyword("trait", "trait $1 {\n    $0\n}");
        add_keyword("static", "static $0");
        add_keyword("mod", "mod $0");
    }

    if expects_item {
        add_keyword("enum", "enum $1 {\n    $0\n}");
        add_keyword("struct", "struct $0");
        add_keyword("union", "union $1 {\n    $0\n}");
    }

    if ctx.expects_type() {
        return;
    }

    if ctx.expects_expression() {
        if !has_block_expr_parent {
            add_keyword("unsafe", "unsafe {\n    $0\n}");
        }
        add_keyword("match", "match $1 {\n    $0\n}");
        add_keyword("while", "while $1 {\n    $0\n}");
        add_keyword("while let", "while let $1 = $2 {\n    $0\n}");
        add_keyword("loop", "loop {\n    $0\n}");
        add_keyword("if", "if $1 {\n    $0\n}");
        add_keyword("if let", "if let $1 = $2 {\n    $0\n}");
        add_keyword("for", "for $1 in $2 {\n    $0\n}");
    }

    if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
        add_keyword("let", "let ");
    }

    if ctx.after_if() {
        add_keyword("else", "else {\n    $0\n}");
        add_keyword("else if", "else if $1 {\n    $0\n}");
    }

    if ctx.expects_ident_pat_or_ref_expr() {
        add_keyword("mut", "mut ");
    }

    let (can_be_stmt, in_loop_body) = match ctx.path_context {
        Some(PathCompletionContext {
            is_trivial_path: true, can_be_stmt, in_loop_body, ..
        }) => (can_be_stmt, in_loop_body),
        _ => return,
    };

    if in_loop_body {
        if can_be_stmt {
            add_keyword("continue", "continue;");
            add_keyword("break", "break;");
        } else {
            add_keyword("continue", "continue");
            add_keyword("break", "break");
        }
    }

    let fn_def = match &ctx.function_def {
        Some(it) => it,
        None => return,
    };

    add_keyword(
        "return",
        match (can_be_stmt, fn_def.ret_type().is_some()) {
            (true, true) => "return $0;",
            (true, false) => "return;",
            (false, true) => "return $0",
            (false, false) => "return",
        },
    )
}

fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
    let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw);
    item.kind(CompletionItemKind::Keyword);

    match ctx.config.snippet_cap {
        Some(cap) => {
            if snippet.ends_with('}') && ctx.incomplete_let {
                cov_mark::hit!(let_semi);
                item.insert_snippet(cap, format!("{};", snippet));
            } else {
                item.insert_snippet(cap, snippet);
            }
        }
        None => {
            item.insert_text(if snippet.contains('$') { kw } else { snippet });
        }
    };
    item.add_to(acc);
}

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

    use crate::{
        tests::{check_edit, filtered_completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword);
        expect.assert_eq(&actual)
    }

    #[test]
    fn test_keywords_in_function() {
        check(
            r"fn quux() { $0 }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_inside_block() {
        check(
            r"fn quux() { if true { $0 } }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_if() {
        check(
            r#"fn quux() { if true { () } $0 }"#,
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw else
                kw else if
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
        check_edit(
            "else",
            r#"fn quux() { if true { () } $0 }"#,
            r#"fn quux() { if true { () } else {
    $0
} }"#,
        );
    }

    #[test]
    fn test_keywords_in_match_arm() {
        check(
            r#"
fn quux() -> i32 {
    match () { () => $0 }
}
"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_loop() {
        check(
            r"fn my() { loop { $0 } }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw continue
                kw break
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_block_expr() {
        check(
            r"fn my_fn() { unsafe $0 }",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn no_keyword_completion_in_comments() {
        cov_mark::check!(no_keyword_completion_in_comments);
        check(
            r#"
fn test() {
    let x = 2; // A comment$0
}
"#,
            expect![[""]],
        );
        check(
            r#"
/*
Some multi-line comment$0
*/
"#,
            expect![[""]],
        );
        check(
            r#"
/// Some doc comment
/// let test$0 = 1
"#,
            expect![[""]],
        );
    }

    #[test]
    fn test_completion_await_impls_future() {
        check(
            r#"
//- minicore: future
use core::future::*;
struct A {}
impl Future for A {}
fn foo(a: A) { a.$0 }
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        );

        check(
            r#"
//- minicore: future
use std::future::*;
fn foo() {
    let a = async {};
    a.$0
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        )
    }

    #[test]
    fn after_let() {
        check(
            r#"fn main() { let _ = $0 }"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        )
    }

    #[test]
    fn skip_struct_initializer() {
        cov_mark::check!(no_keyword_completion_in_record_lit);
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        $0
    }
}
"#,
            expect![[r#""#]],
        );
    }

    #[test]
    fn struct_initializer_field_expr() {
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        f: $0
    }
}
"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn let_semi() {
        cov_mark::check!(let_semi);
        check_edit(
            "match",
            r#"
fn main() { let x = $0 }
"#,
            r#"
fn main() { let x = match $1 {
    $0
}; }
"#,
        );

        check_edit(
            "if",
            r#"
fn main() {
    let x = $0
    let y = 92;
}
"#,
            r#"
fn main() {
    let x = if $1 {
    $0
};
    let y = 92;
}
"#,
        );

        check_edit(
            "loop",
            r#"
fn main() {
    let x = $0
    bar();
}
"#,
            r#"
fn main() {
    let x = loop {
    $0
};
    bar();
}
"#,
        );
    }
}
<commit_msg>Add true and false as completion suggestions when expecting an expression<commit_after>//! Completes keywords.

use syntax::{SyntaxKind, T};

use crate::{
    context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
    CompletionItemKind, CompletionKind, Completions,
};

pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if ctx.token.kind() == SyntaxKind::COMMENT {
        cov_mark::hit!(no_keyword_completion_in_comments);
        return;
    }
    if matches!(ctx.completion_location, Some(ImmediateLocation::RecordExpr(_))) {
        cov_mark::hit!(no_keyword_completion_in_record_lit);
        return;
    }
    if ctx.attribute_under_caret.is_some() {
        cov_mark::hit!(no_keyword_completion_in_attr_of_expr);
        return;
    }

    // Suggest .await syntax for types that implement Future trait
    if let Some(receiver) = ctx.dot_receiver() {
        if let Some(ty) = ctx.sema.type_of_expr(receiver) {
            if ty.impls_future(ctx.db) {
                let mut item =
                    CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
                item.kind(CompletionItemKind::Keyword).detail("expr.await");
                item.add_to(acc);
            }
        };
    }

    let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);

    let expects_assoc_item = ctx.expects_assoc_item();
    let has_block_expr_parent = ctx.has_block_expr_parent();
    let expects_item = ctx.expects_item();

    if ctx.has_impl_or_trait_prev_sibling() {
        add_keyword("where", "where ");
        if ctx.has_impl_prev_sibling() {
            add_keyword("for", "for ");
        }
        return;
    }
    if ctx.previous_token_is(T![unsafe]) {
        if expects_item || expects_assoc_item || has_block_expr_parent {
            add_keyword("fn", "fn $1($2) {\n    $0\n}")
        }

        if expects_item || has_block_expr_parent {
            add_keyword("trait", "trait $1 {\n    $0\n}");
            add_keyword("impl", "impl $1 {\n    $0\n}");
        }

        return;
    }

    if !ctx.has_visibility_prev_sibling()
        && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
    {
        add_keyword("pub(crate)", "pub(crate) ");
        add_keyword("pub", "pub ");
    }

    if expects_item || expects_assoc_item || has_block_expr_parent {
        add_keyword("unsafe", "unsafe ");
        add_keyword("fn", "fn $1($2) {\n    $0\n}");
        add_keyword("const", "const $0");
        add_keyword("type", "type $0");
    }

    if expects_item || has_block_expr_parent {
        if !ctx.has_visibility_prev_sibling() {
            add_keyword("impl", "impl $1 {\n    $0\n}");
            add_keyword("extern", "extern $0");
        }
        add_keyword("use", "use $0");
        add_keyword("trait", "trait $1 {\n    $0\n}");
        add_keyword("static", "static $0");
        add_keyword("mod", "mod $0");
    }

    if expects_item {
        add_keyword("enum", "enum $1 {\n    $0\n}");
        add_keyword("struct", "struct $0");
        add_keyword("union", "union $1 {\n    $0\n}");
    }

    if ctx.expects_type() {
        return;
    }

    if ctx.expects_expression() {
        if !has_block_expr_parent {
            add_keyword("unsafe", "unsafe {\n    $0\n}");
        }
        add_keyword("match", "match $1 {\n    $0\n}");
        add_keyword("while", "while $1 {\n    $0\n}");
        add_keyword("while let", "while let $1 = $2 {\n    $0\n}");
        add_keyword("loop", "loop {\n    $0\n}");
        add_keyword("if", "if $1 {\n    $0\n}");
        add_keyword("if let", "if let $1 = $2 {\n    $0\n}");
        add_keyword("for", "for $1 in $2 {\n    $0\n}");
        add_keyword("true", "true");
        add_keyword("false", "false");
    }

    if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
        add_keyword("let", "let ");
    }

    if ctx.after_if() {
        add_keyword("else", "else {\n    $0\n}");
        add_keyword("else if", "else if $1 {\n    $0\n}");
    }

    if ctx.expects_ident_pat_or_ref_expr() {
        add_keyword("mut", "mut ");
    }

    let (can_be_stmt, in_loop_body) = match ctx.path_context {
        Some(PathCompletionContext {
            is_trivial_path: true, can_be_stmt, in_loop_body, ..
        }) => (can_be_stmt, in_loop_body),
        _ => return,
    };

    if in_loop_body {
        if can_be_stmt {
            add_keyword("continue", "continue;");
            add_keyword("break", "break;");
        } else {
            add_keyword("continue", "continue");
            add_keyword("break", "break");
        }
    }

    let fn_def = match &ctx.function_def {
        Some(it) => it,
        None => return,
    };

    add_keyword(
        "return",
        match (can_be_stmt, fn_def.ret_type().is_some()) {
            (true, true) => "return $0;",
            (true, false) => "return;",
            (false, true) => "return $0",
            (false, false) => "return",
        },
    )
}

fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
    let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw);
    item.kind(CompletionItemKind::Keyword);

    match ctx.config.snippet_cap {
        Some(cap) => {
            if snippet.ends_with('}') && ctx.incomplete_let {
                cov_mark::hit!(let_semi);
                item.insert_snippet(cap, format!("{};", snippet));
            } else {
                item.insert_snippet(cap, snippet);
            }
        }
        None => {
            item.insert_text(if snippet.contains('$') { kw } else { snippet });
        }
    };
    item.add_to(acc);
}

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

    use crate::{
        tests::{check_edit, filtered_completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword);
        expect.assert_eq(&actual)
    }

    #[test]
    fn test_keywords_in_function() {
        check(
            r"fn quux() { $0 }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_inside_block() {
        check(
            r"fn quux() { if true { $0 } }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_if() {
        check(
            r#"fn quux() { if true { () } $0 }"#,
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw else
                kw else if
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
        check_edit(
            "else",
            r#"fn quux() { if true { () } $0 }"#,
            r#"fn quux() { if true { () } else {
    $0
} }"#,
        );
    }

    #[test]
    fn test_keywords_in_match_arm() {
        check(
            r#"
fn quux() -> i32 {
    match () { () => $0 }
}
"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_loop() {
        check(
            r"fn my() { loop { $0 } }",
            expect![[r#"
                kw unsafe
                kw fn
                kw const
                kw type
                kw impl
                kw extern
                kw use
                kw trait
                kw static
                kw mod
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw continue
                kw break
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_block_expr() {
        check(
            r"fn my_fn() { unsafe $0 }",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn no_keyword_completion_in_comments() {
        cov_mark::check!(no_keyword_completion_in_comments);
        check(
            r#"
fn test() {
    let x = 2; // A comment$0
}
"#,
            expect![[""]],
        );
        check(
            r#"
/*
Some multi-line comment$0
*/
"#,
            expect![[""]],
        );
        check(
            r#"
/// Some doc comment
/// let test$0 = 1
"#,
            expect![[""]],
        );
    }

    #[test]
    fn test_completion_await_impls_future() {
        check(
            r#"
//- minicore: future
use core::future::*;
struct A {}
impl Future for A {}
fn foo(a: A) { a.$0 }
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        );

        check(
            r#"
//- minicore: future
use std::future::*;
fn foo() {
    let a = async {};
    a.$0
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        )
    }

    #[test]
    fn after_let() {
        check(
            r#"fn main() { let _ = $0 }"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        )
    }

    #[test]
    fn skip_struct_initializer() {
        cov_mark::check!(no_keyword_completion_in_record_lit);
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        $0
    }
}
"#,
            expect![[r#""#]],
        );
    }

    #[test]
    fn struct_initializer_field_expr() {
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        f: $0
    }
}
"#,
            expect![[r#"
                kw unsafe
                kw match
                kw while
                kw while let
                kw loop
                kw if
                kw if let
                kw for
                kw return
                kw self
                kw super
                kw crate
            "#]],
        );
    }

    #[test]
    fn let_semi() {
        cov_mark::check!(let_semi);
        check_edit(
            "match",
            r#"
fn main() { let x = $0 }
"#,
            r#"
fn main() { let x = match $1 {
    $0
}; }
"#,
        );

        check_edit(
            "if",
            r#"
fn main() {
    let x = $0
    let y = 92;
}
"#,
            r#"
fn main() {
    let x = if $1 {
    $0
};
    let y = 92;
}
"#,
        );

        check_edit(
            "loop",
            r#"
fn main() {
    let x = $0
    bar();
}
"#,
            r#"
fn main() {
    let x = loop {
    $0
};
    bar();
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>//! Does loop filtering on webp lossy images

use crate::utils::clamp;

#[inline]
fn c(val: i32) -> i32 {
    clamp(val, -128, 127)
}

//unsigned to signed
#[inline]
fn u2s(val: u8) -> i32 {
    i32::from(val) - 128
}

//signed to unsigned
#[inline]
fn s2u(val: i32) -> u8 {
    (c(val) + 128) as u8
}

#[inline]
fn diff(val1: u8, val2: u8) -> u8 {
    if val1 > val2 {
        val1 - val2
    } else {
        val2 - val1
    }
}

//15.2
fn common_adjust(use_outer_taps: bool, pixels: &mut [u8], point: usize, stride: usize) -> i32 {
    let p1 = u2s(pixels[point - 2 * stride]);
    let p0 = u2s(pixels[point - stride]);
    let q0 = u2s(pixels[point]);
    let q1 = u2s(pixels[point + stride]);

    //value for the outer 2 pixels
    let outer = if use_outer_taps {
        c(p1 - q1)
    } else {
        0
    };

    let mut a = c(outer + 3 * (q0 - p0));

    let b = (c(a + 3)) >> 3;

    a = (c(a + 4)) >> 3;

    pixels[point] = s2u(q0 - a);
    pixels[point - stride] = s2u(p0 + b);

    a
}

fn simple_threshold(filter_limit: i32, pixels: &[u8], point: usize, stride: usize) -> bool {
   i32::from(diff(pixels[point - stride], pixels[point])) * 2 +
   i32::from(diff(pixels[point - 2 * stride], pixels[point + stride])) / 2 <= filter_limit
}

fn should_filter(interior_limit: u8, edge_limit: u8, pixels: &[u8], point: usize, stride: usize) -> bool {
    simple_threshold(i32::from(edge_limit), pixels, point, stride) &&
    diff(pixels[point - 4 * stride], pixels[point - 3 * stride]) <= interior_limit &&
    diff(pixels[point - 3 * stride], pixels[point - 2 * stride]) <= interior_limit &&
    diff(pixels[point - 2 * stride], pixels[point - stride]) <= interior_limit &&
    diff(pixels[point + 3 * stride], pixels[point + 2 * stride]) <= interior_limit &&
    diff(pixels[point + 2 * stride], pixels[point + stride]) <= interior_limit &&
    diff(pixels[point + stride], pixels[point]) <= interior_limit
}

fn high_edge_variance(threshold: u8, pixels: &[u8], point: usize, stride: usize) -> bool {
    diff(pixels[point - 2 * stride], pixels[point - stride]) > threshold ||
    diff(pixels[point + stride], pixels[point]) > threshold
}

//simple filter
//effects 4 pixels on an edge(2 each side)
pub(crate) fn simple_segment(edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {
    if simple_threshold(i32::from(edge_limit), pixels, point, stride) {
        common_adjust(true, pixels, point, stride);
    }
}

//normal filter
//works on the 8 pixels on the edges between subblocks inside a macroblock
pub(crate) fn subblock_filter(hev_threshold: u8, interior_limit: u8, edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {
    if should_filter(interior_limit, edge_limit, pixels, point, stride) {
        let hv = high_edge_variance(hev_threshold, pixels, point, stride);

        let a = (common_adjust(hv, pixels, point, stride) + 1) >> 1;

        if !hv {
            pixels[point + stride] = s2u(u2s(pixels[5]) - a);
            pixels[point - 2 * stride] = s2u(u2s(pixels[2]) - a);
        }
    }
}

//normal filter
//works on the 8 pixels on the edges between macroblocks
pub(crate) fn macroblock_filter(hev_threshold: u8, interior_limit: u8, edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {

    let mut spixels = [0i32; 8];
    for i in 0..8 {
        spixels[i] = u2s(pixels[point + i * stride - 4 * stride]);
    }

    if should_filter(interior_limit, edge_limit, pixels, point, stride) {
        if !high_edge_variance(hev_threshold, pixels, point, stride) {
            let w = c(c(spixels[2] - spixels[5]) + 3 * (spixels[4] - spixels[3]));

            let mut a = c((27 * w + 63) >> 7);

            pixels[point] = s2u(spixels[4] - a);
            pixels[point - stride] = s2u(spixels[3] + a);

            a = c((18 * w + 63) >> 7);

            pixels[point + stride] = s2u(spixels[5] - a);
            pixels[point - 2 * stride] = s2u(spixels[2] + a);

            a = c((9 * w + 63) >> 7);

            pixels[point + 2 * stride] = s2u(spixels[6] - a);
            pixels[point - 3 * stride] = s2u(spixels[1] + a);

        } else {
            common_adjust(true, pixels, point, stride);
        }
    }
}

<commit_msg>Fixed bug in subblock filtering.<commit_after>//! Does loop filtering on webp lossy images

use crate::utils::clamp;

#[inline]
fn c(val: i32) -> i32 {
    clamp(val, -128, 127)
}

//unsigned to signed
#[inline]
fn u2s(val: u8) -> i32 {
    i32::from(val) - 128
}

//signed to unsigned
#[inline]
fn s2u(val: i32) -> u8 {
    (c(val) + 128) as u8
}

#[inline]
fn diff(val1: u8, val2: u8) -> u8 {
    if val1 > val2 {
        val1 - val2
    } else {
        val2 - val1
    }
}

//15.2
fn common_adjust(use_outer_taps: bool, pixels: &mut [u8], point: usize, stride: usize) -> i32 {
    let p1 = u2s(pixels[point - 2 * stride]);
    let p0 = u2s(pixels[point - stride]);
    let q0 = u2s(pixels[point]);
    let q1 = u2s(pixels[point + stride]);

    //value for the outer 2 pixels
    let outer = if use_outer_taps {
        c(p1 - q1)
    } else {
        0
    };

    let mut a = c(outer + 3 * (q0 - p0));

    let b = (c(a + 3)) >> 3;

    a = (c(a + 4)) >> 3;

    pixels[point] = s2u(q0 - a);
    pixels[point - stride] = s2u(p0 + b);

    a
}

fn simple_threshold(filter_limit: i32, pixels: &[u8], point: usize, stride: usize) -> bool {
   i32::from(diff(pixels[point - stride], pixels[point])) * 2 +
   i32::from(diff(pixels[point - 2 * stride], pixels[point + stride])) / 2 <= filter_limit
}

fn should_filter(interior_limit: u8, edge_limit: u8, pixels: &[u8], point: usize, stride: usize) -> bool {
    simple_threshold(i32::from(edge_limit), pixels, point, stride) &&
    diff(pixels[point - 4 * stride], pixels[point - 3 * stride]) <= interior_limit &&
    diff(pixels[point - 3 * stride], pixels[point - 2 * stride]) <= interior_limit &&
    diff(pixels[point - 2 * stride], pixels[point - stride]) <= interior_limit &&
    diff(pixels[point + 3 * stride], pixels[point + 2 * stride]) <= interior_limit &&
    diff(pixels[point + 2 * stride], pixels[point + stride]) <= interior_limit &&
    diff(pixels[point + stride], pixels[point]) <= interior_limit
}

fn high_edge_variance(threshold: u8, pixels: &[u8], point: usize, stride: usize) -> bool {
    diff(pixels[point - 2 * stride], pixels[point - stride]) > threshold ||
    diff(pixels[point + stride], pixels[point]) > threshold
}

//simple filter
//effects 4 pixels on an edge(2 each side)
pub(crate) fn simple_segment(edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {
    if simple_threshold(i32::from(edge_limit), pixels, point, stride) {
        common_adjust(true, pixels, point, stride);
    }
}

//normal filter
//works on the 8 pixels on the edges between subblocks inside a macroblock
pub(crate) fn subblock_filter(hev_threshold: u8, interior_limit: u8, edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {
    if should_filter(interior_limit, edge_limit, pixels, point, stride) {
        let hv = high_edge_variance(hev_threshold, pixels, point, stride);

        let a = (common_adjust(hv, pixels, point, stride) + 1) >> 1;

        if !hv {
            pixels[point + stride] = s2u(u2s(pixels[point + stride]) - a);
            pixels[point - 2 * stride] = s2u(u2s(pixels[point - 2 * stride]) - a);
        }
    }
}

//normal filter
//works on the 8 pixels on the edges between macroblocks
pub(crate) fn macroblock_filter(hev_threshold: u8, interior_limit: u8, edge_limit: u8, pixels: &mut [u8], point: usize, stride: usize) {

    let mut spixels = [0i32; 8];
    for i in 0..8 {
        spixels[i] = u2s(pixels[point + i * stride - 4 * stride]);
    }

    if should_filter(interior_limit, edge_limit, pixels, point, stride) {
        if !high_edge_variance(hev_threshold, pixels, point, stride) {
            let w = c(c(spixels[2] - spixels[5]) + 3 * (spixels[4] - spixels[3]));

            let mut a = c((27 * w + 63) >> 7);

            pixels[point] = s2u(spixels[4] - a);
            pixels[point - stride] = s2u(spixels[3] + a);

            a = c((18 * w + 63) >> 7);

            pixels[point + stride] = s2u(spixels[5] - a);
            pixels[point - 2 * stride] = s2u(spixels[2] + a);

            a = c((9 * w + 63) >> 7);

            pixels[point + 2 * stride] = s2u(spixels[6] - a);
            pixels[point - 3 * stride] = s2u(spixels[1] + a);

        } else {
            common_adjust(true, pixels, point, stride);
        }
    }
}

<|endoftext|>