<commit_before>use crate::parsing::ParsingContext;
use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{
    cmp,
    io::{self, IoSlice, IoSliceMut},
};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
    available_data: usize,
}

// The bool is true when the checkpoint is to go backwards, false for forward
pub(crate) struct Checkpoint(usize, bool);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
            available_data: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end, true)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        if checkpoint.1 {
            if self.end > checkpoint.0 {
                self.available_data -= self.end - checkpoint.0;
            } else {
                self.available_data -= self.end + (self.capacity - checkpoint.0);
            }
        } else {
            if self.end > checkpoint.0 {
                self.available_data += (self.capacity - self.end) + checkpoint.0;
            } else {
                self.available_data += checkpoint.0 - self.end;
            }
        }
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        let old_capacity = self.capacity;

        self.memory.resize(new_size, 0);
        self.capacity = new_size;

        if self.end < self.position {
            // FIXME: make sure there's enough room
            let (old, new) = self.memory.split_at_mut(old_capacity);
            new[..].copy_from_slice(&old[..self.end]);
            self.end += old_capacity;
        }

        true
    }

    pub(crate) fn available_data(&self) -> usize {
        self.available_data
    }

    fn available_space(&self) -> usize {
        self.capacity - self.available_data
    }

    pub(crate) fn consume(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        self.position %= self.capacity;
        self.available_data -= cnt;
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        self.end %= self.capacity;
        self.available_data += cnt;
        cnt
    }

    pub(crate) fn write_to<T: io::Write>(&self, writer: &mut T) -> io::Result<usize> {
        if self.available_data() == 0 {
            Ok(0)
        } else {
            if self.end > self.position {
                writer.write(&self.memory[self.position..self.end])
            } else {
                writer.write_vectored(&[
                    IoSlice::new(&self.memory[self.position..]),
                    IoSlice::new(&self.memory[..self.end]),
                ])
            }
        }
    }

    pub(crate) fn read_from<T: io::Read>(&mut self, reader: &mut T) -> io::Result<usize> {
        if self.available_space() == 0 {
            Ok(0)
        } else {
            if self.end >= self.position {
                let (start, end) = self.memory.split_at_mut(self.end);
                reader.read_vectored(
                    &mut [
                        IoSliceMut::new(&mut end[..]),
                        IoSliceMut::new(&mut start[..self.position]),
                    ][..],
                )
            } else {
                reader.read(&mut self.memory[self.end..self.position])
            }
        }
    }

    pub(crate) fn offset(&self, buf: ParsingContext<'_>) -> usize {
        let bufptr = buf.as_ptr() as usize;
        if self.end >= self.position {
            let data = &self.memory[self.position..self.end];
            let dataptr = data.as_ptr() as usize;
            bufptr - dataptr
        } else {
            let data = &self.memory[self.position..];
            let dataptr = data.as_ptr() as usize;
            if dataptr < bufptr {
                bufptr - dataptr
            } else {
                let data = &self.memory[..self.end];
                let dataptr = data.as_ptr() as usize;
                bufptr + self.capacity - self.position - dataptr
            }
        }
    }

    pub(crate) fn parsing_context(&self) -> ParsingContext<'_> {
        if self.available_data() == 0 {
            self.memory[self.end..].into()
        } else {
            if self.end > self.position {
                self.memory[self.position..self.end].into()
            } else {
                [&self.memory[self.position..], &self.memory[..self.end]].into()
            }
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = if self.available_space() == 0 {
            0
        } else {
            if self.end >= self.position {
                let mut space = &mut self.memory[self.end..];
                let mut amt = space.write(data)?;
                if amt == self.capacity - self.end {
                    let mut space = &mut self.memory[..self.position];
                    amt += space.write(&data[amt..])?;
                }
                amt
            } else {
                let mut space = &mut self.memory[self.end..self.position];
                space.write(data)?
            }
        };
        self.fill(amt);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.checkpoint();
        s.write.fill(reserved);
        gen(s).and_then(|(s, tmp)| {
            let mut end = s.write.checkpoint();
            end.1 = false;
            s.write.rollback(start);
            before(s, tmp).and_then(|s| {
                s.write.rollback(end);
                Ok(s)
            })
        })
    }
}
<commit_msg>buffer: fix parsing context with no data to parse<commit_after>use crate::parsing::ParsingContext;
use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{
    cmp,
    io::{self, IoSlice, IoSliceMut},
};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
    available_data: usize,
}

// The bool is true when the checkpoint is to go backwards, false for forward
pub(crate) struct Checkpoint(usize, bool);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
            available_data: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end, true)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        if checkpoint.1 {
            if self.end > checkpoint.0 {
                self.available_data -= self.end - checkpoint.0;
            } else {
                self.available_data -= self.end + (self.capacity - checkpoint.0);
            }
        } else {
            if self.end > checkpoint.0 {
                self.available_data += (self.capacity - self.end) + checkpoint.0;
            } else {
                self.available_data += checkpoint.0 - self.end;
            }
        }
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        let old_capacity = self.capacity;

        self.memory.resize(new_size, 0);
        self.capacity = new_size;

        if self.end < self.position {
            // FIXME: make sure there's enough room
            let (old, new) = self.memory.split_at_mut(old_capacity);
            new[..].copy_from_slice(&old[..self.end]);
            self.end += old_capacity;
        }

        true
    }

    pub(crate) fn available_data(&self) -> usize {
        self.available_data
    }

    fn available_space(&self) -> usize {
        self.capacity - self.available_data
    }

    pub(crate) fn consume(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        self.position %= self.capacity;
        self.available_data -= cnt;
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        self.end %= self.capacity;
        self.available_data += cnt;
        cnt
    }

    pub(crate) fn write_to<T: io::Write>(&self, writer: &mut T) -> io::Result<usize> {
        if self.available_data() == 0 {
            Ok(0)
        } else {
            if self.end > self.position {
                writer.write(&self.memory[self.position..self.end])
            } else {
                writer.write_vectored(&[
                    IoSlice::new(&self.memory[self.position..]),
                    IoSlice::new(&self.memory[..self.end]),
                ])
            }
        }
    }

    pub(crate) fn read_from<T: io::Read>(&mut self, reader: &mut T) -> io::Result<usize> {
        if self.available_space() == 0 {
            Ok(0)
        } else {
            if self.end >= self.position {
                let (start, end) = self.memory.split_at_mut(self.end);
                reader.read_vectored(
                    &mut [
                        IoSliceMut::new(&mut end[..]),
                        IoSliceMut::new(&mut start[..self.position]),
                    ][..],
                )
            } else {
                reader.read(&mut self.memory[self.end..self.position])
            }
        }
    }

    pub(crate) fn offset(&self, buf: ParsingContext<'_>) -> usize {
        let bufptr = buf.as_ptr() as usize;
        if self.end >= self.position {
            let data = &self.memory[self.position..self.end];
            let dataptr = data.as_ptr() as usize;
            bufptr - dataptr
        } else {
            let data = &self.memory[self.position..];
            let dataptr = data.as_ptr() as usize;
            if dataptr < bufptr {
                bufptr - dataptr
            } else {
                let data = &self.memory[..self.end];
                let dataptr = data.as_ptr() as usize;
                bufptr + self.capacity - self.position - dataptr
            }
        }
    }

    pub(crate) fn parsing_context(&self) -> ParsingContext<'_> {
        if self.available_data() == 0 {
            self.memory[self.end..self.end].into()
        } else {
            if self.end > self.position {
                self.memory[self.position..self.end].into()
            } else {
                [&self.memory[self.position..], &self.memory[..self.end]].into()
            }
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = if self.available_space() == 0 {
            0
        } else {
            if self.end >= self.position {
                let mut space = &mut self.memory[self.end..];
                let mut amt = space.write(data)?;
                if amt == self.capacity - self.end {
                    let mut space = &mut self.memory[..self.position];
                    amt += space.write(&data[amt..])?;
                }
                amt
            } else {
                let mut space = &mut self.memory[self.end..self.position];
                space.write(data)?
            }
        };
        self.fill(amt);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.checkpoint();
        s.write.fill(reserved);
        gen(s).and_then(|(s, tmp)| {
            let mut end = s.write.checkpoint();
            end.1 = false;
            s.write.rollback(start);
            before(s, tmp).and_then(|s| {
                s.write.rollback(end);
                Ok(s)
            })
        })
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

extern crate proc_macro;
// extern crate syn;

// #[macro_use]
// extern crate quote;

use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn register(_: TokenStream, input: TokenStream) -> TokenStream {
    return input;
}<commit_msg>parse act<commit_after>#![feature(proc_macro)]

extern crate proc_macro;
extern crate syn;

#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

fn output_struct(name: &syn::Ident) -> quote::Tokens {
    quote! {
        struct #name (u8);
        impl #name {
            pub fn get_bit() {

            }
        }
    }
}

