<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}
        }
    ) => {
        ordered_passes_renderpass!{
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: []
                }
            ]
        }
    }
}

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:ty,
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]
                }
            ),*
        ]
    ) => {
        use std;        // TODO: import everything instead
        use std::vec::IntoIter as VecIntoIter;
        use std::sync::Arc;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::format::ClearValue;
        use $crate::framebuffer::UnsafeRenderPass;
        use $crate::framebuffer::RenderPassDesc;
        use $crate::framebuffer::LayoutAttachmentDescription;
        use $crate::framebuffer::LayoutPassDescription;
        use $crate::framebuffer::LayoutPassDependencyDescription;
        use $crate::image::traits::Image;
        use $crate::image::traits::ImageView;

        #[derive(Debug, Clone)]
        pub struct Formats {
            $(
                pub $atch_name: ($format, u32),
            )*
        }

        pub struct CustomRenderPass {
            render_pass: UnsafeRenderPass,
            formats: Formats,
        }

        impl CustomRenderPass {
            pub fn new(device: &Arc<Device>, formats: &Formats)
                       -> Result<Arc<CustomRenderPass>, OomError>
            {
                #![allow(unsafe_code)]

                let rp = try!(unsafe {
                    UnsafeRenderPass::new(device, attachments(formats), passes(), dependencies())
                });

                Ok(Arc::new(CustomRenderPass {
                    render_pass: rp,
                    formats: formats.clone(),
                }))
            }
        }

        unsafe impl $crate::framebuffer::RenderPass for CustomRenderPass {
            #[inline]
            fn render_pass(&self) -> &UnsafeRenderPass {
                &self.render_pass
            }
        }

        unsafe impl RenderPassDesc for CustomRenderPass {
            type AttachmentsIter = VecIntoIter<LayoutAttachmentDescription>;
            type PassesIter = VecIntoIter<LayoutPassDescription>;
            type DependenciesIter = VecIntoIter<LayoutPassDependencyDescription>;

            #[inline]
            fn attachments(&self) -> Self::AttachmentsIter {
                attachments(&self.formats)
            }

            #[inline]
            fn passes(&self) -> Self::PassesIter {
                passes()
            }

            #[inline]
            fn dependencies(&self) -> Self::DependenciesIter {
                dependencies()
            }
        }

        /// Returns an iterator to the list of attachments of this render pass.
        #[inline]
        fn attachments(formats: &Formats) -> VecIntoIter<LayoutAttachmentDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut num = 0;
            vec![$({
                let (initial_layout, final_layout) = attachment_layouts(num);
                num += 1;

                $crate::framebuffer::LayoutAttachmentDescription {
                    format: $crate::format::FormatDesc::format(&formats.$atch_name.0),
                    samples: formats.$atch_name.1,
                    load: $crate::framebuffer::LoadOp::$load,
                    store: $crate::framebuffer::StoreOp::$store,
                    initial_layout: initial_layout,
                    final_layout: final_layout,
                }
            }),*].into_iter()
        }

        /// Returns an iterator to the list of passes of this render pass.
        #[inline]
        fn passes() -> VecIntoIter<LayoutPassDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            vec![
                $({
                    let mut depth = None;
                    $(
                        depth = Some(($depth_atch, $crate::image::Layout::DepthStencilAttachmentOptimal));
                    )*

                    $crate::framebuffer::LayoutPassDescription {
                        color_attachments: vec![
                            $(
                                ($color_atch, $crate::image::Layout::ColorAttachmentOptimal)
                            ),*
                        ],
                        depth_stencil: depth,
                        input_attachments: vec![
                            $(
                                ($input_atch, $crate::image::Layout::ShaderReadOnlyOptimal)
                            ),*
                        ],
                        resolve_attachments: vec![],
                        preserve_attachments: (0 .. attachment_num).filter(|&a| {
                            $(if a == $color_atch { return false; })*
                            $(if a == $depth_atch { return false; })*
                            $(if a == $input_atch { return false; })*
                            true
                        }).collect()
                    }
                }),*
            ].into_iter()
        }

        /// Returns an iterator to the list of pass dependencies of this render pass.
        #[inline]
        fn dependencies() -> VecIntoIter<LayoutPassDependencyDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            (1 .. passes().len()).flat_map(|p2| {
                (0 .. p2.clone()).map(move |p1| {
                    $crate::framebuffer::LayoutPassDependencyDescription {
                        source_subpass: p1,
                        destination_subpass: p2,
                        by_region: false,
                    }
                })
            }).collect::<Vec<_>>().into_iter()
        }

        /// Returns the initial and final layout of an attachment, given its num.
        fn attachment_layouts(num: u32) -> ($crate::image::Layout, $crate::image::Layout) {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            let mut initial_layout = None;
            let mut final_layout = None;

            $({
                $(
                    if $depth_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some($crate::image::Layout::DepthStencilAttachmentOptimal);
                        }
                        final_layout = Some($crate::image::Layout::DepthStencilAttachmentOptimal);
                    }
                )*

                $(
                    if $color_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some($crate::image::Layout::ColorAttachmentOptimal);
                        }
                        final_layout = Some($crate::image::Layout::ColorAttachmentOptimal);
                    }
                )*

                $(
                    if $input_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some($crate::image::Layout::ShaderReadOnlyOptimal);
                        }
                        final_layout = Some($crate::image::Layout::ShaderReadOnlyOptimal);
                    }
                )*
            })*

            (initial_layout.unwrap(), final_layout.unwrap())
        }

        #[allow(non_camel_case_types)]
        pub struct AList<'a, $($atch_name: 'a),*> {
            $(
                pub $atch_name: &'a Arc<$atch_name>,
            )*
        }

        #[allow(non_camel_case_types)]
        unsafe impl<'a, $($atch_name: 'static + ImageView),*> $crate::framebuffer::RenderPassAttachmentsList<AList<'a, $($atch_name),*>> for CustomRenderPass {
            // TODO: shouldn't build a Vec
            type AttachmentsIter = std::vec::IntoIter<(Arc<ImageView>, Arc<Image>, $crate::image::Layout, $crate::image::Layout)>;

            #[inline]
            fn convert_attachments_list(&self, l: AList<'a, $($atch_name),*>) -> Self::AttachmentsIter {
                #![allow(unused_assignments)]

                let mut result = Vec::new();

                let mut num = 0;
                $({
                    let (initial_layout, final_layout) = attachment_layouts(num);
                    num += 1;
                    result.push((l.$atch_name.clone() as Arc<_>, ImageView::parent_arc(&l.$atch_name), initial_layout, final_layout));
                })*

                result.into_iter()
            }
        }

        ordered_passes_renderpass!{__impl_clear_values__ [0] [] [$($atch_name $format, $load,)*] }

        unsafe impl $crate::framebuffer::RenderPassClearValues<ClearValues> for CustomRenderPass {
            type ClearValuesIter = ClearValuesIter;

            #[inline]
            fn convert_clear_values(&self, val: ClearValues) -> ClearValuesIter {
                ClearValuesIter(val, 0)
            }
        }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, Clear, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)* $atch_name [$num] $format,] [$($rest)*] }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, $misc:ident, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)*] [$($rest)*] }
    };

    (__impl_clear_values__ [$total:expr] [$($atch:ident [$num:expr] $format:ty,)+] []) => {
        pub struct ClearValues {
            $(
                pub $atch: <$format as $crate::format::FormatDesc>::ClearValue,
            )+
        }

        pub struct ClearValuesIter(ClearValues, usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                $(
                    if self.1 == $num {
                        self.1 += 1;
                        return Some(ClearValue::from((self.0).$atch));        // FIXME: should use Format::decode_clear_value instead
                    }
                )+

                if self.1 >= $total {
                    None
                } else {
                    Some(ClearValue::None)
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let len = $total - self.1;
                (len, Some(len))
            }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };

    (__impl_clear_values__ [$total:expr] [] []) => {
        pub type ClearValues = ();

        pub struct ClearValuesIter((), usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> { None }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(0)) }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };
}
<commit_msg>Improve imports in render pass macros<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}
        }
    ) => {
        ordered_passes_renderpass!{
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: []
                }
            ]
        }
    }
}

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:ty,
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]
                }
            ),*
        ]
    ) => {
        use std::vec::IntoIter as VecIntoIter;
        use std::sync::Arc;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::format::ClearValue;
        use $crate::framebuffer::UnsafeRenderPass;
        use $crate::framebuffer::RenderPass;
        use $crate::framebuffer::RenderPassDesc;
        use $crate::framebuffer::RenderPassClearValues;
        use $crate::framebuffer::RenderPassAttachmentsList;
        use $crate::framebuffer::LayoutAttachmentDescription;
        use $crate::framebuffer::LayoutPassDescription;
        use $crate::framebuffer::LayoutPassDependencyDescription;
        use $crate::image::Layout;
        use $crate::image::traits::Image;
        use $crate::image::traits::ImageView;

        #[derive(Debug, Clone)]
        pub struct Formats {
            $(
                pub $atch_name: ($format, u32),
            )*
        }

        pub struct CustomRenderPass {
            render_pass: UnsafeRenderPass,
            formats: Formats,
        }

        impl CustomRenderPass {
            pub fn new(device: &Arc<Device>, formats: &Formats)
                       -> Result<Arc<CustomRenderPass>, OomError>
            {
                #![allow(unsafe_code)]

                let rp = try!(unsafe {
                    UnsafeRenderPass::new(device, attachments(formats), passes(), dependencies())
                });

                Ok(Arc::new(CustomRenderPass {
                    render_pass: rp,
                    formats: formats.clone(),
                }))
            }
        }

        unsafe impl RenderPass for CustomRenderPass {
            #[inline]
            fn render_pass(&self) -> &UnsafeRenderPass {
                &self.render_pass
            }
        }

        unsafe impl RenderPassDesc for CustomRenderPass {
            type AttachmentsIter = VecIntoIter<LayoutAttachmentDescription>;
            type PassesIter = VecIntoIter<LayoutPassDescription>;
            type DependenciesIter = VecIntoIter<LayoutPassDependencyDescription>;

            #[inline]
            fn attachments(&self) -> Self::AttachmentsIter {
                attachments(&self.formats)
            }

            #[inline]
            fn passes(&self) -> Self::PassesIter {
                passes()
            }

            #[inline]
            fn dependencies(&self) -> Self::DependenciesIter {
                dependencies()
            }
        }

        /// Returns an iterator to the list of attachments of this render pass.
        #[inline]
        fn attachments(formats: &Formats) -> VecIntoIter<LayoutAttachmentDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut num = 0;
            vec![$({
                let (initial_layout, final_layout) = attachment_layouts(num);
                num += 1;

                $crate::framebuffer::LayoutAttachmentDescription {
                    format: $crate::format::FormatDesc::format(&formats.$atch_name.0),
                    samples: formats.$atch_name.1,
                    load: $crate::framebuffer::LoadOp::$load,
                    store: $crate::framebuffer::StoreOp::$store,
                    initial_layout: initial_layout,
                    final_layout: final_layout,
                }
            }),*].into_iter()
        }

        /// Returns an iterator to the list of passes of this render pass.
        #[inline]
        fn passes() -> VecIntoIter<LayoutPassDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            vec![
                $({
                    let mut depth = None;
                    $(
                        depth = Some(($depth_atch, Layout::DepthStencilAttachmentOptimal));
                    )*

                    $crate::framebuffer::LayoutPassDescription {
                        color_attachments: vec![
                            $(
                                ($color_atch, Layout::ColorAttachmentOptimal)
                            ),*
                        ],
                        depth_stencil: depth,
                        input_attachments: vec![
                            $(
                                ($input_atch, Layout::ShaderReadOnlyOptimal)
                            ),*
                        ],
                        resolve_attachments: vec![],
                        preserve_attachments: (0 .. attachment_num).filter(|&a| {
                            $(if a == $color_atch { return false; })*
                            $(if a == $depth_atch { return false; })*
                            $(if a == $input_atch { return false; })*
                            true
                        }).collect()
                    }
                }),*
            ].into_iter()
        }

        /// Returns an iterator to the list of pass dependencies of this render pass.
        #[inline]
        fn dependencies() -> VecIntoIter<LayoutPassDependencyDescription> {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            (1 .. passes().len()).flat_map(|p2| {
                (0 .. p2.clone()).map(move |p1| {
                    LayoutPassDependencyDescription {
                        source_subpass: p1,
                        destination_subpass: p2,
                        by_region: false,
                    }
                })
            }).collect::<Vec<_>>().into_iter()
        }

        /// Returns the initial and final layout of an attachment, given its num.
        fn attachment_layouts(num: u32) -> (Layout, Layout) {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            let mut initial_layout = None;
            let mut final_layout = None;

            $({
                $(
                    if $depth_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::DepthStencilAttachmentOptimal);
                        }
                        final_layout = Some(Layout::DepthStencilAttachmentOptimal);
                    }
                )*

                $(
                    if $color_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ColorAttachmentOptimal);
                        }
                        final_layout = Some(Layout::ColorAttachmentOptimal);
                    }
                )*

                $(
                    if $input_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ShaderReadOnlyOptimal);
                        }
                        final_layout = Some(Layout::ShaderReadOnlyOptimal);
                    }
                )*
            })*

            (initial_layout.unwrap(), final_layout.unwrap())
        }

        #[allow(non_camel_case_types)]
        pub struct AList<'a, $($atch_name: 'a),*> {
            $(
                pub $atch_name: &'a Arc<$atch_name>,
            )*
        }

        #[allow(non_camel_case_types)]
        unsafe impl<'a, $($atch_name: 'static + ImageView),*> RenderPassAttachmentsList<AList<'a, $($atch_name),*>> for CustomRenderPass {
            // TODO: shouldn't build a Vec
            type AttachmentsIter = VecIntoIter<(Arc<ImageView>, Arc<Image>, Layout, Layout)>;

            #[inline]
            fn convert_attachments_list(&self, l: AList<'a, $($atch_name),*>) -> Self::AttachmentsIter {
                #![allow(unused_assignments)]

                let mut result = Vec::new();

                let mut num = 0;
                $({
                    let (initial_layout, final_layout) = attachment_layouts(num);
                    num += 1;
                    result.push((l.$atch_name.clone() as Arc<_>, ImageView::parent_arc(&l.$atch_name), initial_layout, final_layout));
                })*

                result.into_iter()
            }
        }

        ordered_passes_renderpass!{__impl_clear_values__ [0] [] [$($atch_name $format, $load,)*] }

        unsafe impl RenderPassClearValues<ClearValues> for CustomRenderPass {
            type ClearValuesIter = ClearValuesIter;

            #[inline]
            fn convert_clear_values(&self, val: ClearValues) -> ClearValuesIter {
                ClearValuesIter(val, 0)
            }
        }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, Clear, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)* $atch_name [$num] $format,] [$($rest)*] }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, $misc:ident, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)*] [$($rest)*] }
    };

    (__impl_clear_values__ [$total:expr] [$($atch:ident [$num:expr] $format:ty,)+] []) => {
        pub struct ClearValues {
            $(
                pub $atch: <$format as $crate::format::FormatDesc>::ClearValue,
            )+
        }

        pub struct ClearValuesIter(ClearValues, usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                $(
                    if self.1 == $num {
                        self.1 += 1;
                        return Some(ClearValue::from((self.0).$atch));        // FIXME: should use Format::decode_clear_value instead
                    }
                )+

                if self.1 >= $total {
                    None
                } else {
                    Some(ClearValue::None)
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let len = $total - self.1;
                (len, Some(len))
            }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };

    (__impl_clear_values__ [$total:expr] [] []) => {
        pub type ClearValues = ();

        pub struct ClearValuesIter((), usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> { None }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(0)) }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };
}
<|endoftext|>


<commit_before>use client;
use serde_json;
use std::fmt;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Errcode {
	// UNKNOWN_ERROR
	UnknownError,

	// 1xxx errors
	ApiVersionNotFound,
	ApiVersionDeprecated,
	ApiClassNotFound,
	ApiFunctionNotFound,
	NoApiPermissions,
	InvalidToken,
	ApiFunctionDisabled,
	ProxerMaintenance,
	ApiMaintenance,

	// 2xxx errors
	IpBlocked,
	NewsError,

	// 3xxx errors
	MissingLoginCredentials,
	InvalidLoginCredentials,
	InvalidId,
	InvalidUid,
	UserNotLoggedIn,
	UserNotFound,
	UserAlreadyLoggedIn,
}

impl Errcode {
	pub fn from_code(code: i64) -> Self {
		match code {
			1000 => Errcode::ApiVersionNotFound,
			1001 => Errcode::ApiVersionDeprecated,
			1002 => Errcode::ApiClassNotFound,
			1003 => Errcode::ApiFunctionNotFound,
			1004 => Errcode::NoApiPermissions,
			1005 => Errcode::InvalidToken,
			1006 => Errcode::ApiFunctionDisabled,
			1007 => Errcode::ProxerMaintenance,
			1008 => Errcode::ApiMaintenance,

			2000 => Errcode::IpBlocked,
			2001 => Errcode::NewsError,

			3000 => Errcode::MissingLoginCredentials,
			3001 => Errcode::InvalidLoginCredentials,
			3002 => Errcode::UserNotLoggedIn,
			3003 => Errcode::UserNotFound,
			3004 => Errcode::UserNotLoggedIn,
			3007 => Errcode::InvalidId,
			3009 => Errcode::UserNotLoggedIn,
			3012 => Errcode::UserAlreadyLoggedIn,
			3023 => Errcode::UserNotLoggedIn,
			3034 => Errcode::UserNotLoggedIn,

			_ => Errcode::UnknownError,
		}
	}
}

impl From<i64> for Errcode {
	fn from(code: i64) -> Errcode {
		Errcode::from_code(code)
	}
}

impl fmt::Display for Errcode {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Api: {:?}", self)
	}
}

#[derive(Debug, Clone)]
pub struct Api {
	code: i64,
	message: String,
	error: Errcode,
}

impl Api {
	pub fn new(code: i64, msg: String) -> Self {
		Api {
			code: code,
			message: msg,
			error: Errcode::from(code),
		}
	}

	pub fn error(&self) -> Errcode {
		self.error
	}
}

impl From<serde_json::Value> for Api {
	fn from(json: serde_json::Value) -> Self {
		let error = json.get("code").unwrap().as_i64().unwrap();
		let msg = json.get("message").unwrap().as_str().unwrap();

		Self {
			error: Errcode::from_code(error),
			code: error,
			message: msg.to_string(),
		}
	}
}

impl<T> From<client::ApiResponse<T>> for Api {
	fn from(res: client::ApiResponse<T>) -> Self {
		Self {
			code: res.code.unwrap(),
			error: Errcode::from_code(res.code.unwrap()),
			message: res.message.to_string(),
		}
	}
}

impl fmt::Display for Api {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", Errcode::from(self.code))
	}
}
<commit_msg>add error<commit_after>use client;
use serde_json;
use std::fmt;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Errcode {
	// UNKNOWN_ERROR
	UnknownError,

	// 1xxx errors
	ApiClassNotFound,
	ApiFunctionDisabled,
	ApiFunctionNotFound,
	ApiMaintenance,
	ApiVersionDeprecated,
	ApiVersionNotFound,
	InvalidToken,
	NoApiPermissions,
	ProxerMaintenance,

	// 2xxx errors
	IpBlocked,
	NewsError,

	// 3xxx errors
	AccessDenied,
	InvalidId,
	InvalidLoginCredentials,
	InvalidUid,
	MissingLoginCredentials,
	UserAlreadyLoggedIn,
	UserNotFound,
	UserNotLoggedIn,
}