#[derive(Debug)]
enum BitField {
    Single(u8),
    Range(std::ops::Range<u8>)
}

#[proc_macro_attribute]
pub fn register(_: TokenStream, input: TokenStream) -> TokenStream {
    println!("{}", input);

    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();

    println!("ident: {}", ast.ident);

    let fields = match ast.body {
        syn::Body::Enum(_) => panic!("enum not supported"),
        syn::Body::Struct(x) => match x {
            syn::VariantData::Struct(fields) => fields,
            _ => panic!("tuple and unit not supported")
        }
    };

    for field in &fields {
        let ident = field.ident.clone().unwrap();
        let ty = match field.clone().ty {
            syn::Ty::Path(_, path) => path.segments[0].ident.clone(),
            _ => panic!("only path types supported"),
        };

        let mut bitfield: Option<BitField> = None;

        for attr in &field.attrs {
            if let syn::MetaItem::List(attr_ident, attr_nest) = attr.clone().value {
                println!("found attribute: {}", attr_ident);
                if attr_ident == "bitfield" {
                    println!("found bitfield attribute: {:?}", attr_nest);
                }
            }
        }

        bitfield = match 1 {
            0 => Some(BitField::Single(10)),
            1 => Some(BitField::Range(std::ops::Range{start: 3, end: 5})),
            _ => panic!("wrong bitfield position"),
        };

        println!("field {} @{:?}: {}", ident, bitfield, ty);
    }

    // return input;
    return output_struct(&ast.ident).parse().unwrap();
}

/*
Struct(
    Struct([
        Field {
            ident: Some(Ident("foo")),
            vis: Inherited,
            attrs: [
                Attribute {
                    style: Outer,
                    value: List(
                        Ident("bitfield"),
                        [MetaItem(NameValue(Ident("at"), Int(0, Unsuffixed)))]
                    ),
                    is_sugared_doc: false
                }
            ],
            ty: Path(
                None,
                Path {
                    global: false,
                    segments: [
                        PathSegment {
                            ident: Ident("u8"),
                            parameters: AngleBracketed(
                                AngleBracketedParameterData {
                                    lifetimes: [],
                                    types: [],
                                    bindings: []
                                }
                            )
                        }
                    ]
                }
            )
        }
    ])
)
*/<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;

pub mod apr {
   use libc::{c_int};

   // run this hook first, before ANYTHING
   pub const APR_HOOK_REALLY_FIRST:  c_int = -10;
   // run this hook first
   pub const APR_HOOK_FIRST:         c_int = 0;
   // run this hook somewhere
   pub const APR_HOOK_MIDDLE:        c_int = 10;
   // run this hook after every other hook which is defined
   pub const APR_HOOK_LAST:          c_int = 20;
   // run this hook last, after EVERYTHING
   pub const APR_HOOK_REALLY_LAST:   c_int = 30;

   #[repr(C)]
   pub struct apr_pool_t;
}

pub mod httpd {
   use libc::{c_int};

   #[repr(C)]
   pub struct process_rec;

   #[repr(C)]
   pub struct request_rec;

   #[repr(C)]
   pub struct server_rec;

   pub const OK:        c_int = 0;
   pub const DECLINED:  c_int = -1;
   pub const DONE:      c_int = -2;
   pub const SUSPENDED: c_int = -3;
}

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

   use libc::{c_int, c_char};

   use httpd::{request_rec};

   pub type hook_handler_fn = extern "C" fn(
      r: *mut request_rec
   ) -> c_int;

   extern "C" {
      pub fn ap_hook_handler(
         hook_handler: Option<hook_handler_fn>,
         pre: *const *const c_char,
         succ: *const *const c_char,
         order: c_int
      );
   }
}

pub mod ap_mmn {
   use libc::{c_int, c_ulong};

   pub const MODULE_MAGIC_COOKIE: c_ulong = 0x41503234u64; /* "AP24" */

   pub const MODULE_MAGIC_NUMBER_MAJOR: c_int = 20120211;
   pub const MODULE_MAGIC_NUMBER_MINOR: c_int = 36;
}

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

   use libc::{c_void, c_char, c_int, c_ulong};

   use apr::{apr_pool_t};

   use httpd::{process_rec, server_rec};

   #[repr(C)]
   pub struct command_rec;

   pub type rewrite_args_fn = extern "C" fn(
      process: *mut process_rec
   );

   pub type create_dir_config_fn = extern "C" fn(
      p: *mut apr_pool_t, dir: *mut c_char
   ) -> *mut c_void;

   pub type merge_config_fn = extern "C" fn(
      p: *mut apr_pool_t, base_conf: *mut c_void, new_conf: *mut c_void
   ) -> *mut c_void;

   pub type create_server_config_fn = extern "C" fn(
      p: *mut apr_pool_t, s: *mut server_rec
   ) -> *mut c_void;

   pub type register_hooks_fn = extern "C" fn(
      p: *mut apr_pool_t
   );

   pub type module = module_struct;

   #[repr(C)]
   pub struct module_struct {
      pub version: c_int,

      pub minor_version: c_int,

      pub module_index: c_int,

      pub name: *const c_char,

      pub dynamic_load_handle: *mut c_void,

      pub next: *mut module_struct,

      pub magic: c_ulong,

      pub rewrite_args: Option<rewrite_args_fn>,

      pub create_dir_config: Option<create_dir_config_fn>,

      pub merge_dir_config: Option<merge_config_fn>,

      pub create_server_config: Option<create_server_config_fn>,

      pub merge_server_config: Option<merge_config_fn>,

      pub cmds: *const command_rec,

      pub register_hooks: ::std::option::Option<register_hooks_fn>
   }
}

pub mod http_protocol {
   use libc::{c_void, c_int};

   use httpd::{request_rec};

   extern "C" {
      pub fn ap_rwrite(buf: *const c_void, nbyte: c_int, r: *mut request_rec) -> c_int;
   }
}

use libc::{c_void, c_char, c_int};

use std::ptr;
use std::ffi::CString;

use apr::{apr_pool_t, APR_HOOK_MIDDLE};

use httpd::{OK, request_rec};
use ap_exports::{ap_hook_handler};
use http_config::{command_rec};
use http_protocol::{ap_rwrite};

const NAME: &'static [u8] = b"mod_aprust\0";
const NAME_PTR: *const &'static [u8] = &NAME;
const NAME_CHAR_PTR: *const c_char = NAME_PTR as *const c_char;

#[no_mangle]
pub static mut aprust_module: http_config::module = http_config::module {
   version: ap_mmn::MODULE_MAGIC_NUMBER_MAJOR,
   minor_version: ap_mmn::MODULE_MAGIC_NUMBER_MINOR,
   module_index: -1,
   name: NAME_CHAR_PTR,
   dynamic_load_handle: 0 as *mut c_void,
   next: 0 as *mut http_config::module,
   magic: ap_mmn::MODULE_MAGIC_COOKIE,
   rewrite_args: None,
   create_dir_config: None,
   merge_dir_config: None,
   create_server_config: None,
   merge_server_config: None,
   cmds: 0 as *const command_rec,
   register_hooks: Some(aprust_hooks),
};

#[no_mangle]
pub extern "C" fn aprust_handler(r: *mut request_rec) -> c_int {
   let html = CString::new("<meta charset=\"utf-8\">Здравейте!").unwrap();
   let len = html.to_bytes().len();

   unsafe {
      ap_rwrite(html.as_ptr() as *mut c_void, len as i32, r);
   }

   OK
}

#[no_mangle]
pub extern "C" fn aprust_hooks(_: *mut apr_pool_t) {
   unsafe {
      ap_hook_handler(
         Some(aprust_handler), ptr::null(), ptr::null(), APR_HOOK_MIDDLE
      );
   }
}
<commit_msg>Wrapping the module definition in a macro.<commit_after>#![feature(libc)]

extern crate libc;

pub mod apr {
   use libc::{c_int};

   // run this hook first, before ANYTHING
   pub const APR_HOOK_REALLY_FIRST:  c_int = -10;
   // run this hook first
   pub const APR_HOOK_FIRST:         c_int = 0;
   // run this hook somewhere
   pub const APR_HOOK_MIDDLE:        c_int = 10;
   // run this hook after every other hook which is defined
   pub const APR_HOOK_LAST:          c_int = 20;
   // run this hook last, after EVERYTHING
   pub const APR_HOOK_REALLY_LAST:   c_int = 30;

   #[repr(C)]
   pub struct apr_pool_t;
}

pub mod httpd {
   use libc::{c_int};

   #[repr(C)]
   pub struct process_rec;

   #[repr(C)]
   pub struct request_rec;

   #[repr(C)]
   pub struct server_rec;

   pub const OK:        c_int = 0;
   pub const DECLINED:  c_int = -1;
   pub const DONE:      c_int = -2;
   pub const SUSPENDED: c_int = -3;
}

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

   use libc::{c_int, c_char};

   use httpd::{request_rec};

   pub type hook_handler_fn = extern "C" fn(
      r: *mut request_rec
   ) -> c_int;

   extern "C" {
      pub fn ap_hook_handler(
         hook_handler: Option<hook_handler_fn>,
         pre: *const *const c_char,
         succ: *const *const c_char,
         order: c_int
      );
   }
}

pub mod ap_mmn {
   use libc::{c_int, c_ulong};

   pub const MODULE_MAGIC_COOKIE: c_ulong = 0x41503234u64; /* "AP24" */

   pub const MODULE_MAGIC_NUMBER_MAJOR: c_int = 20120211;
   pub const MODULE_MAGIC_NUMBER_MINOR: c_int = 36;
}

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

   use libc::{c_void, c_char, c_int, c_ulong};

   use apr::{apr_pool_t};

   use httpd::{process_rec, server_rec};

   #[repr(C)]
   pub struct command_rec;

   pub type rewrite_args_fn = extern "C" fn(
      process: *mut process_rec
   );

   pub type create_dir_config_fn = extern "C" fn(
      p: *mut apr_pool_t, dir: *mut c_char
   ) -> *mut c_void;

   pub type merge_config_fn = extern "C" fn(
      p: *mut apr_pool_t, base_conf: *mut c_void, new_conf: *mut c_void
   ) -> *mut c_void;

   pub type create_server_config_fn = extern "C" fn(
      p: *mut apr_pool_t, s: *mut server_rec
   ) -> *mut c_void;

   pub type register_hooks_fn = extern "C" fn(
      p: *mut apr_pool_t
   );

   pub type module = module_struct;

   #[repr(C)]
   pub struct module_struct {
      pub version: c_int,

      pub minor_version: c_int,

      pub module_index: c_int,

      pub name: *const c_char,

      pub dynamic_load_handle: *mut c_void,

      pub next: *mut module_struct,

      pub magic: c_ulong,

      pub rewrite_args: Option<rewrite_args_fn>,

      pub create_dir_config: Option<create_dir_config_fn>,

      pub merge_dir_config: Option<merge_config_fn>,

      pub create_server_config: Option<create_server_config_fn>,

      pub merge_server_config: Option<merge_config_fn>,

      pub cmds: *const command_rec,

      pub register_hooks: ::std::option::Option<register_hooks_fn>
   }
}

pub mod http_protocol {
   use libc::{c_void, c_int};

   use httpd::{request_rec};

   extern "C" {
      pub fn ap_rwrite(buf: *const c_void, nbyte: c_int, r: *mut request_rec) -> c_int;
   }
}

use libc::{c_void, c_char, c_int};

use std::ptr;
use std::ffi::CString;

use apr::{apr_pool_t, APR_HOOK_MIDDLE};

use httpd::{OK, request_rec};
use ap_exports::{ap_hook_handler};
use http_config::{command_rec};
use http_protocol::{ap_rwrite};

macro_rules! module_def {
   ($module:ident, $handler:ident, $cname:expr) => {
      const CNAME: &'static [u8] = $cname;
      const CNAME_PTR: *const &'static [u8] = &CNAME;
      const CNAME_CHAR_PTR: *const c_char = CNAME_PTR as *const c_char;

      #[no_mangle]
      pub static mut $module: http_config::module = http_config::module {
         version: ap_mmn::MODULE_MAGIC_NUMBER_MAJOR,
         minor_version: ap_mmn::MODULE_MAGIC_NUMBER_MINOR,
         module_index: -1,
         name: CNAME_CHAR_PTR,
         dynamic_load_handle: 0 as *mut c_void,
         next: 0 as *mut http_config::module,
         magic: ap_mmn::MODULE_MAGIC_COOKIE,
         rewrite_args: None,
         create_dir_config: None,
         merge_dir_config: None,
         create_server_config: None,
         merge_server_config: None,
         cmds: 0 as *const command_rec,
         register_hooks: Some(module_hooks),
      };

      extern "C" fn module_hooks(_: *mut apr_pool_t) {
         unsafe {
            ap_hook_handler(
               Some($handler), ptr::null(), ptr::null(), APR_HOOK_MIDDLE
            );
         }
      }

   }
}

module_def!(aprust_module, aprust_handler, b"mod_aprust\0");

#[no_mangle]
pub extern "C" fn aprust_handler(r: *mut request_rec) -> c_int {
   let html = CString::new("<meta charset=\"utf-8\">Здравейте!").unwrap();
   let len = html.to_bytes().len();

   unsafe {
      ap_rwrite(html.as_ptr() as *mut c_void, len as i32, r);
   }

   OK
}
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate serde;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate failure;

mod error;
mod errorcode;
mod response;

use std::collections::HashSet;
use std::net::IpAddr;

pub use error::Error;
pub use errorcode::RecaptchaErrorCode;

use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&IpAddr>) -> Result<(), Error> {
    use reqwest::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.query_pairs_mut().extend_pairs(&[
        ("secret", key),
        ("response", response),
    ]);

    if let Some(user_ip) = user_ip {
        url.query_pairs_mut().append_pair("remoteip", &user_ip);
    }

    let client = Client::new();

    let mut response = try!(client.get(url).send());
    let recaptcha_response = response.json::<RecaptchaResponse>()?;

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(Error::Codes(errors)),
        (false, _) => Err(Error::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use Error::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<commit_msg>Remove try!<commit_after>extern crate reqwest;
extern crate serde;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate failure;

mod error;
mod errorcode;
mod response;

use std::collections::HashSet;
use std::net::IpAddr;

pub use error::Error;
pub use errorcode::RecaptchaErrorCode;

use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&IpAddr>) -> Result<(), Error> {
    use reqwest::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.query_pairs_mut().extend_pairs(&[
        ("secret", key),
        ("response", response),
    ]);

    if let Some(user_ip) = user_ip {
        url.query_pairs_mut().append_pair("remoteip", &user_ip);
    }

    let client = Client::new();

    let mut response = client.get(url).send()?;
    let recaptcha_response = response.json::<RecaptchaResponse>()?;

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(Error::Codes(errors)),
        (false, _) => Err(Error::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use Error::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
use rand::Rng;
//use std::convert::From;
use std::cmp::max;
use std::slice;

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

pub struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}

impl FloatStorage {
	fn into_slice(&self) -> &[f32] {
		unsafe {slice::from_raw_parts((*self.t).data, (*self.t).size as usize)}
	}
	fn into_slice_mut(&mut self) -> &mut [f32] {
		unsafe {slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize)}
	}
	pub fn iter(&self) -> slice::Iter<f32> {
		self.into_slice().iter()
	}
	pub fn iter_mut(&mut self) -> slice::IterMut<f32> {
		self.into_slice_mut().iter_mut()
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

pub struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}
	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let t = Tensor::sized(dims);
//		x = random::<f32>();
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

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

    }
}
<commit_msg>finish randn initialization<commit_after>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
//use std::convert::From;
use std::cmp::max;
use std::slice;

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