impl Errcode {
	pub fn from_code(code: i64) -> Self {
		match code {
			1000 => Errcode::ApiVersionNotFound,
			1001 => Errcode::ApiVersionDeprecated,
			1002 => Errcode::ApiClassNotFound,
			1003 => Errcode::ApiFunctionNotFound,
			1004 => Errcode::NoApiPermissions,
			1005 => Errcode::InvalidToken,
			1006 => Errcode::ApiFunctionDisabled,
			1007 => Errcode::ProxerMaintenance,
			1008 => Errcode::ApiMaintenance,

			2000 => Errcode::IpBlocked,
			2001 => Errcode::NewsError,

			3000 => Errcode::MissingLoginCredentials,
			3001 => Errcode::InvalidLoginCredentials,
			3002 => Errcode::UserNotLoggedIn,
			3003 => Errcode::UserNotFound,
			3004 => Errcode::UserNotLoggedIn,
			3007 => Errcode::InvalidId,
			3009 => Errcode::UserNotLoggedIn,
			3012 => Errcode::UserAlreadyLoggedIn,
			3014 => Errcode::AccessDenied,
			3023 => Errcode::UserNotLoggedIn,
			3034 => Errcode::UserNotLoggedIn,

			_ => Errcode::UnknownError,
		}
	}
}

impl From<i64> for Errcode {
	fn from(code: i64) -> Errcode {
		Errcode::from_code(code)
	}
}

impl fmt::Display for Errcode {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Api: {:?}", self)
	}
}

#[derive(Debug, Clone)]
pub struct Api {
	code: i64,
	message: String,
	error: Errcode,
}

impl Api {
	pub fn new(code: i64, msg: String) -> Self {
		Api {
			code: code,
			message: msg,
			error: Errcode::from(code),
		}
	}

	pub fn error(&self) -> Errcode {
		self.error
	}
}

impl From<serde_json::Value> for Api {
	fn from(json: serde_json::Value) -> Self {
		let error = json.get("code").unwrap().as_i64().unwrap();
		let msg = json.get("message").unwrap().as_str().unwrap();

		Self {
			error: Errcode::from_code(error),
			code: error,
			message: msg.to_string(),
		}
	}
}

impl<T> From<client::ApiResponse<T>> for Api {
	fn from(res: client::ApiResponse<T>) -> Self {
		Self {
			code: res.code.unwrap(),
			error: Errcode::from_code(res.code.unwrap()),
			message: res.message.to_string(),
		}
	}
}

impl fmt::Display for Api {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", Errcode::from(self.code))
	}
}
<|endoftext|>


<commit_before>use lang::Lang;
use script::Script;
use script::detect_script;
use info::Info;
use options;
use options::Options;

use detect;

/// Configurable structure that holds detection options and provides functions
/// to detect language and script.
/// # Examples
/// Specifying a whitelist:
///
/// ```
/// use whatlang::{Detector, Lang};
///
/// const WHITELIST : &'static [Lang] = &[Lang::Eng, Lang::Rus];
///
/// // Create detector with whitelist
/// let detector = Detector::with_whitelist(WHITELIST);
/// let lang = detector.detect_lang("That is not Russian");
/// assert_eq!(lang, Some(Lang::Eng));
/// ```
///
/// Specifying a blacklist:
///
/// ```
/// use whatlang::{Detector, Lang};
///
/// const BLACKLIST: &'static [Lang] = &[Lang::Eng, Lang::Ita];
///
/// let detector = Detector::with_blacklist(BLACKLIST);
/// let lang = detector.detect_lang("Jen la trinkejo fermitis, ni iras tra mallumo kaj pluvo.");
/// assert_eq!(lang, Some(Lang::Epo));
/// ```
pub struct Detector<'a> {
    options: Options<'a>,
}

impl<'a> Detector<'a> {
    pub fn new() -> Self {
        Self { options: options::DEFAULT }
    }

    pub fn with_whitelist(whitelist: &'a [Lang]) -> Self {
        let opts = Options { whitelist: Some(whitelist), blacklist: None };
        Self { options: opts }
    }

    pub fn with_blacklist(blacklist: &'a [Lang]) -> Self {
        let opts = Options { whitelist: None, blacklist: Some(blacklist) };
        Self { options: opts }
    }

    pub fn detect(&self, text: &str) -> Option<Info> {
        detect::detect_with_options(text, &self.options)
    }

    pub fn detect_lang(&self, text: &str) -> Option<Lang> {
        detect::detect_lang_with_options(text, &self.options)
    }

    pub fn detect_script(&self, text: &str) -> Option<Script> {
        detect_script(text)
    }
}

#[cfg(test)]
mod tests {
    use super::Detector;
    use super::Script;
    use super::Lang;

    #[test]
    fn test_detect_script() {
        // Russian, Cyrillic
        assert_eq!(Detector::new().detect_script("Кириллица"), Some(Script::Cyrillic));
    }

    #[test]
    fn test_detect_lang() {
        // Esperanto
        let text = "Ĉiuj redaktantoj de Esperanta Vikipedio estas volontuloj. Ili partoprenas en la kunlaborema komunumo, sen estro, kie la anoj kunordigas siajn strebojn kadre de temaj projektoj kaj pluraj diskutejoj. Ili sekvas la bazajn regulojn establitaj de la komunumo, ekzemple kontrolebleco de la informo aŭ la menciindeco de la temo.";
        assert_eq!(Detector::new().detect_lang(text), Some(Lang::Epo));
    }

    #[test]
    fn test_detect() {
        // Esperanto
        let text = "Ĉiuj redaktantoj de Esperanta Vikipedio estas volontuloj. Ili partoprenas en la kunlaborema komunumo, sen estro, kie la anoj kunordigas siajn strebojn kadre de temaj projektoj kaj pluraj diskutejoj. Ili sekvas la bazajn regulojn establitaj de la komunumo, ekzemple kontrolebleco de la informo aŭ la menciindeco de la temo.";
        let output = Detector::new().detect(text);
        assert_eq!(output.is_some(), true);

        let info = output.unwrap();
        assert_eq!(info.lang, Lang::Epo);
        assert_eq!(info.script, Script::Latin);
    }
}
<commit_msg>Fix build for Rust 1.15<commit_after>use lang::Lang;
use script::Script;
use script::detect_script;
use info::Info;
use options;
use options::Options;

use detect;

/// Configurable structure that holds detection options and provides functions
/// to detect language and script.
/// # Examples
/// Specifying a whitelist:
///
/// ```
/// use whatlang::{Detector, Lang};
///
/// const WHITELIST : &'static [Lang] = &[Lang::Eng, Lang::Rus];
///
/// // Create detector with whitelist
/// let detector = Detector::with_whitelist(WHITELIST);
/// let lang = detector.detect_lang("That is not Russian");
/// assert_eq!(lang, Some(Lang::Eng));
/// ```
///
/// Specifying a blacklist:
///
/// ```
/// use whatlang::{Detector, Lang};
///
/// const BLACKLIST: &'static [Lang] = &[Lang::Eng, Lang::Ita];
///
/// let detector = Detector::with_blacklist(BLACKLIST);
/// let lang = detector.detect_lang("Jen la trinkejo fermitis, ni iras tra mallumo kaj pluvo.");
/// assert_eq!(lang, Some(Lang::Epo));
/// ```
pub struct Detector<'a> {
    options: Options<'a>,
}

impl<'a> Detector<'a> {
    pub fn new() -> Self {
        Detector { options: options::DEFAULT }
    }

    pub fn with_whitelist(whitelist: &'a [Lang]) -> Self {
        let opts = Options { whitelist: Some(whitelist), blacklist: None };
        Detector { options: opts }
    }

    pub fn with_blacklist(blacklist: &'a [Lang]) -> Self {
        let opts = Options { whitelist: None, blacklist: Some(blacklist) };
        Detector { options: opts }
    }

    pub fn detect(&self, text: &str) -> Option<Info> {
        detect::detect_with_options(text, &self.options)
    }

    pub fn detect_lang(&self, text: &str) -> Option<Lang> {
        detect::detect_lang_with_options(text, &self.options)
    }

    pub fn detect_script(&self, text: &str) -> Option<Script> {
        detect_script(text)
    }
}

#[cfg(test)]
mod tests {
    use super::Detector;
    use super::Script;
    use super::Lang;

    #[test]
    fn test_detect_script() {
        // Russian, Cyrillic
        assert_eq!(Detector::new().detect_script("Кириллица"), Some(Script::Cyrillic));
    }

    #[test]
    fn test_detect_lang() {
        // Esperanto
        let text = "Ĉiuj redaktantoj de Esperanta Vikipedio estas volontuloj. Ili partoprenas en la kunlaborema komunumo, sen estro, kie la anoj kunordigas siajn strebojn kadre de temaj projektoj kaj pluraj diskutejoj. Ili sekvas la bazajn regulojn establitaj de la komunumo, ekzemple kontrolebleco de la informo aŭ la menciindeco de la temo.";
        assert_eq!(Detector::new().detect_lang(text), Some(Lang::Epo));
    }

    #[test]
    fn test_detect() {
        // Esperanto
        let text = "Ĉiuj redaktantoj de Esperanta Vikipedio estas volontuloj. Ili partoprenas en la kunlaborema komunumo, sen estro, kie la anoj kunordigas siajn strebojn kadre de temaj projektoj kaj pluraj diskutejoj. Ili sekvas la bazajn regulojn establitaj de la komunumo, ekzemple kontrolebleco de la informo aŭ la menciindeco de la temo.";
        let output = Detector::new().detect(text);
        assert_eq!(output.is_some(), true);

        let info = output.unwrap();
        assert_eq!(info.lang, Lang::Epo);
        assert_eq!(info.script, Script::Latin);
    }
}
<|endoftext|>


<commit_before>use super::{Function, Parameterised, VFunction, QFunction, Projection, SparseProjection};
use geometry::Space;
use ndarray::{ArrayView, Array1, Array2};
use std::marker::PhantomData;
use utils::dot;

#[derive(Serialize, Deserialize)]
pub struct DenseLinear<S: Space, P: Projection<S>> {
    pub projector: P,
    pub weights: Array2<f64>,

    phantom: PhantomData<S>,
}