pub struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}
// XXX annotate with lifetime for safety's sake
impl FloatStorage {
	fn into_slice(&self) -> &[f32] {
		unsafe {slice::from_raw_parts((*self.t).data, (*self.t).size as usize)}
	}
	fn into_slice_mut(&mut self) -> &mut [f32] {
		unsafe {slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize)}
	}
	pub fn iter(&self) -> slice::Iter<f32> {
		self.into_slice().iter()
	}
	pub fn iter_mut(&mut self) -> slice::IterMut<f32> {
		self.into_slice_mut().iter_mut()
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

pub struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}

	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let mut t = FloatTensor::sized(dims);
		for x in t.storage.iter_mut() { *x = rand::random::<f32>() }
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

/*
impl fmt::Display for FloatTensor {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match (*self.t).size
		write!(f, "[torchrs.FloatTensor of size ]")
	}
}
*/
#[cfg(test)]
mod tests {
	use super::*;
    #[test]
    fn it_works() {

    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

extern crate serde;
#[macro_use]
extern crate serde_derive;

pub use self::arithmetic::{ArithmeticBase, ArithmeticExpression, ArithmeticOperator};
pub use self::common::{FieldDefinitionExpression, FieldValueExpression, Literal, Operator, Real, SqlType, TableKey};
pub use self::column::{Column, ColumnConstraint, ColumnSpecification, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::delete::DeleteStatement;
pub use self::insert::InsertStatement;
pub use self::join::{JoinConstraint, JoinOperator, JoinRightSide};
pub use self::parser::*;
pub use self::compound_select::{CompoundSelectOperator, CompoundSelectStatement};
pub use self::select::{GroupByClause, JoinClause, LimitClause, SelectStatement};
pub use self::order::{OrderClause, OrderType};
pub use self::table::Table;
pub use self::set::SetStatement;
pub use self::update::UpdateStatement;

pub mod parser;

#[macro_use]
mod keywords;
mod arithmetic;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod compound_select;
mod table;
mod delete;
mod drop;
mod update;
mod set;
mod order;
<commit_msg>Make LiteralExpression public<commit_after>#[macro_use]
extern crate nom;

extern crate serde;
#[macro_use]
extern crate serde_derive;

pub use self::arithmetic::{ArithmeticBase, ArithmeticExpression, ArithmeticOperator};
pub use self::common::{FieldDefinitionExpression, FieldValueExpression, Literal,
                       LiteralExpression, Operator, Real, SqlType, TableKey};
pub use self::column::{Column, ColumnConstraint, ColumnSpecification, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::delete::DeleteStatement;
pub use self::insert::InsertStatement;
pub use self::join::{JoinConstraint, JoinOperator, JoinRightSide};
pub use self::parser::*;
pub use self::compound_select::{CompoundSelectOperator, CompoundSelectStatement};
pub use self::select::{GroupByClause, JoinClause, LimitClause, SelectStatement};
pub use self::order::{OrderClause, OrderType};
pub use self::table::Table;
pub use self::set::SetStatement;
pub use self::update::UpdateStatement;

pub mod parser;

#[macro_use]
mod keywords;
mod arithmetic;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod compound_select;
mod table;
mod delete;
mod drop;
mod update;
mod set;
mod order;
<|endoftext|>


<commit_before>/// Encapsulates a floating point number in the range [0, 1] including both endpoints.
#[derive(Copy, Clone, Debug)]
pub struct Closed01<F>(F);

impl Closed01<f32> {
    #[inline(always)]
    pub fn new(f: f32) -> Closed01<f32> {
        assert!(f >= 0.0 && f <= 1.0);
        Closed01(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01<f32> {
        Closed01(0.0)
    }

    #[inline(always)]
    pub fn one() -> Closed01<f32> {
        Closed01(1.0)
    }

    #[inline(always)]
    pub fn distance(self, other: Closed01<f32>) -> Closed01<f32> {
        let d = (self.0 - other.0).abs();
        debug_assert!(d >= 0.0 && d <= 1.0);
        Closed01(d)
    }

    #[inline(always)]
    pub fn get(self) -> f32 {
        debug_assert!(self.0 >= 0.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// The average of two values.
    pub fn average(a: Closed01<f32>, b: Closed01<f32>) -> Closed01<f32> {
        let avg = (a.get() + b.get()) / 2.0;
        debug_assert!(avg >= 0.0 && avg <= 1.0);
        Closed01(avg)
    }

    #[inline(always)]
    pub fn scale(&self, scalar: Closed01<f32>) -> Closed01<f32> {
        let s = self.get() * scalar.get();
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }
}
<commit_msg>Add min/max functions<commit_after>/// Encapsulates a floating point number in the range [0, 1] including both endpoints.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Closed01<F>(F);

impl Closed01<f32> {
    #[inline(always)]
    pub fn new(f: f32) -> Closed01<f32> {
        assert!(f >= 0.0 && f <= 1.0);
        Closed01(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01<f32> {
        Closed01(0.0)
    }

    #[inline(always)]
    pub fn one() -> Closed01<f32> {
        Closed01(1.0)
    }

    #[inline(always)]
    /// Returns the smaller of the two.
    pub fn min(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 <= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the greater of the two.
    pub fn max(self, other: Closed01<f32>) -> Closed01<f32> {
        if self.0 >= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the distance between the two numbers.
    pub fn distance(self, other: Closed01<f32>) -> Closed01<f32> {
        let d = (self.0 - other.0).abs();
        debug_assert!(d >= 0.0 && d <= 1.0);
        Closed01(d)
    }

    #[inline(always)]
    pub fn get(self) -> f32 {
        debug_assert!(self.0 >= 0.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// The average of two values.
    pub fn average(a: Closed01<f32>, b: Closed01<f32>) -> Closed01<f32> {
        let avg = (a.get() + b.get()) / 2.0;
        debug_assert!(avg >= 0.0 && avg <= 1.0);
        Closed01(avg)
    }

    #[inline(always)]
    pub fn scale(&self, scalar: Closed01<f32>) -> Closed01<f32> {
        let s = self.get() * scalar.get();
        debug_assert!(s >= 0.0 && s <= 1.0);
        Closed01(s)
    }
}

#[test]
fn minmax() {
    let a = Closed01::new(0.4);
    let b = Closed01::new(0.5);
    assert_eq!(a, a.min(b));
    assert_eq!(a, b.min(a));
    assert_eq!(b, a.max(b));
    assert_eq!(b, b.max(a));
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;

#[derive(Debug)]
pub enum Transport {
    Tcp,
    Udp,
}

impl Transport {
    fn to_string(self) -> String {
        match self {
            Transport::Tcp => "tcp".to_string(),
            Transport::Udp => "udp".to_string(),
        }
    }
}

#[derive(Debug)]
pub struct Context{
    /// The scope for the current relation hook
    relation_type: String,
    /// The relation ID for the current relation hook
    relation_id: usize,
    /// Local unit ID
    unit: String,
    /// relation data for all related units
    relations: HashMap<String,String>,
}
impl Context{
    //Gets a context that's filled out from the env variables
    fn new_from_env() -> Context{
        let mut relations: HashMap<String,String> = HashMap::new();
        let relation_type = env::var("JUJU_RELATION").unwrap_or("".to_string());
        let relation_id = env::var("JUJU_RELATION_ID").unwrap_or("0".to_string())
            .parse::<usize>().unwrap();
        let unit = env::var("JUJU_UNIT_NAME").unwrap_or("".to_string());
        Context{
            relation_type: relation_type,
            relation_id: relation_id,
            unit: unit,
            relations: relations,
        }
    }
}

#[derive(Debug)]
pub struct Relation {
    pub name: String,
    pub id: usize
}

pub fn log(msg: &String){
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(msg.clone());
    run_command("juju-log", &arg_list, false);
}

pub fn reboot(){
    run_command_no_args("juju-reboot", true);
}

pub fn unit_get_private_addr() ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push("private-address".to_string());
    let output = run_command("unit-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn unit_get_public_addr() ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push("public-address".to_string());
    let output = run_command("unit-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn config_get(key: &String) ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(key.clone());
    let output = run_command("config-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn open_port(port: usize, transport: Transport){
    let mut arg_list: Vec<String>  = Vec::new();
    let port_string = format!("{}/{}", port.to_string(), transport.to_string());

    arg_list.push(port_string);
    run_command("open-port", &arg_list, false);
}

pub fn close_port(port: usize, transport: Transport){
    let mut arg_list: Vec<String>  = Vec::new();
    let port_string = format!("{}/{}", port.to_string() , transport.to_string());

    arg_list.push(port_string);
    run_command("close-port", &arg_list, false);
}

pub fn relation_set(key: &String, value: &String){
    let mut arg_list: Vec<String>  = Vec::new();
    let arg = key.clone() + &"=" + value;

    arg_list.push(arg);
    run_command("relation-set", &arg_list, false);
}

pub fn relation_get(key: &String) -> String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(key.clone());
    let output = run_command("relation-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn relation_get_by_unit(key: &String, unit: &Relation) -> String{
    let mut arg_list: Vec<String>  = Vec::new();
    //arg_list.push("-r".to_string());
    arg_list.push(key.clone());
    arg_list.push(format!("{}/{}", unit.name , unit.id.to_string()));
    let output = run_command("relation-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn relation_list() ->Vec<Relation>{
    let mut related_units: Vec<Relation> = Vec::new();
    let output = run_command_no_args("relation-list", false);
    let output_str =  String::from_utf8(output.stdout).unwrap();
    log(&format!("relation-list output: {}", output_str));

    for line in output_str.lines(){
        let v: Vec<&str> = line.split('/').collect();
        let id: usize = v[1].parse::<usize>().unwrap();
        let r: Relation = Relation{
            name: v[0].to_string(),
            id: id,
        };
        related_units.push(r);
    }
    return related_units;
}

pub fn relation_ids() ->Vec<Relation>{
    let mut related_units: Vec<Relation> = Vec::new();
    let output = run_command_no_args("relation-ids", false);
    let output_str =  String::from_utf8(output.stdout).unwrap();
    log(&format!("relation-ids output: {}", output_str));

    for line in output_str.lines(){
        let v: Vec<&str> = line.split(':').collect();
        let id: usize = v[1].parse::<usize>().unwrap();
        let r: Relation = Relation{
            name: v[0].to_string(),
            id: id,
        };
        related_units.push(r);
    }
    return related_units;
}

fn run_command_no_args(command: &str, as_root: bool)-> std::process::Output{
    if as_root{
        let mut cmd = std::process::Command::new("sudo");
        println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }else{
       let mut cmd = std::process::Command::new(command);
        println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }
}

fn run_command(command: &str, arg_list: &Vec<String>, as_root: bool) -> std::process::Output{
    if as_root{
        let mut cmd = std::process::Command::new("sudo");
        cmd.arg(command);
        for arg in arg_list{
            cmd.arg(&arg);
        }
        println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }else{
       let mut cmd = std::process::Command::new(command);
        for arg in arg_list{
            cmd.arg(&arg);
        }
        println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }
}
<commit_msg>Trying to borrow more values instead of taking ownership in the library<commit_after>use std::collections::HashMap;
use std::env;

#[derive(Debug)]
pub enum Transport {
    Tcp,
    Udp,
}

impl Transport {
    fn to_string(self) -> String {
        match self {
            Transport::Tcp => "tcp".to_string(),
            Transport::Udp => "udp".to_string(),
        }
    }
}

#[derive(Debug)]
pub struct Context{
    /// The scope for the current relation hook
    pub relation_type: String,
    /// The relation ID for the current relation hook
    pub relation_id: usize,
    /// Local unit ID
    pub unit: String,
    /// relation data for all related units
    pub relations: HashMap<String,String>,
}
impl Context{
    //Gets a context that's filled out from the env variables
    pub fn new_from_env() -> Context{
        let mut relations: HashMap<String,String> = HashMap::new();
        let relation_type = env::var("JUJU_RELATION").unwrap_or("".to_string());
        let relation_id_str = env::var("JUJU_RELATION_ID").unwrap_or("".to_string());
        let parts: Vec<&str> = relation_id_str.split(":").collect();
        let relation_id: usize = parts[1].parse::<usize>().unwrap();

        let unit = env::var("JUJU_UNIT_NAME").unwrap_or("".to_string());
        Context{
            relation_type: relation_type,
            relation_id: relation_id,
            unit: unit,
            relations: relations,
        }
    }
}

#[derive(Debug)]
pub struct Relation {
    pub name: String,
    pub id: usize
}

pub fn log(msg: &String){
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(msg.clone());
    run_command("juju-log", &arg_list, false);
}

pub fn reboot(){
    run_command_no_args("juju-reboot", true);
}

pub fn unit_get_private_addr() ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push("private-address".to_string());
    let output = run_command("unit-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn unit_get_public_addr() ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push("public-address".to_string());
    let output = run_command("unit-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn config_get(key: &String) ->String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(key.clone());
    let output = run_command("config-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn open_port(port: usize, transport: Transport){
    let mut arg_list: Vec<String>  = Vec::new();
    let port_string = format!("{}/{}", port.to_string(), transport.to_string());

    arg_list.push(port_string);
    run_command("open-port", &arg_list, false);
}

pub fn close_port(port: usize, transport: Transport){
    let mut arg_list: Vec<String>  = Vec::new();
    let port_string = format!("{}/{}", port.to_string() , transport.to_string());

    arg_list.push(port_string);
    run_command("close-port", &arg_list, false);
}

pub fn relation_set(key: &str, value: &str){
    let mut arg_list: Vec<String>  = Vec::new();
    let arg = format!("{}={}", key.clone(), value);

    arg_list.push(arg);
    run_command("relation-set", &arg_list, false);
}

pub fn relation_get(key: &String) -> String{
    let mut arg_list: Vec<String>  = Vec::new();
    arg_list.push(key.clone());
    let output = run_command("relation-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn relation_get_by_unit(key: &String, unit: &Relation) -> String{
    let mut arg_list: Vec<String>  = Vec::new();
    //arg_list.push("-r".to_string());
    arg_list.push(key.clone());
    arg_list.push(format!("{}/{}", unit.name , unit.id.to_string()));
    let output = run_command("relation-get", &arg_list, false);
    return String::from_utf8(output.stdout).unwrap();
}

pub fn relation_list() ->Vec<Relation>{
    let mut related_units: Vec<Relation> = Vec::new();
    let output = run_command_no_args("relation-list", false);
    let output_str =  String::from_utf8(output.stdout).unwrap();
    log(&format!("relation-list output: {}", output_str));

    for line in output_str.lines(){
        let v: Vec<&str> = line.split('/').collect();
        let id: usize = v[1].parse::<usize>().unwrap();
        let r: Relation = Relation{
            name: v[0].to_string(),
            id: id,
        };
        related_units.push(r);
    }
    return related_units;
}

pub fn relation_ids() ->Vec<Relation>{
    let mut related_units: Vec<Relation> = Vec::new();
    let output = run_command_no_args("relation-ids", false);
    let output_str =  String::from_utf8(output.stdout).unwrap();
    log(&format!("relation-ids output: {}", output_str));

    for line in output_str.lines(){
        let v: Vec<&str> = line.split(':').collect();
        let id: usize = v[1].parse::<usize>().unwrap();
        let r: Relation = Relation{
            name: v[0].to_string(),
            id: id,
        };
        related_units.push(r);
    }
    return related_units;
}

//Call back any functions that are registered
/*
pub fn process(args: Vec<String>){

}

///
pub fn register_hook<F: Fn()>(func: F){

}
*/

fn run_command_no_args(command: &str, as_root: bool)-> std::process::Output{
    if as_root{
        let mut cmd = std::process::Command::new("sudo");
        //println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }else{
       let mut cmd = std::process::Command::new(command);
        //println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }
}

fn run_command(command: &str, arg_list: &Vec<String>, as_root: bool) -> std::process::Output{
    if as_root{
        let mut cmd = std::process::Command::new("sudo");
        cmd.arg(command);
        for arg in arg_list{
            cmd.arg(&arg);
        }
        //println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }else{
       let mut cmd = std::process::Command::new(command);
        for arg in arg_list{
            cmd.arg(&arg);
        }
        //println!("Running command: {:?}", cmd);
        let output = cmd.output().unwrap_or_else(|e| { panic!("failed to execute process: {} ", e)});
        return output;
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::usize;
use std::mem;
use std::ptr;
use std::cmp;

/// ringbuffer operations on slices
pub trait SliceRing<T> {
    fn push_many_back(&mut self, values: &[T]);
    fn drop_many_front(&mut self, count: usize) -> usize;
    fn read_many_front(&self, output: &mut [T]) -> usize;
}

impl<T: Copy> SliceRing<T> for VecDeque<T> {
    fn push_many_back(&mut self, values: &[T]) {
        for value in values {
            // in most situations this should just be a pointer
            // copy and value copy without any reallocations
            self.push_back(*value);
        }
    }
    fn drop_many_front(&mut self, count: usize) -> usize {
        let real_count = std::cmp::min(self.len(), count);
        for _ in 0..real_count {
            self.pop_front();
        }
        real_count
    }
    fn read_many_front(&self, output: &mut [T]) -> usize {
        let count = std::cmp::min(self.len(), output.len());
        for i in 0..count {
            output[i] = self[i];
        }
        count
    }
}

const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
const MAXIMUM_ZST_CAPACITY: usize = usize::MAX;

// readable area starts at first_readable and goes until (not including)
// next_writable is one after the last readable

// R = first_readable
// W = next_writable
// o = occupied (len)
// . = free
//
//  R             W
// [o o o o o o o . . . .]
pub struct OptimizedSliceRing<T> {
    /// index into `buf` of the first element that could be read.
    /// only to be incremented.
    pub first_readable: usize,
    /// index into `buf` where the next element could we written
    pub next_writable: usize,
    pub buf: Vec<T>,
}

/// Calculate the number of elements left to be read in the buffer
#[inline]
fn count(tail: usize, head: usize, size: usize) -> usize {
    // size is always a power of 2
    (head.wrapping_sub(tail)) & (size - 1)
}

#[inline]
fn wrap_index(index: usize, size: usize) -> usize {
    // size is always a power of 2
    // TODO ?
    debug_assert!(size.is_power_of_two());
    // TODO or is this because the capacity preserves 1 always ?
    let max_index = size - 1;
    index & max_index
}

// TODO implement only what's needed below
/// ringbuffer focused on and optimized for operating on slices of values:
/// appending to the back, reading from the front
/// and dropping from the front.
/// which is much faster.
/// TODO call OptimizedSliceRingImpl
impl<T> OptimizedSliceRing<T> {
    /// Creates an empty `OptimizedSliceRing`.
    pub fn new() -> OptimizedSliceRing<T> {
        OptimizedSliceRing::with_capacity(INITIAL_CAPACITY)
    }

    /// Creates an empty `OptimizedSliceRing` with space for at least `n` elements.
    pub fn with_capacity(n: usize) -> OptimizedSliceRing<T> {
        // +1 since the ringbuffer always leaves one space empty
        let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
        assert!(cap > n, "capacity overflow");

        OptimizedSliceRing {
            first_readable: 0,
            next_writable: 0,
            buf: Vec::with_capacity(cap),
        }
    }

    #[inline]
    pub fn cap(&self) -> usize {
        if mem::size_of::<T>() == 0 {
            // For zero sized types, we are always at maximum capacity
            MAXIMUM_ZST_CAPACITY
        } else {
            self.buf.capacity()
        }
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.cap() - 1
    }

    #[inline]
    pub fn is_continuous(&self) -> bool {
        self.first_readable <= self.next_writable
    }

    #[inline]
    pub fn len(&self) -> usize {
        count(self.first_readable, self.next_writable, self.cap())
    }

    /// - 1 because ...
    #[inline]
    pub fn wrap_add(&self, index: usize, addend: usize) -> usize {
        // wrapping_add is a method of std::usize
        wrap_index(index.wrapping_add(addend), self.cap())
    }

    /// Copies a contiguous block of memory len long from src to dst
    /// we can use this if we own the data and move it around
    /// instead of copying it.
    /// the data still exists in only in one place.
    /// it is just moved to another place.
    #[inline]
    unsafe fn copy_nonoverlapping(&mut self, src: usize, dst: usize, len: usize) {
        debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
                      self.cap());
        debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
                      self.cap());
    }

    /// this is the most complex part
    /// Frobs the head and tail sections around to handle the fact that we
    /// just reallocated. Unsafe because it trusts old_cap.
    #[inline]
    pub unsafe fn handle_cap_increase(&mut self, old_cap: usize) {
        // move the shortest contiguous section of the ring buffer
        // R = first_readable
        // W = next_writable
        // o = occupied
        // . = free
        // c = copied by `handle_cap_increase`

        // continuous !
        // before cap increase:
        //  R             W
        // [o o o o o o o . ]
        // after cap increase:
        //  R             W
        // [o o o o o o o . . . . . . . . . ]
        // after handle_cap_increase:
        //  R             W
        // [o o o o o o o . . . . . . . . . ]
        if self.is_continuous() { return }

        // shortest section at front:
        // before cap increase:
        //      W R
        // [o o . o o o o o ]
        // after cap increase:
        //      W R
        // [c c . o o o o o . . . . . . . . ]
        // after handle_cap_increase:
        //        R             W
        // [. . . o o o o o c c . . . . . . ]
        if self.next_writable < old_cap - self.first_readable {
            let next_writable = self.next_writable;
            let copy_src = 0;
            // after the previous
            let copy_dst = old_cap;
            // everything before next_writable
            let copy_len = next_writable;
            self.copy_nonoverlapping(copy_src, copy_dst, copy_len);
            self.next_writable += old_cap;
            debug_assert!(self.next_writable > self.first_readable);
            debug_assert!(self.next_writable < self.cap());
            debug_assert!(self.first_readable < self.cap());
            debug_assert!(self.cap().is_power_of_two());
            return
        }

        // shortest section at tail:
        // before cap increase:
        //            W R
        // [o o o o o . o o ]
        // after cap increase:
        //            W R
        // [o o o o o . c c . . . . . . . . ]
        // after handle_cap_increase:
        //            W                 R
        // [o o o o o . . . . . . . . . c c ]
        let new_cap = self.cap();
        let new_first_readable =
            new_cap - (old_cap - self.first_readable);
        let copy_src = self.first_readable;
        let copy_dst = new_first_readable;
        let copy_len = old_cap - self.first_readable;
        self.copy_nonoverlapping(copy_src, copy_dst, copy_len);
        self.first_readable = new_first_readable;
        debug_assert!(self.next_writable < self.first_readable);
        debug_assert!(self.next_writable < self.cap());
        debug_assert!(self.first_readable < self.cap());
        debug_assert!(self.cap().is_power_of_two());
    }
}

// TODO test with zero sized types and max length

impl<T: Copy> SliceRing<T> for OptimizedSliceRing<T> {
    /// increases `self.len()` by `count`.
    fn push_many_back(&mut self, input: &[T]) {
        // make enough space
        let additional = input.len();
        let required = self.buf.len() + additional;
        let cap = self.cap();
        if cap < required {
            self.buf.reserve(required.next_power_of_two());
            unsafe {
                self.handle_cap_increase(cap);
            }
        }

        for i in 0..additional {
            // Unsafe code so this can be optimised to a memcpy (or something
            // similarly fast) when T is Copy. LLVM is easily confused, so any
            // extra operations during the loop can prevent this optimisation.
            // TODO benchmark a T (struct) that is Copy
            // vs a T (struct) that is Clone
            // TODO maybe replace by two loops that
            // each copy consecutive elements
            unsafe {
                let dst_index = self.wrap_add(self.next_writable, i);
                let dst = self.buf.get_unchecked_mut(dst_index);
                let src = input.get_unchecked(i).clone();
                ptr::write(dst, src);
            }
        }
        self.next_writable = self.wrap_add(self.next_writable, additional);
    }

    // DONE !!!
    /// reduces `self.len()` by `count`.
    fn drop_many_front(&mut self, count: usize) -> usize {
        // TODO improve name of real_count
        let real_count = std::cmp::min(self.len(), count);
        self.first_readable = self.wrap_add(
            self.first_readable, real_count);
        real_count
    }

    // DONE !!!
    fn read_many_front(&self, output: &mut [T]) -> usize {
        let real_count = std::cmp::min(self.len(), output.len());
        for i in 0..real_count {
            // Unsafe code so this can be optimised to a memcpy (or something
            // similarly fast) when T is Copy. LLVM is easily confused, so any
            // extra operations during the loop can prevent this optimisation.
            unsafe {
                let dst = output.get_unchecked_mut(i);
                let src_index = self.wrap_add(self.first_readable, i);
                let src = self.buf.get_unchecked(src_index).clone();
                ptr::write(dst, src);
            }
        }
        real_count
    }
}

// /// for safe and convenient ... fixed window and step size
// /// this is the main thing of this module
// /// two backing buffer types:
// /// one simple for illustration
// /// one optimized for performance
// /// benchmarked against each other
// pub struct SlidingWindow<T, Storage: SliceRing<T>> {
//     pub window_size: usize,
//     pub step_size: usize,
//     pub buf: T
// }
//
// impl<T, Storage: SliceRing<T>> SlidingWindow<Storage> {
//     pub fn from_storage(storage: Storage) {
//
//     }
//     pub fn new_slow(window_size: usize, step_size: usize) {
//         SlidingWindow {
//             window_size: window_size,
//             step_size: step_size,
//             // TODO initialize based on window and step size
//             buf: VecDeque::<T>::new()
//         }
//     }
// }
//
// drop `count` elements
// remove `step_size` values from the front of `ringbuffer`
// O(1) instead of O(n)
//
// impl<T> FixedSliceRing<T> {
//
//     /// returns the number of values appended
//     /// `O(n)` where `n = fill_me.len()`
//     pub fn push(&mut self, &[T]) -> usize {
//
//     }
//
//     /// write into `fill_me` the first `fill_me.len()` values
//     /// present in this ring.
//     /// `O(n)` where `n = fill_me.len()`
//     pub fn peak(&self, fill_me: &[T]) -> usize {
//
//     }
//
//     /// drop (remove) the first `count` values
//     /// present in this ring.
//     /// O(1)
//     pub fn pop(&mut self, count: usize) -> usize
//
//     }
//
//     pub fn len(&self) {
//
//     }
//
//     ///
//     pub fn space(&self) {
//
//     }
// }
// impl<T: Copy> SlidingWindow<T> {
//     pub fn new(window_size: usize, step_size: usize) -> Self {
//         assert!(0 < window_size);
//         assert!(0 < step_size);
//
//         SlidingWindow {
//             window_size: window_size,
//             step_size: step_size,
//             // TODO with_capacity
//             ringbuffer: VecDeque::new(),
//         }
//     }
//
//     // TODO how fast is this ?
//     // time complexity
//     // append `samples`
//     pub fn len
//
//     pub fn is_full(&self) -> bool {
//         self.window_size <= self.ringbuffer.len()
//     }
//
//     pub fn read_front(&mut self, fill_me: &mut [T]) -> bool {
//         if !self.can_fill() { return false; }
//         assert_eq!(fill_me.len(), self.window_size);
//         for i in 0..self.window_size {
//             fill_me[i] = self.ringbuffer[i];
//         }
//         true
//     }
//
//     pub fn drop_front(&mut self, count: usize) {
//         for _ in 0..count {
//             self.buf.pop_front();
//         }
//     }
//
//     // if `self.can_fill()` fills `window` fully with the next
//     // `window_size` samples.
//     // then makes a step discards `self.step_size` samples.
//     // else does nothing.
//     // `window.len()` must be equal to `self.window_size`.
//     // returns whether `self.can_fill()`.
//     pub fn fill_and_step(&mut self, fill_me: &mut [T]) -> bool {
//         if !self.fill(fill_me) { return false; }
//         self.step();
//         true
//     }
// }

<commit_msg>update comments<commit_after>use std::collections::VecDeque;
use std::usize;
use std::mem;
use std::ptr;
use std::cmp;

/// ringbuffer operations on slices
pub trait SliceRing<T> {
    fn push_many_back(&mut self, values: &[T]);
    fn drop_many_front(&mut self, count: usize) -> usize;
    fn read_many_front(&self, output: &mut [T]) -> usize;
}

impl<T: Copy> SliceRing<T> for VecDeque<T> {
    fn push_many_back(&mut self, values: &[T]) {
        for value in values {
            // in most situations this should just be a pointer
            // copy and value copy without any reallocations
            self.push_back(*value);
        }
    }
    fn drop_many_front(&mut self, count: usize) -> usize {
        let real_count = std::cmp::min(self.len(), count);
        for _ in 0..real_count {
            self.pop_front();
        }
        real_count
    }
    fn read_many_front(&self, output: &mut [T]) -> usize {
        let count = std::cmp::min(self.len(), output.len());
        for i in 0..count {
            output[i] = self[i];
        }
        count
    }
}

const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
const MAXIMUM_ZST_CAPACITY: usize = usize::MAX;

// readable area starts at first_readable and goes until (not including)
// next_writable is one after the last readable

// TODO move this into its own file
// R = first_readable
// W = next_writable
// o = occupied (len)
// . = free
//
//  R             W
// [o o o o o o o . . . .]
pub struct OptimizedSliceRing<T> {
    /// index into `buf` of the first element that could be read.
    /// only to be incremented.
    pub first_readable: usize,
    /// index into `buf` where the next element could we written
    pub next_writable: usize,
    pub buf: Vec<T>,
}

/// Calculate the number of elements left to be read in the buffer
#[inline]
fn count(tail: usize, head: usize, size: usize) -> usize {
    // size is always a power of 2
    (head.wrapping_sub(tail)) & (size - 1)
}

#[inline]
fn wrap_index(index: usize, size: usize) -> usize {
    // size is always a power of 2
    // TODO ?
    debug_assert!(size.is_power_of_two());
    // TODO or is this because the capacity preserves 1 always ?
    let max_index = size - 1;
    index & max_index
}

// TODO implement only what's needed below
/// ringbuffer focused on and optimized for operating on slices of values:
/// appending to the back, reading from the front
/// and dropping from the front.
/// which is much faster.
/// TODO call OptimizedSliceRingImpl
impl<T> OptimizedSliceRing<T> {
    /// Creates an empty `OptimizedSliceRing`.
    pub fn new() -> OptimizedSliceRing<T> {
        OptimizedSliceRing::with_capacity(INITIAL_CAPACITY)
    }

    /// Creates an empty `OptimizedSliceRing` with space for at least `n` elements.
    pub fn with_capacity(n: usize) -> OptimizedSliceRing<T> {
        // +1 since the ringbuffer always leaves one space empty
        let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
        assert!(cap > n, "capacity overflow");

        OptimizedSliceRing {
            first_readable: 0,
            next_writable: 0,
            buf: Vec::with_capacity(cap),
        }
    }

    #[inline]
    pub fn cap(&self) -> usize {
        if mem::size_of::<T>() == 0 {
            // For zero sized types, we are always at maximum capacity
            MAXIMUM_ZST_CAPACITY
        } else {
            self.buf.capacity()
        }
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.cap() - 1
    }

    #[inline]
    pub fn is_continuous(&self) -> bool {
        self.first_readable <= self.next_writable
    }

    #[inline]
    pub fn len(&self) -> usize {
        count(self.first_readable, self.next_writable, self.cap())
    }

    /// - 1 because ...
    #[inline]
    pub fn wrap_add(&self, index: usize, addend: usize) -> usize {
        // wrapping_add is a method of std::usize
        wrap_index(index.wrapping_add(addend), self.cap())
    }

    /// Copies a contiguous block of memory len long from src to dst
    /// we can use this if we own the data and move it around
    /// instead of copying it.
    /// the data still exists in only in one place.
    /// it is just moved to another place.
    #[inline]
    unsafe fn copy_nonoverlapping(&mut self, src: usize, dst: usize, len: usize) {
        debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
                      self.cap());
        debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
                      self.cap());
    }

    /// this is the most complex part
    /// Frobs the head and tail sections around to handle the fact that we
    /// just reallocated. Unsafe because it trusts old_cap.
    #[inline]
    pub unsafe fn handle_cap_increase(&mut self, old_cap: usize) {
        // move the shortest contiguous section of the ring buffer
        // R = first_readable
        // W = next_writable
        // o = occupied
        // . = free
        // c = copied by `handle_cap_increase`

        // continuous !
        // before cap increase:
        //  R             W
        // [o o o o o o o . ]
        // after cap increase:
        //  R             W
        // [o o o o o o o . . . . . . . . . ]
        // after handle_cap_increase:
        //  R             W
        // [o o o o o o o . . . . . . . . . ]
        if self.is_continuous() { return }

        // shortest section at front:
        // before cap increase:
        //      W R
        // [o o . o o o o o ]
        // after cap increase:
        //      W R
        // [c c . o o o o o . . . . . . . . ]
        // after handle_cap_increase:
        //        R             W
        // [. . . o o o o o c c . . . . . . ]
        if self.next_writable < old_cap - self.first_readable {
            let next_writable = self.next_writable;
            let copy_src = 0;
            // after the previous
            let copy_dst = old_cap;
            // everything before next_writable
            let copy_len = next_writable;
            self.copy_nonoverlapping(copy_src, copy_dst, copy_len);
            self.next_writable += old_cap;
            debug_assert!(self.next_writable > self.first_readable);
            debug_assert!(self.next_writable < self.cap());
            debug_assert!(self.first_readable < self.cap());
            debug_assert!(self.cap().is_power_of_two());
            return
        }

        // shortest section at tail:
        // before cap increase:
        //            W R
        // [o o o o o . o o ]
        // after cap increase:
        //            W R
        // [o o o o o . c c . . . . . . . . ]
        // after handle_cap_increase:
        //            W                 R
        // [o o o o o . . . . . . . . . c c ]
        let new_cap = self.cap();
        let new_first_readable =
            new_cap - (old_cap - self.first_readable);
        let copy_src = self.first_readable;
        let copy_dst = new_first_readable;
        let copy_len = old_cap - self.first_readable;
        self.copy_nonoverlapping(copy_src, copy_dst, copy_len);
        self.first_readable = new_first_readable;
        debug_assert!(self.next_writable < self.first_readable);
        debug_assert!(self.next_writable < self.cap());
        debug_assert!(self.first_readable < self.cap());
        debug_assert!(self.cap().is_power_of_two());
    }
}

// TODO test with zero sized types and max length

impl<T: Copy> SliceRing<T> for OptimizedSliceRing<T> {
    /// increases `self.len()` by `count`.
    fn push_many_back(&mut self, input: &[T]) {
        // make enough space
        let additional = input.len();
        let required = self.buf.len() + additional;
        let cap = self.cap();
        if cap < required {
            self.buf.reserve(required.next_power_of_two());
            unsafe {
                self.handle_cap_increase(cap);
            }
        }

        for i in 0..additional {
            // Unsafe code so this can be optimised to a memcpy (or something
            // similarly fast) when T is Copy. LLVM is easily confused, so any
            // extra operations during the loop can prevent this optimisation.
            // TODO benchmark a T (struct) that is Copy
            // vs a T (struct) that is Clone
            // TODO maybe replace by two loops that
            // each copy consecutive elements
            unsafe {
                let dst_index = self.wrap_add(self.next_writable, i);
                let dst = self.buf.get_unchecked_mut(dst_index);
                let src = input.get_unchecked(i).clone();
                ptr::write(dst, src);
            }
        }
        self.next_writable = self.wrap_add(self.next_writable, additional);
    }

    /// reduces `self.len()` by `count`.
    fn drop_many_front(&mut self, count: usize) -> usize {
        // TODO improve name of real_count
        let real_count = std::cmp::min(self.len(), count);
        self.first_readable = self.wrap_add(
            self.first_readable, real_count);
        real_count
    }

    fn read_many_front(&self, output: &mut [T]) -> usize {
        let real_count = std::cmp::min(self.len(), output.len());
        for i in 0..real_count {
            // Unsafe code so this can be optimised to a memcpy (or something
            // similarly fast) when T is Copy. LLVM is easily confused, so any
            // extra operations during the loop can prevent this optimisation.
            unsafe {
                let dst = output.get_unchecked_mut(i);
                let src_index = self.wrap_add(self.first_readable, i);
                let src = self.buf.get_unchecked(src_index).clone();
                ptr::write(dst, src);
            }
        }
        real_count
    }
}

// /// for safe and convenient ... fixed window and step size
// /// this is the main thing of this module
// /// two backing buffer types:
// /// one simple for illustration
// /// one optimized for performance
// /// benchmarked against each other
// pub struct SlidingWindow<T, Storage: SliceRing<T>> {
//     pub window_size: usize,
//     pub step_size: usize,
//     pub buf: T
// }
//
// impl<T, Storage: SliceRing<T>> SlidingWindow<Storage> {
//     pub fn from_storage(storage: Storage) {
//
//     }
//     pub fn new_slow(window_size: usize, step_size: usize) {
//         SlidingWindow {
//             window_size: window_size,
//             step_size: step_size,
//             // TODO initialize based on window and step size
//             buf: VecDeque::<T>::new()
//         }
//     }
// }
//
// drop `count` elements
// remove `step_size` values from the front of `ringbuffer`
// O(1) instead of O(n)
//
// impl<T> FixedSliceRing<T> {
//
//     /// returns the number of values appended
//     /// `O(n)` where `n = fill_me.len()`
//     pub fn push(&mut self, &[T]) -> usize {
//
//     }
//
//     /// write into `fill_me` the first `fill_me.len()` values
//     /// present in this ring.
//     /// `O(n)` where `n = fill_me.len()`
//     pub fn peak(&self, fill_me: &[T]) -> usize {
//
//     }
//
//     /// drop (remove) the first `count` values
//     /// present in this ring.
//     /// O(1)
//     pub fn pop(&mut self, count: usize) -> usize
//
//     }
//
//     pub fn len(&self) {
//
//     }
//
//     ///
//     pub fn space(&self) {
//
//     }
// }
// impl<T: Copy> SlidingWindow<T> {
//     pub fn new(window_size: usize, step_size: usize) -> Self {
//         assert!(0 < window_size);
//         assert!(0 < step_size);
//
//         SlidingWindow {
//             window_size: window_size,
//             step_size: step_size,
//             // TODO with_capacity
//             ringbuffer: VecDeque::new(),
//         }
//     }
//
//     // TODO how fast is this ?
//     // time complexity
//     // append `samples`
//     pub fn len
//
//     pub fn is_full(&self) -> bool {
//         self.window_size <= self.ringbuffer.len()
//     }
//
//     pub fn read_front(&mut self, fill_me: &mut [T]) -> bool {
//         if !self.can_fill() { return false; }
//         assert_eq!(fill_me.len(), self.window_size);
//         for i in 0..self.window_size {
//             fill_me[i] = self.ringbuffer[i];
//         }
//         true
//     }
//
//     pub fn drop_front(&mut self, count: usize) {
//         for _ in 0..count {
//             self.buf.pop_front();
//         }
//     }
//
//     // if `self.can_fill()` fills `window` fully with the next
//     // `window_size` samples.
//     // then makes a step discards `self.step_size` samples.
//     // else does nothing.
//     // `window.len()` must be equal to `self.window_size`.
//     // returns whether `self.can_fill()`.
//     pub fn fill_and_step(&mut self, fill_me: &mut [T]) -> bool {
//         if !self.fill(fill_me) { return false; }
//         self.step();
//         true
//     }
// }

<|endoftext|>