impl<S: Space, P: Projection<S>> DenseLinear<S, P> {
    pub fn new(projector: P, n_outputs: usize) -> Self {
        let n_features = projector.size();

        Self {
            projector: projector,
            weights: Array2::<f64>::zeros((n_features, n_outputs)),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, P: Projection<S>> Function<S::Repr, f64> for DenseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> f64 {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as VFunction<S>>::evaluate_phi(self, &phi)
    }
}

impl<S: Space, P: Projection<S>> Function<S::Repr, Vec<f64>> for DenseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> Vec<f64> {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        // Apply matrix multiplication and return Vec<f64>:
        <Self as QFunction<S>>::evaluate_phi(self, &phi)
    }
}

impl<S: Space, P: Projection<S>> Parameterised<S::Repr, f64> for DenseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, error: f64) {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as VFunction<S>>::update_phi(self, &phi, error);
    }
}

impl<S: Space, P: Projection<S>> Parameterised<S::Repr, Vec<f64>> for DenseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, errors: Vec<f64>) {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as QFunction<S>>::update_phi(self, &phi, errors);
    }
}

impl<S: Space, P: Projection<S>> VFunction<S> for DenseLinear<S, P> {
    fn evaluate_phi(&self, phi: &Array1<f64>) -> f64 {
        dot(self.weights.column(0).as_slice().unwrap(),
            phi.as_slice().unwrap())
    }

    fn update_phi(&mut self, phi: &Array1<f64>, error: f64) {
        self.weights.column_mut(0).scaled_add(error, phi);
    }
}

impl<S: Space, P: Projection<S>> QFunction<S> for DenseLinear<S, P> {
    fn evaluate_action(&self, input: &S::Repr, action: usize) -> f64 {
        let phi = self.projector.project(input);

        self.evaluate_action_phi(&phi, action)
    }

    fn update_action(&mut self, input: &S::Repr, action: usize, error: f64) {
        let phi = self.projector.project(input);

        self.update_action_phi(&phi, action, error);
    }

    fn evaluate_phi(&self, phi: &Array1<f64>) -> Vec<f64> {
        (self.weights.t().dot(phi)).into_raw_vec()
    }

    fn evaluate_action_phi(&self, phi: &Array1<f64>, action: usize) -> f64 {
        self.weights.column(action).dot(phi)
    }

    fn update_phi(&mut self, phi: &Array1<f64>, errors: Vec<f64>) {
        let phi_view = phi.view().into_shape((self.weights.rows(), 1)).unwrap();
        let error_matrix = ArrayView::from_shape((1, self.weights.cols()), errors.as_slice())
            .unwrap();

        self.weights += &phi_view.dot(&error_matrix);
    }

    fn update_action_phi(&mut self, phi: &Array1<f64>, action: usize, error: f64) {
        self.weights.column_mut(action).scaled_add(error, &phi);
    }
}

impl<S: Space, P: Projection<S>> Projection<S> for DenseLinear<S, P> {
    fn project(&self, input: &S::Repr) -> Array1<f64> {
        self.projector.project(input)
    }

    fn project_onto(&self, input: &S::Repr, phi: &mut Array1<f64>) {
        self.projector.project_onto(input, phi);
    }

    fn dim(&self) -> usize {
        self.projector.dim()
    }

    fn size(&self) -> usize {
        self.projector.size()
    }

    fn equivalent(&self, other: &Self) -> bool {
        self.projector.equivalent(&other.projector)
    }
}

#[derive(Serialize, Deserialize)]
pub struct SparseLinear<S: Space, P: SparseProjection<S>> {
    pub projector: P,
    pub weights: Array2<f64>,

    phantom: PhantomData<S>,
}

impl<S: Space, P: SparseProjection<S>> SparseLinear<S, P> {
    pub fn new(projector: P, n_outputs: usize) -> Self {
        let n_features = projector.size();

        Self {
            projector: projector,
            weights: Array2::<f64>::zeros((n_features, n_outputs)),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, P: SparseProjection<S>> Function<S::Repr, f64> for SparseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> f64 {
        self.projector.project_sparse(input).fold(0.0f64,
                                                  |acc, i| acc + self.weights.column(0)[*i])
    }
}

impl<S: Space, P: SparseProjection<S>> Function<S::Repr, Vec<f64>> for SparseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> Vec<f64> {
        let indices = self.projector.project_sparse(input);

        (0..self.weights.cols()).map(|c| {
            indices.fold(0.0f64, |acc, i| acc + self.weights.column(c)[*i])
        }).collect()
    }
}

impl<S: Space, P: SparseProjection<S>> Parameterised<S::Repr, f64> for SparseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, error: f64) {
        let scaled_error = error / self.projector.sparsity() as f64;

        for i in self.projector.project_sparse(input).iter() {
            self.weights.column_mut(0)[*i] += scaled_error;
        }
    }
}

impl<S: Space, P: SparseProjection<S>> Parameterised<S::Repr, Vec<f64>> for SparseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, errors: Vec<f64>) {
        for c in 0..self.weights.cols() {
            let scaled_error = errors[c] / self.projector.sparsity() as f64;

            for i in self.projector.project_sparse(input).iter() {
                self.weights.column_mut(c)[*i] += scaled_error;
            }
        }
    }
}

impl<S: Space, P: SparseProjection<S>> VFunction<S> for SparseLinear<S, P> {}

impl<S: Space, P: SparseProjection<S>> QFunction<S> for SparseLinear<S, P> {
    fn evaluate_action(&self, input: &S::Repr, action: usize) -> f64 {
        self.projector.project_sparse(input).fold(0.0f64,
                                                  |acc, i| acc + self.weights.column(action)[*i])
    }

    fn update_action(&mut self, input: &S::Repr, action: usize, error: f64) {
        let scaled_error = error / self.projector.sparsity() as f64;

        for i in self.projector.project_sparse(input).iter() {
            self.weights.column_mut(action)[*i] += scaled_error;
        }
    }
}
<commit_msg>test(fa): add tests for DenseLinear update/eval<commit_after>use super::{Function, Parameterised, VFunction, QFunction, Projection, SparseProjection};
use geometry::Space;
use ndarray::{ArrayView, Array1, Array2};
use std::marker::PhantomData;
use utils::dot;

#[derive(Serialize, Deserialize)]
pub struct DenseLinear<S: Space, P: Projection<S>> {
    pub projector: P,
    pub weights: Array2<f64>,

    phantom: PhantomData<S>,
}

impl<S: Space, P: Projection<S>> DenseLinear<S, P> {
    pub fn new(projector: P, n_outputs: usize) -> Self {
        let n_features = projector.size();

        Self {
            projector: projector,
            weights: Array2::<f64>::zeros((n_features, n_outputs)),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, P: Projection<S>> Function<S::Repr, f64> for DenseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> f64 {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as VFunction<S>>::evaluate_phi(self, &phi)
    }
}

impl<S: Space, P: Projection<S>> Function<S::Repr, Vec<f64>> for DenseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> Vec<f64> {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        // Apply matrix multiplication and return Vec<f64>:
        <Self as QFunction<S>>::evaluate_phi(self, &phi)
    }
}

impl<S: Space, P: Projection<S>> Parameterised<S::Repr, f64> for DenseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, error: f64) {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as VFunction<S>>::update_phi(self, &phi, error);
    }
}

impl<S: Space, P: Projection<S>> Parameterised<S::Repr, Vec<f64>> for DenseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, errors: Vec<f64>) {
        // Compute the feature vector phi:
        let phi = self.projector.project(input);

        <Self as QFunction<S>>::update_phi(self, &phi, errors);
    }
}

impl<S: Space, P: Projection<S>> VFunction<S> for DenseLinear<S, P> {
    fn evaluate_phi(&self, phi: &Array1<f64>) -> f64 {
        dot(self.weights.column(0).as_slice().unwrap(),
            phi.as_slice().unwrap())
    }

    fn update_phi(&mut self, phi: &Array1<f64>, error: f64) {
        self.weights.column_mut(0).scaled_add(error, phi);
    }
}

impl<S: Space, P: Projection<S>> QFunction<S> for DenseLinear<S, P> {
    fn evaluate_action(&self, input: &S::Repr, action: usize) -> f64 {
        let phi = self.projector.project(input);

        self.evaluate_action_phi(&phi, action)
    }

    fn update_action(&mut self, input: &S::Repr, action: usize, error: f64) {
        let phi = self.projector.project(input);

        self.update_action_phi(&phi, action, error);
    }

    fn evaluate_phi(&self, phi: &Array1<f64>) -> Vec<f64> {
        (self.weights.t().dot(phi)).into_raw_vec()
    }

    fn evaluate_action_phi(&self, phi: &Array1<f64>, action: usize) -> f64 {
        self.weights.column(action).dot(phi)
    }

    fn update_phi(&mut self, phi: &Array1<f64>, errors: Vec<f64>) {
        let phi_view = phi.view().into_shape((self.weights.rows(), 1)).unwrap();
        let error_matrix = ArrayView::from_shape((1, self.weights.cols()), errors.as_slice())
            .unwrap();

        self.weights += &phi_view.dot(&error_matrix);
    }

    fn update_action_phi(&mut self, phi: &Array1<f64>, action: usize, error: f64) {
        self.weights.column_mut(action).scaled_add(error, &phi);
    }
}

impl<S: Space, P: Projection<S>> Projection<S> for DenseLinear<S, P> {
    fn project(&self, input: &S::Repr) -> Array1<f64> {
        self.projector.project(input)
    }

    fn project_onto(&self, input: &S::Repr, phi: &mut Array1<f64>) {
        self.projector.project_onto(input, phi);
    }

    fn dim(&self) -> usize {
        self.projector.dim()
    }

    fn size(&self) -> usize {
        self.projector.size()
    }

    fn equivalent(&self, other: &Self) -> bool {
        self.projector.equivalent(&other.projector)
    }
}

#[derive(Serialize, Deserialize)]
pub struct SparseLinear<S: Space, P: SparseProjection<S>> {
    pub projector: P,
    pub weights: Array2<f64>,

    phantom: PhantomData<S>,
}

impl<S: Space, P: SparseProjection<S>> SparseLinear<S, P> {
    pub fn new(projector: P, n_outputs: usize) -> Self {
        let n_features = projector.size();

        Self {
            projector: projector,
            weights: Array2::<f64>::zeros((n_features, n_outputs)),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, P: SparseProjection<S>> Function<S::Repr, f64> for SparseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> f64 {
        self.projector.project_sparse(input).fold(0.0f64,
                                                  |acc, i| acc + self.weights.column(0)[*i])
    }
}

impl<S: Space, P: SparseProjection<S>> Function<S::Repr, Vec<f64>> for SparseLinear<S, P> {
    fn evaluate(&self, input: &S::Repr) -> Vec<f64> {
        let indices = self.projector.project_sparse(input);

        (0..self.weights.cols()).map(|c| {
            indices.fold(0.0f64, |acc, i| acc + self.weights.column(c)[*i])
        }).collect()
    }
}

impl<S: Space, P: SparseProjection<S>> Parameterised<S::Repr, f64> for SparseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, error: f64) {
        let scaled_error = error / self.projector.sparsity() as f64;

        for i in self.projector.project_sparse(input).iter() {
            self.weights.column_mut(0)[*i] += scaled_error;
        }
    }
}

impl<S: Space, P: SparseProjection<S>> Parameterised<S::Repr, Vec<f64>> for SparseLinear<S, P> {
    fn update(&mut self, input: &S::Repr, errors: Vec<f64>) {
        for c in 0..self.weights.cols() {
            let scaled_error = errors[c] / self.projector.sparsity() as f64;

            for i in self.projector.project_sparse(input).iter() {
                self.weights.column_mut(c)[*i] += scaled_error;
            }
        }
    }
}

impl<S: Space, P: SparseProjection<S>> VFunction<S> for SparseLinear<S, P> {}

impl<S: Space, P: SparseProjection<S>> QFunction<S> for SparseLinear<S, P> {
    fn evaluate_action(&self, input: &S::Repr, action: usize) -> f64 {
        self.projector.project_sparse(input).fold(0.0f64,
                                                  |acc, i| acc + self.weights.column(action)[*i])
    }

    fn update_action(&mut self, input: &S::Repr, action: usize, error: f64) {
        let scaled_error = error / self.projector.sparsity() as f64;

        for i in self.projector.project_sparse(input).iter() {
            self.weights.column_mut(action)[*i] += scaled_error;
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate seahash;

    use super::*;
    use std::hash::BuildHasherDefault;
    use fa::projection::TileCoding;

    type SHBuilder = BuildHasherDefault<seahash::SeaHasher>;

    #[test]
    fn test_dense_update_eval() {
        let p = TileCoding::new(SHBuilder::default(), 4, 100);
        let mut f = DenseLinear::new(p.clone(), 1);

        let input = vec![5.0];

        f.update(&input, 50.0);
        let out: f64 = f.evaluate(&input);

        assert_eq!(out, 50.0);
    }

    #[test]
    fn test_dense_eval_phi() {
        let p = TileCoding::new(SHBuilder::default(), 4, 100);
        let f = DenseLinear::new(p.clone(), 1);

        let input = vec![5.0];

        let out: f64 = f.evaluate(&input);
        let out_alt_v: f64 = VFunction::evaluate_phi(&f, &p.project(&input));
        let out_alt_q: Vec<f64> = QFunction::evaluate_phi(&f, &p.project(&input));

        assert_eq!(out, out_alt_v);
        assert_eq!(vec![out], out_alt_q);
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fs;
use std::io;
use std::io::{Read,Write};
use std::mem;

use fat::RootEntry;
use fat::BIOSParam;

// TODO: Kill me
const SECTORS_PER_DATA_AREA: usize = 2847;

// Always the same
const SECTORS_PER_ROOT: usize = 14;
const BYTES_PER_ROOT_ENTRY: usize = 32;

#[test]
fn test_root_entry_size() {
    assert_eq!(mem::size_of::<RootEntry>(), BYTES_PER_ROOT_ENTRY);
}

#[derive(Debug)]
pub struct Image {
    boot_sector: Vec<u8>,
    fat_1: Vec<u8>,
    fat_2: Vec<u8>,
    root_dir: Vec<u8>,
    data_area: Vec<u8>,
    bpb_data: BIOSParam,
}

#[allow(dead_code)]
impl Image {
    /// Create a new blank FAT Image from a defined BPB
    fn new(bpb: BIOSParam) -> Image {
        let bytes_per_fat = (bpb.sectors_per_fat * bpb.bytes_per_sector as u32) as usize;
        let bytes_per_root = SECTORS_PER_ROOT * bpb.bytes_per_sector as usize;
        let data_offset = bpb.bytes_per_sector as usize + (bytes_per_fat as usize * 2) + bytes_per_root as usize;
        let bytes_per_data_area = bpb.len() - data_offset;
        Image {
            boot_sector: vec![0; bpb.bytes_per_sector as usize],
            fat_1: vec![0; bytes_per_fat],
            fat_2: vec![0; bytes_per_fat],
            root_dir: vec![0; bytes_per_root],
            data_area: vec![0; bytes_per_data_area],
            bpb_data: bpb,
        }
    }

    /// Create a new FAT Image from the specified file.
    pub fn from(image_fn: String)
        -> Result<Image, Box<error::Error>>
    {
        let bpb = BIOSParam::from(image_fn.clone())?;
        let mut file = fs::File::open(image_fn)?;
        let mut image = Image::new(bpb);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Save the FAT filesystem image to the specified file.
    pub fn save(&self, image_fn: String)
        -> Result<(), io::Error>
    {
        let mut file = fs::File::create(image_fn)?;

        try!(file.write_all(&self.boot_sector));
        try!(file.write_all(&self.fat_1));
        try!(file.write_all(&self.fat_2));
        try!(file.write_all(&self.root_dir));
        try!(file.write_all(&self.data_area));

        Ok(())
    }

    /// Extract the BIOS Parameter Block (BPB) from the FAT filesystem.
    pub fn bios_parameter(&self) -> BIOSParam {
        self.bpb_data.clone()
    }

    /// FAT sector size in bytes.
    pub fn sector_size(&self) -> usize {
        self.bpb_data.bytes_per_sector as usize
    }

    // TODO: Make this an iterator
    pub fn root_entries(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .filter(|entry| { entry.filename[0] != 0xe5 })
            .take_while(|entry| { entry.filename[0] != 0 })
            .collect::<Vec<RootEntry>>()
    }

    /// Get the RootEntry for the specified file within the Image.
    pub fn get_file_entry(&self, filename: String)
        -> Result<RootEntry, Box<error::Error>>
    {
        let entries = self.root_entries();
        for entry in entries {
            let entry_name: String;
            match entry.filename() {
                Ok(name) => entry_name = name,
                Err(_) => continue,
            }

            if entry_name.to_lowercase() == filename.to_lowercase() {
                return Ok(entry);
            }
        }

        Err(From::from(format!("file {} not found", filename)))
    }

    /// Create a new RootEntry within the Image with the specified filename.
    pub fn create_file_entry(&self, filename: String)
        -> Result<(RootEntry, u16), Box<error::Error>>
    {
        for (index, e) in self.root_entries().iter().enumerate() {
            if !e.is_free() { continue; }

            let mut entry = RootEntry::new();
            try!(entry.set_filename(filename));
            return Ok((entry.clone(), index as u16));
        }

        Err(From::from("no free entries"))
    }

    pub fn save_file_entry(&mut self, entry: RootEntry, index: u16)
        -> Result<(), Box<error::Error>>
    {
        let entry_bytes: [u8; BYTES_PER_ROOT_ENTRY];
        unsafe { entry_bytes = mem::transmute(entry); }

        self.root_dir[
            index as usize * BYTES_PER_ROOT_ENTRY ..
            (index as usize + 1) * BYTES_PER_ROOT_ENTRY
        ].clone_from_slice(&entry_bytes[..]);
        Ok(())
    }

    pub fn fat_entries<'a>(&'a self)
        -> Box<Iterator<Item=(usize, u16)> + 'a>
    {
        Box::new(
            self.fat_1
            .windows(2)
            .enumerate()
            .filter_map(|(i, w)|
                if i % 3 == 2 {
                    None
                } else {
                    let val = if i % 3 == 0 {
                        ((w[1] as u16 & 0xf) << 8) | w[0] as u16
                    } else {
                        (w[1] as u16 & 0xf0) | ((w[1] as u16) << 4)
                    };
                    Some((i, val))
                }
            )
        )
    }

    pub fn get_fat_entry(&self, cluster_num: u16) -> u16 {
        let offset: usize = cluster_num as usize * 3 / 2;
        let byte_1: u16 = self.fat_1[offset] as u16;
        let byte_2: u16 = self.fat_1[offset + 1] as u16;

        if cluster_num % 2 == 0 { byte_1 | ((byte_2 & 0x0f) << 8) }
        else                    { (byte_1 >> 4) | (byte_2 << 4) }
    }

    pub fn get_free_fat_entry(&self) -> Option<usize> {
        self.fat_entries()
            .filter(|&(_, e)| e == 0)
            .map(|(i, _)| i + 2)
            .nth(0)
    }

    pub fn write_data_sector(&mut self, sector: usize, data: &[u8])
        -> Result<(), Box<error::Error>>
    {
        let sector = sector - 2;
        if sector >= SECTORS_PER_DATA_AREA {
            return Err(From::from(format!("sector {} too high to write to", sector)))
        }

        let mut target_slice = &mut self.data_area[
            self.bpb_data.bytes_per_sector as usize * sector ..
            self.bpb_data.bytes_per_sector as usize * (sector + 1)
        ];

        target_slice.copy_from_slice(data);
        Ok(())
    }
}
<commit_msg>fat/image: Extend boot_sector based on reserved_sectors<commit_after>use std::error;
use std::fs;
use std::io;
use std::io::{Read,Write};
use std::mem;

use fat::RootEntry;
use fat::BIOSParam;

// TODO: Kill me
const SECTORS_PER_DATA_AREA: usize = 2847;

// Always the same
const SECTORS_PER_ROOT: usize = 14;
const BYTES_PER_ROOT_ENTRY: usize = 32;

#[test]
fn test_root_entry_size() {
    assert_eq!(mem::size_of::<RootEntry>(), BYTES_PER_ROOT_ENTRY);
}

#[derive(Debug)]
pub struct Image {
    boot_sector: Vec<u8>,
    fat_1: Vec<u8>,
    fat_2: Vec<u8>,
    root_dir: Vec<u8>,
    data_area: Vec<u8>,
    bpb_data: BIOSParam,
}

#[allow(dead_code)]
impl Image {
    /// Create a new blank FAT Image from a defined BPB
    fn new(bpb: BIOSParam) -> Image {
        let boot_sector_size = bpb.bytes_per_sector as usize * bpb.reserved_sectors as usize;
        let bytes_per_fat = (bpb.sectors_per_fat * bpb.bytes_per_sector as u32) as usize;
        let bytes_per_root = SECTORS_PER_ROOT * bpb.bytes_per_sector as usize;
        let data_offset = bpb.bytes_per_sector as usize + (bytes_per_fat as usize * 2) + bytes_per_root as usize;
        let bytes_per_data_area = bpb.len() - data_offset;
        Image {
            boot_sector: vec![0; boot_sector_size],
            fat_1: vec![0; bytes_per_fat],
            fat_2: vec![0; bytes_per_fat],
            root_dir: vec![0; bytes_per_root],
            data_area: vec![0; bytes_per_data_area],
            bpb_data: bpb,
        }
    }

    /// Create a new FAT Image from the specified file.
    pub fn from(image_fn: String)
        -> Result<Image, Box<error::Error>>
    {
        let bpb = BIOSParam::from(image_fn.clone())?;
        let mut file = fs::File::open(image_fn)?;
        let mut image = Image::new(bpb);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Save the FAT filesystem image to the specified file.
    pub fn save(&self, image_fn: String)
        -> Result<(), io::Error>
    {
        let mut file = fs::File::create(image_fn)?;

        try!(file.write_all(&self.boot_sector));
        try!(file.write_all(&self.fat_1));
        try!(file.write_all(&self.fat_2));
        try!(file.write_all(&self.root_dir));
        try!(file.write_all(&self.data_area));

        Ok(())
    }

    /// Extract the BIOS Parameter Block (BPB) from the FAT filesystem.
    pub fn bios_parameter(&self) -> BIOSParam {
        self.bpb_data.clone()
    }

    /// FAT sector size in bytes.
    pub fn sector_size(&self) -> usize {
        self.bpb_data.bytes_per_sector as usize
    }

    // TODO: Make this an iterator
    pub fn root_entries(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .filter(|entry| { entry.filename[0] != 0xe5 })
            .take_while(|entry| { entry.filename[0] != 0 })
            .collect::<Vec<RootEntry>>()
    }

    /// Get the RootEntry for the specified file within the Image.
    pub fn get_file_entry(&self, filename: String)
        -> Result<RootEntry, Box<error::Error>>
    {
        let entries = self.root_entries();
        for entry in entries {
            let entry_name: String;
            match entry.filename() {
                Ok(name) => entry_name = name,
                Err(_) => continue,
            }

            if entry_name.to_lowercase() == filename.to_lowercase() {
                return Ok(entry);
            }
        }

        Err(From::from(format!("file {} not found", filename)))
    }

    /// Create a new RootEntry within the Image with the specified filename.
    pub fn create_file_entry(&self, filename: String)
        -> Result<(RootEntry, u16), Box<error::Error>>
    {
        for (index, e) in self.root_entries().iter().enumerate() {
            if !e.is_free() { continue; }

            let mut entry = RootEntry::new();
            try!(entry.set_filename(filename));
            return Ok((entry.clone(), index as u16));
        }

        Err(From::from("no free entries"))
    }

    pub fn save_file_entry(&mut self, entry: RootEntry, index: u16)
        -> Result<(), Box<error::Error>>
    {
        let entry_bytes: [u8; BYTES_PER_ROOT_ENTRY];
        unsafe { entry_bytes = mem::transmute(entry); }

        self.root_dir[
            index as usize * BYTES_PER_ROOT_ENTRY ..
            (index as usize + 1) * BYTES_PER_ROOT_ENTRY
        ].clone_from_slice(&entry_bytes[..]);
        Ok(())
    }

    pub fn fat_entries<'a>(&'a self)
        -> Box<Iterator<Item=(usize, u16)> + 'a>
    {
        Box::new(
            self.fat_1
            .windows(2)
            .enumerate()
            .filter_map(|(i, w)|
                if i % 3 == 2 {
                    None
                } else {
                    let val = if i % 3 == 0 {
                        ((w[1] as u16 & 0xf) << 8) | w[0] as u16
                    } else {
                        (w[1] as u16 & 0xf0) | ((w[1] as u16) << 4)
                    };
                    Some((i, val))
                }
            )
        )
    }

    pub fn get_fat_entry(&self, cluster_num: u16) -> u16 {
        let offset: usize = cluster_num as usize * 3 / 2;
        let byte_1: u16 = self.fat_1[offset] as u16;
        let byte_2: u16 = self.fat_1[offset + 1] as u16;

        if cluster_num % 2 == 0 { byte_1 | ((byte_2 & 0x0f) << 8) }
        else                    { (byte_1 >> 4) | (byte_2 << 4) }
    }

    pub fn get_free_fat_entry(&self) -> Option<usize> {
        self.fat_entries()
            .filter(|&(_, e)| e == 0)
            .map(|(i, _)| i + 2)
            .nth(0)
    }

    pub fn write_data_sector(&mut self, sector: usize, data: &[u8])
        -> Result<(), Box<error::Error>>
    {
        let sector = sector - 2;
        if sector >= SECTORS_PER_DATA_AREA {
            return Err(From::from(format!("sector {} too high to write to", sector)))
        }

        let mut target_slice = &mut self.data_area[
            self.bpb_data.bytes_per_sector as usize * sector ..
            self.bpb_data.bytes_per_sector as usize * (sector + 1)
        ];

        target_slice.copy_from_slice(data);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use core::mem;

use super::int::Int;

pub mod conv;
pub mod add;
pub mod pow;
pub mod sub;

/// Trait for some basic operations on floats
pub trait Float: Sized + Copy {
    /// A uint of the same with as the float
    type Int: Int;

    /// The bitwidth of the float type
    const BITS: u32;

    /// The bitwidth of the significand
    const SIGNIFICAND_BITS: u32;

    /// The bitwidth of the exponent
    const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1;

    /// The maximum value of the exponent
    const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1;

    /// The exponent bias value
    const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1;

    /// A mask for the sign bit
    const SIGN_MASK: Self::Int;

    /// A mask for the significand
    const SIGNIFICAND_MASK: Self::Int;

    // The implicit bit of the float format
    const IMPLICIT_BIT: Self::Int;

    /// A mask for the exponent
    const EXPONENT_MASK: Self::Int;

    /// Returns `self` transmuted to `Self::Int`
    fn repr(self) -> Self::Int;

    #[cfg(test)]
    /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
    /// represented in multiple different ways. This method returns `true` if two NaNs are
    /// compared.
    fn eq_repr(self, rhs: Self) -> bool;

    /// Returns a `Self::Int` transmuted back to `Self`
    fn from_repr(a: Self::Int) -> Self;

    /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
    fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self;

    /// Returns (normalized exponent, normalized significand)
    fn normalize(significand: Self::Int) -> (i32, Self::Int);
}

// FIXME: Some of this can be removed if RFC Issue #1424 is resolved
//        https://github.com/rust-lang/rfcs/issues/1424
macro_rules! float_impl {
    ($ty:ident, $ity:ident, $bits:expr, $significand_bits:expr) => {
        impl Float for $ty {
            type Int = $ity;
            const BITS: u32 = $bits;
            const SIGNIFICAND_BITS: u32 = $significand_bits;

            const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
            const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1;
            const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
            const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);

            fn repr(self) -> Self::Int {
                unsafe { mem::transmute(self) }
            }
            #[cfg(test)]
            fn eq_repr(self, rhs: Self) -> bool {
                if self.is_nan() && rhs.is_nan() {
                    true
                } else {
                    self.repr() == rhs.repr()
                }
            }
            fn from_repr(a: Self::Int) -> Self {
                unsafe { mem::transmute(a) }
            }
            fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
                Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) |
                    ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) |
                    (significand & Self::SIGNIFICAND_MASK))
            }
            fn normalize(significand: Self::Int) -> (i32, Self::Int) {
                let shift = significand.leading_zeros()
                    .wrapping_sub((Self::Int::ONE << Self::SIGNIFICAND_BITS).leading_zeros());
                (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
            }
        }
    }
}

float_impl!(f32, u32, 32, 23);
float_impl!(f64, u64, 64, 52);
<commit_msg>Extend the Float trait by some constants and supertraits<commit_after>use core::mem;
use core::ops;

use super::int::Int;

pub mod conv;
pub mod add;
pub mod pow;
pub mod sub;

/// Trait for some basic operations on floats
pub trait Float:
    Copy +
    PartialEq +
    PartialOrd +
    ops::AddAssign +
    ops::MulAssign +
    ops::Add<Output = Self> +
    ops::Sub<Output = Self> +
    ops::Div<Output = Self> +
    ops::Rem<Output = Self> +
{
    /// A uint of the same with as the float
    type Int: Int;

    const ZERO: Self;
    const ONE: Self;

    /// The bitwidth of the float type
    const BITS: u32;

    /// The bitwidth of the significand
    const SIGNIFICAND_BITS: u32;

    /// The bitwidth of the exponent
    const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1;

    /// The maximum value of the exponent
    const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1;

    /// The exponent bias value
    const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1;

    /// A mask for the sign bit
    const SIGN_MASK: Self::Int;

    /// A mask for the significand
    const SIGNIFICAND_MASK: Self::Int;

    // The implicit bit of the float format
    const IMPLICIT_BIT: Self::Int;

    /// A mask for the exponent
    const EXPONENT_MASK: Self::Int;

    /// Returns `self` transmuted to `Self::Int`
    fn repr(self) -> Self::Int;

    #[cfg(test)]
    /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
    /// represented in multiple different ways. This method returns `true` if two NaNs are
    /// compared.
    fn eq_repr(self, rhs: Self) -> bool;

    /// Returns a `Self::Int` transmuted back to `Self`
    fn from_repr(a: Self::Int) -> Self;

    /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
    fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self;

    /// Returns (normalized exponent, normalized significand)
    fn normalize(significand: Self::Int) -> (i32, Self::Int);
}

// FIXME: Some of this can be removed if RFC Issue #1424 is resolved
//        https://github.com/rust-lang/rfcs/issues/1424
macro_rules! float_impl {
    ($ty:ident, $ity:ident, $bits:expr, $significand_bits:expr) => {
        impl Float for $ty {
            type Int = $ity;
            const ZERO: Self = 0.0;
            const ONE: Self = 1.0;

            const BITS: u32 = $bits;
            const SIGNIFICAND_BITS: u32 = $significand_bits;

            const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
            const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1;
            const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
            const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);

            fn repr(self) -> Self::Int {
                unsafe { mem::transmute(self) }
            }
            #[cfg(test)]
            fn eq_repr(self, rhs: Self) -> bool {
                if self.is_nan() && rhs.is_nan() {
                    true
                } else {
                    self.repr() == rhs.repr()
                }
            }
            fn from_repr(a: Self::Int) -> Self {
                unsafe { mem::transmute(a) }
            }
            fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
                Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) |
                    ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) |
                    (significand & Self::SIGNIFICAND_MASK))
            }
            fn normalize(significand: Self::Int) -> (i32, Self::Int) {
                let shift = significand.leading_zeros()
                    .wrapping_sub((Self::Int::ONE << Self::SIGNIFICAND_BITS).leading_zeros());
                (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int)
            }
        }
    }
}

float_impl!(f32, u32, 32, 23);
float_impl!(f64, u64, 64, 52);
<|endoftext|>


<commit_before>//*****************************
// Minetest/Freemine data model

extern crate classreader;
extern crate rusqlite;
extern crate flate2;
extern crate multiarray;

use self::flate2::Compression;
use self::flate2::write::ZlibEncoder;
use self::rusqlite::Connection;
use self::multiarray::{MultiArray, Dim3};
use codecity::Package;

pub fn write_to_freeminer(path: &String, root: &Package) {
	let voxels = build_array(root);
    // Open DB connection
    let conn = Connection::open(path).unwrap();
	output_sql(&conn, root, &voxels);
    conn.close().unwrap();
}

fn build_array(root: &Package) -> MultiArray<u8, Dim3> {
	use self::multiarray::*;
	let height = root.height();
	let (width, depth) = root.size();
	// u8 for the future use, when we'll have more than just non-emptiness to track
	let mut voxels = Array3D::new([width as usize, depth as usize, height as usize], 0 as u8);
	fill_from_package(root, &mut voxels, 0);
	return voxels;
}

fn fill_from_package(pkg: &Package, voxels: &mut MultiArray<u8, Dim3>, oz: usize) {
	let (w, d) = pkg.size();
	let (ox, oy) = pkg.position();
	// Fill the package itself
	for x in ox .. ox + w {
		for y in oy .. oy + d {
			voxels[[x as usize, y as usize, oz]] = 1u8;
		}
	}
	// Fill the subpackages
	for p in &pkg.packages() {
		fill_from_package(p, voxels, oz + 1);
	}
	// Fill the buildings
	for b in pkg.buildings() {
		let (px, py) = b.position();
		let (bw, bd) = b.size();
		let h = b.height() as usize;
		for x in px .. px + bw {
			for y in py .. py + bd {
				for z in oz + 1 .. oz + 1 + h {
					voxels[[x as usize, y as usize, z]] = 1;
				}
			}
		}
	}

}

struct NodeBlob {
    param0: [u16; 4096],
    param1: [u8; 4096],
    param2: [u8; 4096]
}

// blob to bytes...
fn to_bytes(blob: &NodeBlob) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::new();
    for i in 0..4096 {
        let p = blob.param0[i];
        vec.push((p >> 8) as u8);
        vec.push(p as u8);
    }
    for i in 0..4096 {
        vec.push(blob.param1[i]);
    }
    for i in 0..4096 {
        vec.push(blob.param2[i]);
    }
    vec
}

// Write one variable to the vector
fn push_variable(vec: &mut Vec<u8>, name: &str, value: &str) {
    let klen = name.len() as u16;
    vec.push((klen >> 8) as u8);
    vec.push(klen as u8);
    for b in name.bytes() {
        vec.push(b);
    }
    let vlen = value.len() as u32;
    vec.push((vlen >> 24) as u8);
    vec.push((vlen >> 16) as u8);
    vec.push((vlen >> 8) as u8);
    vec.push(vlen as u8);
    for b in value.bytes() {
        vec.push(b);
    }
}

// Encode stuff we want to have in meta (signs mostly).
fn meta_bytes(text: &str, pos: u16) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::new();
    vec.push(0x01); // version
    vec.push(0x00); // count byte 0
    vec.push(0x01); // count byte 1
    vec.push((pos >> 8) as u8); // position byte 0
    vec.push(pos as u8); // position byte 1
    vec.push(0x00); // num_vars byte 0
    vec.push(0x00); // num_vars byte 1
    vec.push(0x00); // num_vars byte 2
    vec.push(0x03); // num_vars byte 3
    push_variable(&mut vec, "formspec", "field[text;;${text}]");
    push_variable(&mut vec, "infotext", text);
    push_variable(&mut vec, "text", text);
    // EndInventory
    vec.append(&mut vec![0x45 as u8, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x0a]);
    vec
}

// bytes to hex. There should be a better way for sure.
fn hex(v: &Vec<u8>) -> String {
    use std::fmt::Write;
    let mut s = String::new();
    for &byte in v {
        write!(&mut s, "{:02X}", byte).unwrap();
    }
    s
}

// blob position in the world
// Note that in freeminer x and z are horizontals and y (!) is the vertical (grows up)
fn compute_position(x: usize, y: usize, z: usize) -> usize {
    x + 4096 * (y + 4096 * z)
}

// node position inside the blob
fn node_pos(x: usize, y: usize, z: usize) -> usize {
    (z * 16 + y) * 16 + x
}

fn output_blob(blob: &NodeBlob, conn: &Connection, pos: usize, sign: &str, sign_pos: usize) {
    use std::io::prelude::*;
    let blob_encoded = to_bytes(blob);
    let mut e = ZlibEncoder::new(Vec::new(), Compression::Default);
    e.write(&blob_encoded).unwrap();
    let blob_compressed = e.finish().unwrap();
    let blob_hex = hex(&blob_compressed);

    let meta_encoded = meta_bytes(sign, sign_pos as u16);
    let mut e1 = ZlibEncoder::new(Vec::new(), Compression::Default);
    e1.write(&meta_encoded).unwrap();
    let meta_compressed = e1.finish().unwrap();
    let meta_hex = hex(&meta_compressed);
    let block = format!("19060202{}{}0000000000024900000A0000000D64656661756C743A73746F6E650001000C64656661756C743A73616E640002000C64656661756C743A64697274000300036169720004001064656661756C743A646972745F6472790005001764656661756C743A646972745F776974685F67726173730006001564656661756C743A77617465725F666C6F77696E670007000F64656661756C743A67726173735F310008001164656661756C743A7369676E5F77616C6C0009000E64656661756C743A67726176656C0A0000", blob_hex, meta_hex);
    conn.execute(&format!("DELETE FROM blocks WHERE pos = {};", pos), &[]).unwrap();
    conn.execute(&format!("INSERT INTO blocks VALUES({},X'{}');", pos, block), &[]).unwrap();
}

static BLOB_DIM: usize = 16;

fn voxels_to_blob(voxels: &MultiArray<u8, Dim3>, sx: usize, sy: usize, sz: usize) -> NodeBlob {
    let mut parr = [0x3 as u16; 4096];
    let mut parr2 = [0x0 as u8; 4096];
    let parr3 = [0x0 as u8; 4096];
    for x in sx .. sx + BLOB_DIM {
        for y in sy .. sy + BLOB_DIM {
            for z in sz .. sz + BLOB_DIM {
                if x + 1 < voxels.extents()[0] &&
                   y + 1 < voxels.extents()[1] &&
                   z + 1 < voxels.extents()[2] &&
                   voxels[[x,y,z]] == 1u8 {
                    let i = node_pos(x, y, z);
                    parr[i] = 0x0;
                    parr2[i] = 0xf;
                }
            }
        }
    }
    return NodeBlob {
        param0: parr,
        param1: parr2,
        param2: parr3
    };
}

fn output_sql(conn: &Connection, package: &Package, voxels: &MultiArray<u8, Dim3>) {
    // First, determine the dimensions
    let dimx = voxels.extents()[0] / BLOB_DIM + 1;
    let dimy = voxels.extents()[1] / BLOB_DIM + 1;
    let dimz = voxels.extents()[2] / BLOB_DIM + 1;

    for x in 0 .. dimx {
        for y in 0 .. dimy {
            // create base
            let blob = NodeBlob {
                param0: [0xe; 4096],
                param1: [0; 4096],
                param2: [0; 4096]
            };
            output_blob(&blob, conn, compute_position(x, 1, y), "", node_pos(0, 0, 0));
            for z in 0 .. dimz {
                // create our class
                let blob2 = voxels_to_blob(voxels, x * BLOB_DIM, y * BLOB_DIM, z * BLOB_DIM);
                output_blob(&blob2, conn, compute_position(x, 2 + z, y), "", node_pos(0, 0, 0));
            }
            // Create air on top of our last block
            let blob3 = NodeBlob {
                param0: [0x3; 4096],
                param1: [0; 4096],
                param2: [0; 4096]
            };
            output_blob(&blob3, conn, compute_position(x, 2 + dimz, y), "", node_pos(0, 0, 0));
            output_blob(&blob3, conn, compute_position(x, 3 + dimz, y), "", node_pos(0, 0, 0));
        }
    }
    /*
    // Let's place a sign
    let sign_pos = node_pos(4, height, 4);
    parr[sign_pos] = 0x8;
    parr2[sign_pos] = 0x0f;
    parr3[sign_pos] = 0x1;
    let blob2 = NodeBlob {
        param0: parr,
        param1: parr2,
        param2: parr3
    };
    // output_blob(&blob2, conn, compute_position(0 + offset * 2, 2, 0), &get_class_name(&class), sign_pos);
    output_blob(&blob2, conn, compute_position(0, 2, 0), &package.name(), sign_pos);
    */
}

//*****************************
// Unit tests
<commit_msg>Fixing it now<commit_after>//*****************************
// Minetest/Freemine data model

extern crate classreader;
extern crate rusqlite;
extern crate flate2;
extern crate multiarray;

use self::flate2::Compression;
use self::flate2::write::ZlibEncoder;
use self::rusqlite::Connection;
use self::multiarray::{MultiArray, Dim3};
use codecity::Package;

pub fn write_to_freeminer(path: &String, root: &Package) {
	let voxels = build_array(root);
    // Open DB connection
    let conn = Connection::open(path).unwrap();
	output_sql(&conn, root, &voxels);
    conn.close().unwrap();
}

fn build_array(root: &Package) -> MultiArray<u8, Dim3> {
	use self::multiarray::*;
	let height = root.height();
	let (width, depth) = root.size();
	// u8 for the future use, when we'll have more than just non-emptiness to track
	let mut voxels = Array3D::new([width as usize, depth as usize, height as usize], 0 as u8);
	fill_from_package(root, &mut voxels, 0);
	return voxels;
}

fn fill_from_package(pkg: &Package, voxels: &mut MultiArray<u8, Dim3>, oz: usize) {
	let (w, d) = pkg.size();
	let (ox, oy) = pkg.position();
	// Fill the package itself
	for x in ox .. ox + w {
		for y in oy .. oy + d {
			voxels[[x as usize, y as usize, oz]] = 1u8;
		}
	}
	// Fill the subpackages
	for p in &pkg.packages() {
		fill_from_package(p, voxels, oz + 1);
	}
	// Fill the buildings
	for b in pkg.buildings() {
		let (px, py) = b.position();
		let (bw, bd) = b.size();
		let h = b.height() as usize;
		for x in px .. px + bw {
			for y in py .. py + bd {
				for z in oz + 1 .. oz + 1 + h {
					voxels[[x as usize, y as usize, z]] = 1;
				}
			}
		}
	}

}

struct NodeBlob {
    param0: [u16; 4096],
    param1: [u8; 4096],
    param2: [u8; 4096]
}

// blob to bytes...
fn to_bytes(blob: &NodeBlob) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::new();
    for i in 0..4096 {
        let p = blob.param0[i];
        vec.push((p >> 8) as u8);
        vec.push(p as u8);
    }
    for i in 0..4096 {
        vec.push(blob.param1[i]);
    }
    for i in 0..4096 {
        vec.push(blob.param2[i]);
    }
    vec
}

// Write one variable to the vector
fn push_variable(vec: &mut Vec<u8>, name: &str, value: &str) {
    let klen = name.len() as u16;
    vec.push((klen >> 8) as u8);
    vec.push(klen as u8);
    for b in name.bytes() {
        vec.push(b);
    }
    let vlen = value.len() as u32;
    vec.push((vlen >> 24) as u8);
    vec.push((vlen >> 16) as u8);
    vec.push((vlen >> 8) as u8);
    vec.push(vlen as u8);
    for b in value.bytes() {
        vec.push(b);
    }
}

// Encode stuff we want to have in meta (signs mostly).
fn meta_bytes(text: &str, pos: u16) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::new();
    vec.push(0x01); // version
    vec.push(0x00); // count byte 0
    vec.push(0x01); // count byte 1
    vec.push((pos >> 8) as u8); // position byte 0
    vec.push(pos as u8); // position byte 1
    vec.push(0x00); // num_vars byte 0
    vec.push(0x00); // num_vars byte 1
    vec.push(0x00); // num_vars byte 2
    vec.push(0x03); // num_vars byte 3
    push_variable(&mut vec, "formspec", "field[text;;${text}]");
    push_variable(&mut vec, "infotext", text);
    push_variable(&mut vec, "text", text);
    // EndInventory
    vec.append(&mut vec![0x45 as u8, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x0a]);
    vec
}

// bytes to hex. There should be a better way for sure.
fn hex(v: &Vec<u8>) -> String {
    use std::fmt::Write;
    let mut s = String::new();
    for &byte in v {
        write!(&mut s, "{:02X}", byte).unwrap();
    }
    s
}

// blob position in the world
// Note that in freeminer x and z are horizontals and y (!) is the vertical (grows up)
fn compute_position(x: usize, y: usize, z: usize) -> usize {
    x + 4096 * (y + 4096 * z)
}

// node position inside the blob
fn node_pos(x: usize, y: usize, z: usize) -> usize {
    (z * 16 + y) * 16 + x
}

fn output_blob(blob: &NodeBlob, conn: &Connection, pos: usize, sign: &str, sign_pos: usize) {
    use std::io::prelude::*;
    let blob_encoded = to_bytes(blob);
    let mut e = ZlibEncoder::new(Vec::new(), Compression::Default);
    e.write(&blob_encoded).unwrap();
    let blob_compressed = e.finish().unwrap();
    let blob_hex = hex(&blob_compressed);

    let meta_encoded = meta_bytes(sign, sign_pos as u16);
    let mut e1 = ZlibEncoder::new(Vec::new(), Compression::Default);
    e1.write(&meta_encoded).unwrap();
    let meta_compressed = e1.finish().unwrap();
    let meta_hex = hex(&meta_compressed);
    let block = format!("19060202{}{}0000000000024900000A0000000D64656661756C743A73746F6E650001000C64656661756C743A73616E640002000C64656661756C743A64697274000300036169720004001064656661756C743A646972745F6472790005001764656661756C743A646972745F776974685F67726173730006001564656661756C743A77617465725F666C6F77696E670007000F64656661756C743A67726173735F310008001164656661756C743A7369676E5F77616C6C0009000E64656661756C743A67726176656C0A0000", blob_hex, meta_hex);
    conn.execute(&format!("DELETE FROM blocks WHERE pos = {};", pos), &[]).unwrap();
    conn.execute(&format!("INSERT INTO blocks VALUES({},X'{}');", pos, block), &[]).unwrap();
}

static BLOB_DIM: usize = 16;

fn voxels_to_blob(voxels: &MultiArray<u8, Dim3>, sx: usize, sy: usize, sz: usize) -> NodeBlob {
    let mut parr = [0x3 as u16; 4096];
    let mut parr2 = [0x0 as u8; 4096];
    let parr3 = [0x0 as u8; 4096];
    for x in sx .. sx + BLOB_DIM {
        for y in sy .. sy + BLOB_DIM {
            for z in sz .. sz + BLOB_DIM {
                if x + 1 < voxels.extents()[0] &&
                   y + 1 < voxels.extents()[1] &&
                   z + 1 < voxels.extents()[2] &&
                   voxels[[x,y,z]] == 1u8 {
                    let i = node_pos(x - sx, z - sz, y - sy);
                    parr[i] = 0x0;
                    parr2[i] = 0xf;
                }
            }
        }
    }
    return NodeBlob {
        param0: parr,
        param1: parr2,
        param2: parr3
    };
}

fn output_sql(conn: &Connection, package: &Package, voxels: &MultiArray<u8, Dim3>) {
    // First, determine the dimensions
    let dimx = voxels.extents()[0] / BLOB_DIM + 1;
    let dimy = voxels.extents()[1] / BLOB_DIM + 1;
    let dimz = voxels.extents()[2] / BLOB_DIM + 1;
    println!("Total map dimensions: {}x{}x{} blobs", dimx, dimy, dimz);

    for x in 0 .. dimx {
        for y in 0 .. dimy {
            // create base
            let blob = NodeBlob {
                param0: [0xe; 4096],
                param1: [0; 4096],
                param2: [0; 4096]
            };
            output_blob(&blob, conn, compute_position(x, 1, y), "", node_pos(0, 0, 0));
            for z in 0 .. dimz {
                println!("Working on a blob: {}x{}x{}", x, y, z);
                // create our class
                let blob2 = voxels_to_blob(voxels, x * BLOB_DIM, y * BLOB_DIM, z * BLOB_DIM);
                output_blob(&blob2, conn, compute_position(x, 2 + z, y), "", node_pos(0, 0, 0));
            }
            // Create air on top of our last block
            let blob3 = NodeBlob {
                param0: [0x3; 4096],
                param1: [0; 4096],
                param2: [0; 4096]
            };
            output_blob(&blob3, conn, compute_position(x, 2 + dimz, y), "", node_pos(0, 0, 0));
            output_blob(&blob3, conn, compute_position(x, 3 + dimz, y), "", node_pos(0, 0, 0));
        }
    }
    /*
    // Let's place a sign
    let sign_pos = node_pos(4, height, 4);
    parr[sign_pos] = 0x8;
    parr2[sign_pos] = 0x0f;
    parr3[sign_pos] = 0x1;
    let blob2 = NodeBlob {
        param0: parr,
        param1: parr2,
        param2: parr3
    };
    // output_blob(&blob2, conn, compute_position(0 + offset * 2, 2, 0), &get_class_name(&class), sign_pos);
    output_blob(&blob2, conn, compute_position(0, 2, 0), &package.name(), sign_pos);
    */
}

//*****************************
// Unit tests
<|endoftext|>