<commit_before>#![allow(non_camel_case_types)]

use libc::*;

pub type xmpp_handler = Option<extern "C" fn(*const xmpp_conn_t, *const xmpp_stanza_t, *const c_void)>;
pub type xmpp_conn_handler = Option<extern "C" fn(*const xmpp_conn_t, c_int, c_int, *const xmpp_stream_error_t, *const c_void)>;
pub type xmpp_timed_handler = Option<extern "C" fn(*const xmpp_conn_t, *const xmpp_stanza_t, *const c_void)>;
pub type xmpp_log_handler = Option<extern "C" fn(*const c_void, c_int, *const c_char, *const c_char, *const c_char)>;
pub type xmpp_open_handler = Option<extern "C" fn(*const xmpp_conn_t)>;

pub type hash_free_func = Option<extern "C" fn(*const xmpp_ctx_t, *mut c_void)>;

#[repr(C)]
pub struct xmpp_conn_t {
  _ref: c_uint,
  ctx: *mut xmpp_ctx_t,
  _type: c_int,

  state: c_int,
  timeout_stamp: uint64_t,
  error: c_int,
  stream_error: *mut xmpp_stream_error_t,
  sock: c_int,
  tls: *mut c_void,

  tls_support: c_int,
  tls_disabled: c_int,
  tls_failed: c_int,
  sasl_support: c_int,
  secured: c_int,

  bind_required: c_int,
  session_required: c_int,

  lang: *mut c_char,
  domain: *mut c_char,
  connectdomain: *mut c_char,
  connectport: *mut c_char,
  jid: *mut c_char,
  pass: *mut c_char,
  bound_jid: *mut c_char,
  stream_id: *mut c_char,

  blocking_seed: c_int,
  send_queue_max: c_int,
  send_queue_len: c_int,
  send_queue_head: *mut c_void,
  send_queue_tail: *mut c_void,

  reset_parser: c_int,
  parser: *mut c_void,
  connect_timeout: c_uint,
  open_handler: xmpp_open_handler,
  authenticated: c_int,

  conn_handler: xmpp_conn_handler,
  userdata: *mut c_void,

  timed_handlers: *mut c_void,
  id_handlers: *mut hash_t,
  handlers: *mut c_void
}

#[repr(C)]
pub struct xmpp_stanza_t {
  _ref: c_int,
  ctx: *mut xmpp_ctx_t,
  _type: c_int,
  prev: *mut xmpp_stanza_t,
  next: *mut xmpp_stanza_t,
  children: *mut xmpp_stanza_t,
  parent: *mut xmpp_stanza_t,
  data: *mut c_char,
  attributes: *mut hash_t
}

#[repr(C)]
pub struct xmpp_ctx_t {
  mem: *const xmpp_mem_t,
  log: *const xmpp_log_t,
  loop_status: c_int,
  connlist: *mut xmpp_connlist_t
}

#[repr(C)]
pub struct xmpp_connlist_t {
  conn: *mut xmpp_conn_t,
  next: *mut xmpp_connlist_t
}

#[repr(C)]
pub struct xmpp_mem_t {
  alloc: Option<extern "C" fn(size_t, *mut u8) -> *mut u8>,
  free: Option<extern "C" fn(*mut u8, *const u8)>,
  realloc: Option<extern "C" fn(*mut u8, size_t, *const u8) -> *mut u8>,
  userdata: *mut c_void
}

#[repr(C)]
pub struct xmpp_log_t {
  handler: xmpp_log_handler,
  userdata: *mut c_void
}

#[repr(C)]
pub struct xmpp_stream_error_t {
  _type: c_int, //xmpp_error_type_t
  text: *mut c_char,
  stanza: *mut xmpp_stanza_t
}

#[repr(C)]
pub struct hashentry_t {
  next: *mut hashentry_t,
  key: *mut c_char,
  values: *mut c_void
}

#[repr(C)]
pub struct hash_t {
  _ref: c_uint,
  ctx: *mut xmpp_ctx_t,
  free: hash_free_func,
  length: c_int,
  num_keys: c_int,
  entries: *mut *mut hashentry_t
}

#[repr(C)]
pub enum xmpp_log_level_t {
  XMPP_LEVEL_DEBUG,
  XMPP_LEVEL_INFO,
  XMPP_LEVEL_WARN,
  XMPP_LEVEL_ERROR
}

#[repr(C)]
pub enum xmpp_conn_type_t {
  XMPP_UNKNOWN,
  XMPP_CLIENT,
  XMPP_COMPONENT
}

#[repr(C)]
pub enum xmpp_conn_event_t {
  XMPP_CONN_CONNECT,
  XMPP_CONN_DISCONNECT,
  XMPP_CONN_FAIL
}

#[repr(C)]
pub enum xmpp_error_type_t {
  XMPP_SE_BAD_FORMAT,
  XMPP_SE_BAD_NS_PREFIX,
  XMPP_SE_CONFLICT,
  XMPP_SE_CONN_TIMEOUT,
  XMPP_SE_HOST_GONE,
  XMPP_SE_HOST_UNKNOWN,
  XMPP_SE_IMPROPER_ADDR,
  XMPP_SE_INTERNAL_SERVER_ERROR,
  XMPP_SE_INVALID_FROM,
  XMPP_SE_INVALID_ID,
  XMPP_SE_INVALID_NS,
  XMPP_SE_INVALID_XML,
  XMPP_SE_NOT_AUTHORIZED,
  XMPP_SE_POLICY_VIOLATION,
  XMPP_SE_REMOTE_CONN_FAILED,
  XMPP_SE_RESOURCE_CONSTRAINT,
  XMPP_SE_RESTRICTED_XML,
  XMPP_SE_SEE_OTHER_HOST,
  XMPP_SE_SYSTEM_SHUTDOWN,
  XMPP_SE_UNDEFINED_CONDITION,
  XMPP_SE_UNSUPPORTED_ENCODING,
  XMPP_SE_UNSUPPORTED_STANZA_TYPE,
  XMPP_SE_UNSUPPORTED_VERSION,
  XMPP_SE_XML_NOT_WELL_FORMED
}

pub const XMPP_NS_CLIENT: &'static str = "jabber:client";
pub const XMPP_NS_COMPONENT: &'static str = "jabber:component:accept";
pub const XMPP_NS_STREAMS: &'static str = "http://etherx.jabber.org/streams";
pub const XMPP_NS_STREAMS_IETF: &'static str = "urn:ietf:params:xml:ns:xmpp-streams";
pub const XMPP_NS_TLS: &'static str = "urn:ietf:params:xml:ns:xmpp-tls";
pub const XMPP_NS_SASL: &'static str = "urn:ietf:params:xml:ns:xmpp-sasl";
pub const XMPP_NS_BIND: &'static str = "urn:ietf:params:xml:ns:xmpp-bind";
pub const XMPP_NS_SESSION: &'static str = "urn:ietf:params:xml:ns:xmpp-session";
pub const XMPP_NS_AUTH: &'static str = "jabber:iq:auth";
pub const XMPP_NS_DISCO_INFO: &'static str = "http://jabber.org/protocol/disco#info";
pub const XMPP_NS_DISCO_ITEMS: &'static str = "http://jabber.org/protocol/disco#items";
pub const XMPP_NS_ROSTER: &'static str = "jabber:iq:roster";

pub const XMPP_EOK:    c_int = 0;
pub const XMPP_EMEM:   c_int = -1;
pub const XMPP_EINVOP: c_int = -2;
pub const XMPP_EINT:   c_int = -3;

#[link(name="strophe")]
extern {
  // connection management
  pub fn xmpp_conn_new(ctx: *const xmpp_ctx_t) -> *mut xmpp_conn_t;
  pub fn xmpp_conn_close(ctx: *const xmpp_ctx_t) -> *mut xmpp_conn_t;
  pub fn xmpp_conn_release(conn: *const xmpp_conn_t) -> c_int;
  pub fn xmpp_conn_get_jid(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_get_bound_jid(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_set_jid(conn: *const xmpp_conn_t, jid: *const c_char);
  pub fn xmpp_conn_get_pass(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_set_pass(conn: *const xmpp_conn_t, pass: *const c_char);
  pub fn xmpp_conn_get_context(conn: *const xmpp_conn_t) -> *mut xmpp_ctx_t;
  pub fn xmpp_connect_client(conn: *const xmpp_conn_t, altdomain: *const c_char, altport: c_ushort, callback: xmpp_conn_handler, userdata: *const u8) -> c_int;
  pub fn xmpp_disconnect(conn: *const xmpp_conn_t);
  pub fn xmpp_send(conn: *const xmpp_conn_t, stanza: *const xmpp_stanza_t);

  // context objects
  pub fn xmpp_get_default_logger(level: c_int) -> *mut xmpp_log_t;
  pub fn xmpp_ctx_new(mem: *const xmpp_mem_t, log: *const xmpp_log_t) -> *mut xmpp_ctx_t;
  pub fn xmpp_ctx_free(ctx: *const xmpp_ctx_t);

  // initialization, shutdown and versioning
  pub fn xmpp_initialize();
  pub fn xmpp_shutdown();
  pub fn xmpp_version_check(major: c_int, minor: c_int) -> c_int;

  // event loop
  pub fn xmpp_run_once(ctx: *mut xmpp_ctx_t, timeout: c_ulong);
  pub fn xmpp_run(ctx: *mut xmpp_ctx_t);
  pub fn xmpp_stop(ctx: *mut xmpp_ctx_t);

  // stanza and timed event handlers
  pub fn xmpp_timed_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_timed_handler);
  pub fn xmpp_id_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_handler, id: *const c_char);
  pub fn xmpp_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_handler);
  pub fn xmpp_timed_handler_add(conn: *const xmpp_conn_t, handler: xmpp_timed_handler, period: c_ulong, userdata: *const c_void);
  pub fn xmpp_id_handler_add(conn: *const xmpp_conn_t, handler: xmpp_handler, id: *const c_char, userdata: *const c_void);
  pub fn xmpp_handler_add(conn: *const xmpp_conn_t, handler: xmpp_handler, ns: *const c_char, name: *const c_char, _type: *const c_char, userdata: *const c_void);

  // stanza creation and manipulation
  pub fn xmpp_stanza_new(ctx: *mut xmpp_ctx_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_clone(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_copy(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_release(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_is_text(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_is_tag(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_to_text(stanza: *mut xmpp_stanza_t, buf: *const *const c_char, sizelen: *const size_t) -> c_int;
  pub fn xmpp_stanza_set_name(stanza: *mut xmpp_stanza_t, name: *const c_char) -> c_int;
  pub fn xmpp_stanza_get_name(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_attribute_count(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_get_attributes(stanza: *const xmpp_stanza_t, attr: *const *const c_char, attrlen: c_int) -> c_int;
  pub fn xmpp_stanza_set_attribute(stanza: *const xmpp_stanza_t, key: *const c_char, value: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_ns(stanza: *const xmpp_stanza_t, ns: *const c_char) -> c_int;
  pub fn xmpp_stanza_add_child(stanza: *mut xmpp_stanza_t, child: *mut xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_set_text(stanza: *mut xmpp_stanza_t, text: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_text_with_size(stanza: *mut xmpp_stanza_t, text: *const c_char, size: size_t) -> c_int;
  pub fn xmpp_stanza_get_id(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_ns(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_type(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_child_by_name(stanza: *const xmpp_stanza_t, name: *const c_char) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_child_by_ns(stanza: *const xmpp_stanza_t, ns: *const c_char) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_children(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_next(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_text(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_text_ptr(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_set_id(stanza: *const xmpp_stanza_t, id: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_type(stanza: *const xmpp_stanza_t, _type: *const c_char) -> c_int;
  pub fn xmpp_stanza_get_attribute(stanza: *const xmpp_stanza_t, name: *const c_char) -> *mut c_char;
}

<commit_msg>replace integer with it's actual enum<commit_after>#![allow(non_camel_case_types)]

use libc::*;

pub type xmpp_handler = Option<extern "C" fn(*const xmpp_conn_t, *const xmpp_stanza_t, *const c_void)>;
pub type xmpp_conn_handler = Option<extern "C" fn(*const xmpp_conn_t, xmpp_conn_event_t, c_int, *const xmpp_stream_error_t, *const c_void)>;
pub type xmpp_timed_handler = Option<extern "C" fn(*const xmpp_conn_t, *const xmpp_stanza_t, *const c_void)>;
pub type xmpp_log_handler = Option<extern "C" fn(*const c_void, xmpp_log_level_t, *const c_char, *const c_char, *const c_char)>;
pub type xmpp_open_handler = Option<extern "C" fn(*const xmpp_conn_t)>;

pub type hash_free_func = Option<extern "C" fn(*const xmpp_ctx_t, *mut c_void)>;

#[repr(C)]
pub struct xmpp_conn_t {
  _ref: c_uint,
  ctx: *mut xmpp_ctx_t,
  _type: c_int,

  state: c_int,
  timeout_stamp: uint64_t,
  error: c_int,
  stream_error: *mut xmpp_stream_error_t,
  sock: c_int,
  tls: *mut c_void,

  tls_support: c_int,
  tls_disabled: c_int,
  tls_failed: c_int,
  sasl_support: c_int,
  secured: c_int,

  bind_required: c_int,
  session_required: c_int,

  lang: *mut c_char,
  domain: *mut c_char,
  connectdomain: *mut c_char,
  connectport: *mut c_char,
  jid: *mut c_char,
  pass: *mut c_char,
  bound_jid: *mut c_char,
  stream_id: *mut c_char,

  blocking_seed: c_int,
  send_queue_max: c_int,
  send_queue_len: c_int,
  send_queue_head: *mut c_void,
  send_queue_tail: *mut c_void,

  reset_parser: c_int,
  parser: *mut c_void,
  connect_timeout: c_uint,
  open_handler: xmpp_open_handler,
  authenticated: c_int,

  conn_handler: xmpp_conn_handler,
  userdata: *mut c_void,

  timed_handlers: *mut c_void,
  id_handlers: *mut hash_t,
  handlers: *mut c_void
}

#[repr(C)]
pub struct xmpp_stanza_t {
  _ref: c_int,
  ctx: *mut xmpp_ctx_t,
  _type: c_int,
  prev: *mut xmpp_stanza_t,
  next: *mut xmpp_stanza_t,
  children: *mut xmpp_stanza_t,
  parent: *mut xmpp_stanza_t,
  data: *mut c_char,
  attributes: *mut hash_t
}

#[repr(C)]
pub struct xmpp_ctx_t {
  mem: *const xmpp_mem_t,
  log: *const xmpp_log_t,
  loop_status: c_int,
  connlist: *mut xmpp_connlist_t
}

#[repr(C)]
pub struct xmpp_connlist_t {
  conn: *mut xmpp_conn_t,
  next: *mut xmpp_connlist_t
}

#[repr(C)]
pub struct xmpp_mem_t {
  alloc: Option<extern "C" fn(size_t, *mut u8) -> *mut u8>,
  free: Option<extern "C" fn(*mut u8, *const u8)>,
  realloc: Option<extern "C" fn(*mut u8, size_t, *const u8) -> *mut u8>,
  userdata: *mut c_void
}

#[repr(C)]
pub struct xmpp_log_t {
  handler: xmpp_log_handler,
  userdata: *mut c_void
}

#[repr(C)]
pub struct xmpp_stream_error_t {
  _type: c_int, //xmpp_error_type_t
  text: *mut c_char,
  stanza: *mut xmpp_stanza_t
}

#[repr(C)]
pub struct hashentry_t {
  next: *mut hashentry_t,
  key: *mut c_char,
  values: *mut c_void
}

#[repr(C)]
pub struct hash_t {
  _ref: c_uint,
  ctx: *mut xmpp_ctx_t,
  free: hash_free_func,
  length: c_int,
  num_keys: c_int,
  entries: *mut *mut hashentry_t
}

#[repr(C)]
pub enum xmpp_log_level_t {
  XMPP_LEVEL_DEBUG,
  XMPP_LEVEL_INFO,
  XMPP_LEVEL_WARN,
  XMPP_LEVEL_ERROR
}

#[repr(C)]
pub enum xmpp_conn_type_t {
  XMPP_UNKNOWN,
  XMPP_CLIENT,
  XMPP_COMPONENT
}

#[repr(C)]
pub enum xmpp_conn_event_t {
  XMPP_CONN_CONNECT,
  XMPP_CONN_DISCONNECT,
  XMPP_CONN_FAIL
}

#[repr(C)]
pub enum xmpp_error_type_t {
  XMPP_SE_BAD_FORMAT,
  XMPP_SE_BAD_NS_PREFIX,
  XMPP_SE_CONFLICT,
  XMPP_SE_CONN_TIMEOUT,
  XMPP_SE_HOST_GONE,
  XMPP_SE_HOST_UNKNOWN,
  XMPP_SE_IMPROPER_ADDR,
  XMPP_SE_INTERNAL_SERVER_ERROR,
  XMPP_SE_INVALID_FROM,
  XMPP_SE_INVALID_ID,
  XMPP_SE_INVALID_NS,
  XMPP_SE_INVALID_XML,
  XMPP_SE_NOT_AUTHORIZED,
  XMPP_SE_POLICY_VIOLATION,
  XMPP_SE_REMOTE_CONN_FAILED,
  XMPP_SE_RESOURCE_CONSTRAINT,
  XMPP_SE_RESTRICTED_XML,
  XMPP_SE_SEE_OTHER_HOST,
  XMPP_SE_SYSTEM_SHUTDOWN,
  XMPP_SE_UNDEFINED_CONDITION,
  XMPP_SE_UNSUPPORTED_ENCODING,
  XMPP_SE_UNSUPPORTED_STANZA_TYPE,
  XMPP_SE_UNSUPPORTED_VERSION,
  XMPP_SE_XML_NOT_WELL_FORMED
}

pub const XMPP_NS_CLIENT: &'static str = "jabber:client";
pub const XMPP_NS_COMPONENT: &'static str = "jabber:component:accept";
pub const XMPP_NS_STREAMS: &'static str = "http://etherx.jabber.org/streams";
pub const XMPP_NS_STREAMS_IETF: &'static str = "urn:ietf:params:xml:ns:xmpp-streams";
pub const XMPP_NS_TLS: &'static str = "urn:ietf:params:xml:ns:xmpp-tls";
pub const XMPP_NS_SASL: &'static str = "urn:ietf:params:xml:ns:xmpp-sasl";
pub const XMPP_NS_BIND: &'static str = "urn:ietf:params:xml:ns:xmpp-bind";
pub const XMPP_NS_SESSION: &'static str = "urn:ietf:params:xml:ns:xmpp-session";
pub const XMPP_NS_AUTH: &'static str = "jabber:iq:auth";
pub const XMPP_NS_DISCO_INFO: &'static str = "http://jabber.org/protocol/disco#info";
pub const XMPP_NS_DISCO_ITEMS: &'static str = "http://jabber.org/protocol/disco#items";
pub const XMPP_NS_ROSTER: &'static str = "jabber:iq:roster";

pub const XMPP_EOK:    c_int = 0;
pub const XMPP_EMEM:   c_int = -1;
pub const XMPP_EINVOP: c_int = -2;
pub const XMPP_EINT:   c_int = -3;

#[link(name="strophe")]
extern {
  // connection management
  pub fn xmpp_conn_new(ctx: *const xmpp_ctx_t) -> *mut xmpp_conn_t;
  pub fn xmpp_conn_close(ctx: *const xmpp_ctx_t) -> *mut xmpp_conn_t;
  pub fn xmpp_conn_release(conn: *const xmpp_conn_t) -> c_int;
  pub fn xmpp_conn_get_jid(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_get_bound_jid(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_set_jid(conn: *const xmpp_conn_t, jid: *const c_char);
  pub fn xmpp_conn_get_pass(conn: *const xmpp_conn_t) -> *const c_char;
  pub fn xmpp_conn_set_pass(conn: *const xmpp_conn_t, pass: *const c_char);
  pub fn xmpp_conn_get_context(conn: *const xmpp_conn_t) -> *mut xmpp_ctx_t;
  pub fn xmpp_connect_client(conn: *const xmpp_conn_t, altdomain: *const c_char, altport: c_ushort, callback: xmpp_conn_handler, userdata: *const u8) -> c_int;
  pub fn xmpp_disconnect(conn: *const xmpp_conn_t);
  pub fn xmpp_send(conn: *const xmpp_conn_t, stanza: *const xmpp_stanza_t);

  // context objects
  pub fn xmpp_get_default_logger(level: xmpp_log_level_t) -> *mut xmpp_log_t;
  pub fn xmpp_ctx_new(mem: *const xmpp_mem_t, log: *const xmpp_log_t) -> *mut xmpp_ctx_t;
  pub fn xmpp_ctx_free(ctx: *const xmpp_ctx_t);

  // initialization, shutdown and versioning
  pub fn xmpp_initialize();
  pub fn xmpp_shutdown();
  pub fn xmpp_version_check(major: c_int, minor: c_int) -> c_int;

  // event loop
  pub fn xmpp_run_once(ctx: *mut xmpp_ctx_t, timeout: c_ulong);
  pub fn xmpp_run(ctx: *mut xmpp_ctx_t);
  pub fn xmpp_stop(ctx: *mut xmpp_ctx_t);

  // stanza and timed event handlers
  pub fn xmpp_timed_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_timed_handler);
  pub fn xmpp_id_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_handler, id: *const c_char);
  pub fn xmpp_handler_delete(conn: *const xmpp_conn_t, handler: xmpp_handler);
  pub fn xmpp_timed_handler_add(conn: *const xmpp_conn_t, handler: xmpp_timed_handler, period: c_ulong, userdata: *const c_void);
  pub fn xmpp_id_handler_add(conn: *const xmpp_conn_t, handler: xmpp_handler, id: *const c_char, userdata: *const c_void);
  pub fn xmpp_handler_add(conn: *const xmpp_conn_t, handler: xmpp_handler, ns: *const c_char, name: *const c_char, _type: *const c_char, userdata: *const c_void);

  // stanza creation and manipulation
  pub fn xmpp_stanza_new(ctx: *mut xmpp_ctx_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_clone(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_copy(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_release(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_is_text(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_is_tag(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_to_text(stanza: *mut xmpp_stanza_t, buf: *const *const c_char, sizelen: *const size_t) -> c_int;
  pub fn xmpp_stanza_set_name(stanza: *mut xmpp_stanza_t, name: *const c_char) -> c_int;
  pub fn xmpp_stanza_get_name(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_attribute_count(stanza: *const xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_get_attributes(stanza: *const xmpp_stanza_t, attr: *const *const c_char, attrlen: c_int) -> c_int;
  pub fn xmpp_stanza_set_attribute(stanza: *const xmpp_stanza_t, key: *const c_char, value: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_ns(stanza: *const xmpp_stanza_t, ns: *const c_char) -> c_int;
  pub fn xmpp_stanza_add_child(stanza: *mut xmpp_stanza_t, child: *mut xmpp_stanza_t) -> c_int;
  pub fn xmpp_stanza_set_text(stanza: *mut xmpp_stanza_t, text: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_text_with_size(stanza: *mut xmpp_stanza_t, text: *const c_char, size: size_t) -> c_int;
  pub fn xmpp_stanza_get_id(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_ns(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_type(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_child_by_name(stanza: *const xmpp_stanza_t, name: *const c_char) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_child_by_ns(stanza: *const xmpp_stanza_t, ns: *const c_char) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_children(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_next(stanza: *const xmpp_stanza_t) -> *mut xmpp_stanza_t;
  pub fn xmpp_stanza_get_text(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_get_text_ptr(stanza: *const xmpp_stanza_t) -> *mut c_char;
  pub fn xmpp_stanza_set_id(stanza: *const xmpp_stanza_t, id: *const c_char) -> c_int;
  pub fn xmpp_stanza_set_type(stanza: *const xmpp_stanza_t, _type: *const c_char) -> c_int;
  pub fn xmpp_stanza_get_attribute(stanza: *const xmpp_stanza_t, name: *const c_char) -> *mut c_char;
}

<|endoftext|>


<commit_before>use matrix::{Matrix, BaseMatrix, BaseMatrixMut};
use error::{Error, ErrorKind};

use std::any::Any;

use libnum::Float;

impl<T> Matrix<T> where T: Any + Float
{
    /// Computes L, U, and P for LUP decomposition.
    ///
    /// Returns L,U, and P respectively.
    ///
    /// # Examples
    ///
    /// ```
    /// use rulinalg::matrix::Matrix;
    ///
    /// let a = Matrix::new(3,3, vec![1.0,2.0,0.0,
    ///                               0.0,3.0,4.0,
    ///                               5.0, 1.0, 2.0]);
    ///
    /// let (l,u,p) = a.lup_decomp().expect("This matrix should decompose!");
    /// ```
    ///
    /// # Panics
    ///
    /// - Matrix is not square.
    ///
    /// # Failures
    ///
    /// - Matrix cannot be LUP decomposed.
    pub fn lup_decomp(&self) -> Result<(Matrix<T>, Matrix<T>, Matrix<T>), Error> {
        let n = self.cols;
        let mut l = Matrix::<T>::zeros(n, n);
        let mut u = self.clone();
        let mut p = Matrix::<T>::identity(n);

        for index in 0..n {
            let mut curr_max_idx = index;
            let mut curr_max = u[[curr_max_idx, curr_max_idx]];

            for i in curr_max_idx..n {
                if u[[i, index]].abs() > curr_max.abs() {
                    curr_max = u[[i, index]];
                    curr_max_idx = i;
                }
            }
            if curr_max.abs() < T::epsilon() {
                return Err(Error::new(ErrorKind::DivByZero,
                    "Singular matrix found in LUP decomposition. \
                    A value in the diagonal of U == 0.0."));
            }

            if curr_max_idx != index {
                l.swap_rows(index, curr_max_idx);
                u.swap_rows(index, curr_max_idx);
                p.swap_rows(index, curr_max_idx);
            }
            l[[index, index]] = T::one();
            for i in (index+1)..n {
                let mult = u[[i, index]]/curr_max;
                l[[i, index]] = mult;
                u[[i, index]] = T::zero();
                for j in (index+1)..n {
                    u[[i, j]] = u[[i,j]] - mult*u[[index, j]];
                }
            }
        }
        Ok((l, u, p))
    }
}

#[cfg(test)]
mod tests {
    use matrix::Matrix;

    #[test]
    #[should_panic]
    fn test_non_square_lup_decomp() {
        let a: Matrix<f64> = Matrix::ones(2, 3);

        let _ = a.lup_decomp();
    }

    #[test]
    fn test_lup_decomp() {
        use error::ErrorKind;
        let a: Matrix<f64> = matrix!(
            1., 2., 3., 4.;
            0., 0., 0., 0.;
            0., 0., 0., 0.;
            0., 0., 0., 0.
        );

        match a.lup_decomp() {
            Err(e) => assert!(*e.kind() == ErrorKind::DivByZero),
            Ok(_) => panic!()
        }
    }
}
<commit_msg>remove an unnecessary loop from the pivot selection<commit_after>use matrix::{Matrix, BaseMatrix, BaseMatrixMut};
use error::{Error, ErrorKind};

use std::any::Any;

use libnum::Float;

impl<T> Matrix<T> where T: Any + Float
{
    /// Computes L, U, and P for LUP decomposition.
    ///
    /// Returns L,U, and P respectively.
    ///
    /// # Examples
    ///
    /// ```
    /// use rulinalg::matrix::Matrix;
    ///
    /// let a = Matrix::new(3,3, vec![1.0,2.0,0.0,
    ///                               0.0,3.0,4.0,
    ///                               5.0, 1.0, 2.0]);
    ///
    /// let (l,u,p) = a.lup_decomp().expect("This matrix should decompose!");
    /// ```
    ///
    /// # Panics
    ///
    /// - Matrix is not square.
    ///
    /// # Failures
    ///
    /// - Matrix cannot be LUP decomposed.
    pub fn lup_decomp(&self) -> Result<(Matrix<T>, Matrix<T>, Matrix<T>), Error> {
        let n = self.cols;
        let mut l = Matrix::<T>::zeros(n, n);
        let mut u = self.clone();
        let mut p = Matrix::<T>::identity(n);

        for index in 0..n {
            let mut curr_max_idx = index;
            let mut curr_max = u[[curr_max_idx, curr_max_idx]];

            for i in (curr_max_idx+1)..n {
                if u[[i, index]].abs() > curr_max.abs() {
                    curr_max = u[[i, index]];
                    curr_max_idx = i;
                }
            }
            if curr_max.abs() < T::epsilon() {
                return Err(Error::new(ErrorKind::DivByZero,
                    "Singular matrix found in LUP decomposition. \
                    A value in the diagonal of U == 0.0."));
            }

            if curr_max_idx != index {
                l.swap_rows(index, curr_max_idx);
                u.swap_rows(index, curr_max_idx);
                p.swap_rows(index, curr_max_idx);
            }
            l[[index, index]] = T::one();
            for i in (index+1)..n {
                let mult = u[[i, index]]/curr_max;
                l[[i, index]] = mult;
                u[[i, index]] = T::zero();
                for j in (index+1)..n {
                    u[[i, j]] = u[[i,j]] - mult*u[[index, j]];
                }
            }
        }
        Ok((l, u, p))
    }
}

#[cfg(test)]
mod tests {
    use matrix::Matrix;

    #[test]
    #[should_panic]
    fn test_non_square_lup_decomp() {
        let a: Matrix<f64> = Matrix::ones(2, 3);

        let _ = a.lup_decomp();
    }

    #[test]
    fn test_lup_decomp() {
        use error::ErrorKind;
        let a: Matrix<f64> = matrix!(
            1., 2., 3., 4.;
            0., 0., 0., 0.;
            0., 0., 0., 0.;
            0., 0., 0., 0.
        );

        match a.lup_decomp() {
            Err(e) => assert!(*e.kind() == ErrorKind::DivByZero),
            Ok(_) => panic!()
        }
    }
}
<|endoftext|>


<commit_before>//! Define semi-implicit schemes

use ndarray::*;
use ndarray_linalg::*;

use super::traits::*;
use super::diag::{Diagonal, StiffDiagonal, diagonal};

pub struct DiagRK4<NLin, Lin, Time: RealScalar> {
    nlin: NLin,
    lin: Lin,
    dt: Time,
}

pub fn diag_rk4<A, D, EOM>(eom: EOM, dt: A::Real) -> DiagRK4<EOM, Diagonal<A, D>, A::Real>
    where A: Scalar,
          D: Dimension,
          EOM: StiffDiagonal<A, D>
{
    let diag = diagonal(&eom, dt / into_scalar(2.0));
    DiagRK4 {
        nlin: eom,
        lin: diag,
        dt: dt,
    }
}

impl<NLin, Lin, Time> TimeStep for DiagRK4<NLin, Lin, Time>
    where Time: RealScalar,
          Lin: TimeStep<Time = Time>
{
    type Time = Time;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.lin.set_dt(dt / into_scalar(2.0));
    }
}

impl<D, NLin, Lin, Time> ModelSize<D> for DiagRK4<NLin, Lin, Time>
    where D: Dimension,
          NLin: ModelSize<D>,
          Lin: ModelSize<D>,
          Time: RealScalar
{
    fn model_size(&self) -> D::Pattern {
        self.nlin.model_size() // TODO check
    }
}

impl<NLin, Lin, Time> WithBuffer for DiagRK4<NLin, Lin, Time>
    where Lin: WithBuffer,
          Time: RealScalar
{
    type Buffer = Lin::Buffer;

    fn new_buffer(&self) -> Self::Buffer {
        self.lin.new_buffer()
    }
}

impl<A, D, NLin, Lin> TimeEvolution<D> for DiagRK4<NLin, Lin, A::Real>
    where A: Scalar,
          D: Dimension,
          NLin: SemiImplicit<D, Scalar = A>,
          Lin: TimeEvolution<D, Scalar = A> + TimeStep<Time = A::Real>
{
    type Scalar = A;

    fn iterate<'a, S>(&self,
                      x: &'a mut ArrayBase<S, D>,
                      mut buf: &mut Self::Buffer)
                      -> &'a mut ArrayBase<S, D>
        where S: DataMut<Elem = A>
    {
        // constants
        let dt = self.dt;
        let dt_2 = self.dt / into_scalar(2.0);
        let dt_3 = self.dt / into_scalar(3.0);
        let dt_6 = self.dt / into_scalar(6.0);
        // operators
        let l = &self.lin;
        let f = &self.nlin;
        // calc
        let mut x_ = x.to_owned();
        let mut lx = x.to_owned();
        l.iterate(&mut lx, &mut buf);
        let mut k1 = f.nlin(x);
        let k1_ = k1.to_owned();
        Zip::from(&mut *k1)
            .and(&x_)
            .apply(|k1, &x_| { *k1 = x_ + k1.mul_real(dt_2); });
        let mut k2 = f.nlin(l.iterate(k1, &mut buf));
        let k2_ = k2.to_owned();
        Zip::from(&mut *k2)
            .and(&lx)
            .apply(|k2, &lx| { *k2 = lx + k2.mul_real(dt_2); });
        let mut k3 = f.nlin(k2);
        let k3_ = k3.to_owned();
        Zip::from(&mut *k3)
            .and(&lx)
            .apply(|k3, &lx| { *k3 = lx + k3.mul_real(dt); });
        let mut k4 = f.nlin(l.iterate(k3, &mut buf));
        azip!(mut x_, k1_ in { *x_ = *x_ + k1_.mul_real(dt_6) });
        l.iterate(&mut x_, &mut buf);
        azip!(mut x_, k2_, k3_ in { *x_ = *x_ + (k2_ + k3_).mul_real(dt_3) });
        l.iterate(&mut x_, &mut buf);
        Zip::from(&mut *k4)
            .and(&x_)
            .apply(|k4, &x_| { *k4 = x_ + k4.mul_real(dt_6); });
        k4
    }
}
<commit_msg>Revise DiagRK4<commit_after>//! Define semi-implicit schemes

use ndarray::*;
use ndarray_linalg::*;

use super::traits::*;
use super::diag::{Diagonal, StiffDiagonal, diagonal};

pub struct DiagRK4<A, NLin, Lin>
    where A: Scalar
{
    nlin: NLin,
    lin: Lin,
    dt: A::Real,
}

pub fn diag_rk4<A, D, EOM>(eom: EOM, dt: A::Real) -> DiagRK4<A, EOM, Diagonal<A, D>>
    where A: Scalar,
          D: Dimension,
          EOM: StiffDiagonal<A, D>
{
    let diag = diagonal(&eom, dt / into_scalar(2.0));
    DiagRK4 {
        nlin: eom,
        lin: diag,
        dt: dt,
    }
}

impl<A, NLin, Lin> TimeStep for DiagRK4<A, NLin, Lin>
    where A: Scalar,
          Lin: TimeStep<Time = A::Real>
{
    type Time = A::Real;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.lin.set_dt(dt / into_scalar(2.0));
    }
}

impl<A, D, NLin, Lin> ModelSize<D> for DiagRK4<A, NLin, Lin>
    where A: Scalar,
          D: Dimension,
          NLin: ModelSize<D>,
          Lin: ModelSize<D>
{
    fn model_size(&self) -> D::Pattern {
        self.nlin.model_size() // TODO check
    }
}

impl<A, NLin, Lin> WithBuffer for DiagRK4<A, NLin, Lin>
    where A: Scalar,
          Lin: WithBuffer
{
    type Buffer = Lin::Buffer;

    fn new_buffer(&self) -> Self::Buffer {
        self.lin.new_buffer()
    }
}

impl<A, D, NLin, Lin> TimeEvolution<D> for DiagRK4<A, NLin, Lin>
    where A: Scalar,
          D: Dimension,
          NLin: SemiImplicit<D, Scalar = A>,
          Lin: TimeEvolution<D, Scalar = A> + TimeStep<Time = A::Real>
{
    type Scalar = A;

    fn iterate<'a, S>(&self,
                      x: &'a mut ArrayBase<S, D>,
                      mut buf: &mut Self::Buffer)
                      -> &'a mut ArrayBase<S, D>
        where S: DataMut<Elem = A>
    {
        // constants
        let dt = self.dt;
        let dt_2 = self.dt / into_scalar(2.0);
        let dt_3 = self.dt / into_scalar(3.0);
        let dt_6 = self.dt / into_scalar(6.0);
        // operators
        let l = &self.lin;
        let f = &self.nlin;
        // calc
        let mut x_ = x.to_owned();
        let mut lx = x.to_owned();
        l.iterate(&mut lx, &mut buf);
        let mut k1 = f.nlin(x);
        let k1_ = k1.to_owned();
        Zip::from(&mut *k1)
            .and(&x_)
            .apply(|k1, &x_| { *k1 = x_ + k1.mul_real(dt_2); });
        let mut k2 = f.nlin(l.iterate(k1, &mut buf));
        let k2_ = k2.to_owned();
        Zip::from(&mut *k2)
            .and(&lx)
            .apply(|k2, &lx| { *k2 = lx + k2.mul_real(dt_2); });
        let mut k3 = f.nlin(k2);
        let k3_ = k3.to_owned();
        Zip::from(&mut *k3)
            .and(&lx)
            .apply(|k3, &lx| { *k3 = lx + k3.mul_real(dt); });
        let mut k4 = f.nlin(l.iterate(k3, &mut buf));
        azip!(mut x_, k1_ in { *x_ = *x_ + k1_.mul_real(dt_6) });
        l.iterate(&mut x_, &mut buf);
        azip!(mut x_, k2_, k3_ in { *x_ = *x_ + (k2_ + k3_).mul_real(dt_3) });
        l.iterate(&mut x_, &mut buf);
        Zip::from(&mut *k4)
            .and(&x_)
            .apply(|k4, &x_| { *k4 = x_ + k4.mul_real(dt_6); });
        k4
    }
}
<|endoftext|>


<commit_before>//! Media I/O, see [OpenCV
//! videoio](http://docs.opencv.org/3.1.0/dd/de7/group__videoio.html)
use core::{Mat, CMat, Size2i};
use libc::{c_int, c_char, c_double};

// =============================================================================
//   VideoCapture
// =============================================================================
enum CvVideoCapture {}

/// Video capturing from video files, image sequences or cameras.
#[derive(Debug)]
pub struct VideoCapture {
    inner: *mut CvVideoCapture,
}

extern "C" {
    fn cv_videocapture_new(index: c_int) -> *mut CvVideoCapture;
    fn cv_videocapture_from_file(path: *const c_char) -> *mut CvVideoCapture;
    fn cv_videocapture_is_opened(ccap: *const CvVideoCapture) -> bool;
    fn cv_videocapture_read(v: *mut CvVideoCapture, m: *mut CMat) -> bool;
    fn cv_videocapture_drop(cap: *mut CvVideoCapture);
    fn cv_videocapture_set(cap: *mut CvVideoCapture, property: c_int, value: c_double) -> bool;
    fn cv_videocapture_get(cap: *mut CvVideoCapture, property: c_int) -> c_double;
}

#[allow(missing_docs)]
/// Video capture's property identifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CapProp {
    /// Current position of the video file in milliseconds or video capture
    /// timestamp.
    PosMsec = 0,

    /// 0-based index of the frame to be decoded/captured next.
    PosFrames = 1,

    /// Relative position of the video file: 0 - start of the film, 1 - end of
    /// the film.
    PosAviRatio = 2,

    /// Width of the frames in the video stream.
    FrameWidth = 3,

    /// Height of the frames in the video stream.
    FrameHeight = 4,

    /// Frame rate.
    Fps = 5,

    /// 4-character code of codec.
    Fourcc = 6,

    /// Number of frames in the video file.
    FrameCount = 7,

    /// Format of the Mat objects returned by retrieve() .
    Format = 8,

    /// Backend-specific value indicating the current capture mode.
    Mode = 9,

    /// Brightness of the image (only for cameras).
    Brightness = 10,

    /// Contrast of the image (only for cameras).
    Contrast = 11,

    /// Saturation of the image (only for cameras).
    Saturation = 12,

    /// Hue of the image (only for cameras).
    Hue = 13,

    /// Gain of the image (only for cameras).
    Gain = 14,

    /// Exposure (only for cameras).
    Exposure = 15,

    /// Boolean flags indicating whether images should be converted to RGB.
    ConvertRgb = 16,

    /// Currently not supported
    WhiteBalanceBlueU = 17,

    /// Rectification flag for stereo cameras (note: only supported by DC1394 v
    /// 2.x backend currently)
    Rectification = 18,
    Monochrome = 19,
    Sharpness = 20,
    AutoExposure = 21,
    Gamma = 22,
    Temperature = 23,
    Trigger = 24,
    TriggerDelay = 25,
    WhiteBalanceRedV = 26,
    Zoom = 27,
    Focus = 28,
    Guid = 29,
    IsoSpeed = 30,
    Backlight = 32,
    Pan = 33,
    Tilt = 34,
    Roll = 35,
    Iris = 36,
    Settings = 37,
    Buffersize = 38,
    Autofocus = 39,
}

impl VideoCapture {
    /// Creates a capture device with specified camera id. If there is a single
    /// camera connected, just pass 0.
    pub fn new(index: i32) -> Self {
        let cap = unsafe { cv_videocapture_new(index) };
        VideoCapture { inner: cap }
    }

    /// Creates a capture device with the path of a video file (eg. video.avi).
    /// This also supports image sequence, eg. img_%02d.jpg, which will read
    /// samples like img_00.jpg, img_01.jpg, img_02.jpg, ...).
    pub fn from_path(path: &str) -> Self {
        let s = ::std::ffi::CString::new(path).unwrap();
        let cap = unsafe { cv_videocapture_from_file((&s).as_ptr()) };
        VideoCapture { inner: cap }
    }

    /// Returns true if video capturing has been initialized already.
    pub fn is_open(&self) -> bool {
        unsafe { cv_videocapture_is_opened(self.inner) }
    }

    /// Grabs, decodes and returns the next video frame. `read` combines
    /// `VideoCapture::grab` and `VideoCapture::retrieve` in one call. This is
    /// the most convenient method for reading video files or capturing data
    /// from decode and return the just grabbed frame.
    ///
    /// If no frames has been grabbed (camera has been disconnected, or there
    /// are no more frames in video file), the methods return `None`.
    pub fn read(&self) -> Option<Mat> {
        let inner = CMat::new();
        let status = unsafe { cv_videocapture_read(self.inner, inner) };
        if status {
            Some(Mat::from_raw(inner))
        } else {
            None
        }
    }

    /// Sets a property in the `VideoCapture`.
    pub fn set(&self, property: CapProp, value: f64) -> bool {
        unsafe { cv_videocapture_set(self.inner, property as c_int, value) }
    }

    /// Gets a property in the `VideoCapture`.
    pub fn get(&self, property: CapProp) -> Option<f64> {
        let ret = unsafe { cv_videocapture_get(self.inner, property as c_int) };
        if ret != 0.0 { Some(ret) } else { None }
    }
}

impl Drop for VideoCapture {
    fn drop(&mut self) {
        unsafe {
            cv_videocapture_drop(self.inner);
        }
    }
}

// =============================================================================
//   VideoWriter
// =============================================================================

/// Opaque VideoWriter type.
enum CvVideoWriter {}

/// `VideoWriter` provides easy access to write videos to files.
/// - On Linux FFMPEG is used to write videos;
/// - On Windows FFMPEG or VFW is used;
/// - On MacOSX QTKit is used.
#[derive(Debug)]
pub struct VideoWriter {
    inner: *mut CvVideoWriter,
}

extern "C" {
    fn cv_videowriter_default() -> *mut CvVideoWriter;
    fn cv_videowriter_new(path: *const c_char,
                          fourcc: c_int,
                          fps: c_double,
                          frame_size: Size2i,
                          is_color: bool)
                          -> *mut CvVideoWriter;
    fn cv_videowriter_drop(w: *mut CvVideoWriter);

    fn cv_videowriter_open(w: *mut CvVideoWriter,
                           path: *const c_char,
                           fourcc: c_int,
                           fps: c_double,
                           frame_size: Size2i,
                           is_color: bool)
                           -> bool;
    fn cv_videowriter_is_opened(w: *mut CvVideoWriter) -> bool;
    fn cv_videowriter_write(w: *mut CvVideoWriter, m: *mut CMat);
    fn cv_videowriter_set(w: *mut CvVideoWriter, property: c_int, value: c_double) -> bool;
    fn cv_videowriter_get(w: *mut CvVideoWriter, property: c_int) -> c_double;
}

impl VideoWriter {
    /// `VideoWriter` constructor.
    /// * path – Name of the output video file.
    /// * fourcc – 4-character code of codec used to compress the frames. For
    ///   example, VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec,
    ///   VideoWriter::fourcc('M','J','P','G') is a motion-jpeg codec etc. List
    ///   of codes can be obtained at Video Codecs by FOURCC page.
    /// * fps – Framerate of the created video stream.
    /// * frame_size – Size of the video frames.
    /// * is_color – If it is not zero, the encoder will expect and encode color
    ///   frames, otherwise it will work with grayscale frames (the flag is
    ///   currently supported on Windows only).
    pub fn new(path: &str, fourcc: i32, fps: f64, frame_size: Size2i, is_color: bool) -> VideoWriter {
        let s = ::std::ffi::CString::new(path).unwrap();
        let writer = unsafe { cv_videowriter_new((&s).as_ptr(), fourcc, fps, frame_size, is_color) };
        VideoWriter { inner: writer }
    }

    /// `VideoWriter` constructor.
    /// * path – Name of the output video file.
    /// * fourcc – 4-character code of codec used to compress the frames. For
    ///   example, VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec,
    ///   VideoWriter::fourcc('M','J','P','G') is a motion-jpeg codec etc. List
    ///   of codes can be obtained at Video Codecs by FOURCC page.
    /// * fps – Framerate of the created video stream.
    /// * frame_size – Size of the video frames.
    /// * is_color – If it is not zero, the encoder will expect and encode color
    ///   frames, otherwise it will work with grayscale frames (the flag is
    ///   currently supported on Windows only).
    pub fn open(&self, path: &str, fourcc: i32, fps: f64, frame_size: Size2i, is_color: bool) -> bool {
        let s = ::std::ffi::CString::new(path).unwrap();
        unsafe { cv_videowriter_open(self.inner, (&s).as_ptr(), fourcc, fps, frame_size, is_color) }
    }

    /// Writes the specified image to video file. It must have the same size as
    /// has been specified when opening the video writer.
    pub fn write(&self, mat: &Mat) {
        unsafe { cv_videowriter_write(self.inner, mat.inner) }
    }

    /// Returns true if video writer has been initialized already.
    pub fn is_open(&self) -> bool {
        unsafe { cv_videowriter_is_opened(self.inner) }
    }

    /// Sets a property in the `VideoWriter`.
    /// Note: `VideoWriterProperty::FrameBytes` is read-only.
    pub fn set(&self, property: VideoWriterProperty, value: f64) -> bool {
        unsafe { cv_videowriter_set(self.inner, property as c_int, value) }
    }

    /// Gets a property in the `VideoWriter`.
    pub fn get(&self, property: VideoWriterProperty) -> Option<f64> {
        let ret = unsafe { cv_videowriter_get(self.inner, property as c_int) };
        if ret != 0.0 { Some(ret) } else { None }
    }
}

impl Default for VideoWriter {
    fn default() -> VideoWriter {
        VideoWriter { inner: unsafe { cv_videowriter_default() } }
    }
}

impl Drop for VideoWriter {
    fn drop(&mut self) {
        unsafe {
            cv_videowriter_drop(self.inner);
        }
    }
}

/// `VideoWriter`'s property identifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VideoWriterProperty {
    /// Current quality of the encoded videostream.
    Quality = 1,

    /// (Read-only) Size of just encoded video frame; note that the encoding
    /// order may be different from representation order.
    FrameBytes = 2,

    /// Number of stripes for parallel encoding
    NStripes = 3,
}

// =============================================================================
//   Utility functions
// =============================================================================
extern "C" {
    fn cv_fourcc(c1: c_char, c2: c_char, c3: c_char, c4: c_char) -> c_int;
}

/// Converts from [four character code](https://www.fourcc.org/) to `i32` for
/// OpenCV.
pub fn fourcc(c1: char, c2: char, c3: char, c4: char) -> i32 {
    unsafe { cv_fourcc(c1 as c_char, c2 as c_char, c3 as c_char, c4 as c_char) }
}

/// Converts from OpenCV's int to [four character
/// code](https://www.fourcc.org/).
pub fn codec_name(fourcc: i32) -> Option<String> {
    let ex = fourcc as u32;
    let vec = vec![(ex & 0xFFu32) as u8,
                   ((ex & 0xFF00u32) >> 8) as u8,
                   ((ex & 0xFF0000u32) >> 16) as u8,
                   ((ex & 0xFF000000u32) >> 24) as u8];
    String::from_utf8(vec).ok()
}
<commit_msg>fix: impl Send for videocapture<commit_after>//! Media I/O, see [OpenCV
//! videoio](http://docs.opencv.org/3.1.0/dd/de7/group__videoio.html)

use core::{Mat, CMat, Size2i};
use libc::{c_int, c_char, c_double};

// =============================================================================
//   VideoCapture
// =============================================================================
enum CvVideoCapture {}

unsafe impl Send for CvVideoCapture {}

/// Video capturing from video files, image sequences or cameras.
#[derive(Debug)]
pub struct VideoCapture {
    inner: *mut CvVideoCapture,
}

unsafe impl Send for VideoCapture {}

extern "C" {
    fn cv_videocapture_new(index: c_int) -> *mut CvVideoCapture;
    fn cv_videocapture_from_file(path: *const c_char) -> *mut CvVideoCapture;
    fn cv_videocapture_is_opened(ccap: *const CvVideoCapture) -> bool;
    fn cv_videocapture_read(v: *mut CvVideoCapture, m: *mut CMat) -> bool;
    fn cv_videocapture_drop(cap: *mut CvVideoCapture);
    fn cv_videocapture_set(cap: *mut CvVideoCapture, property: c_int, value: c_double) -> bool;
    fn cv_videocapture_get(cap: *mut CvVideoCapture, property: c_int) -> c_double;
}

#[allow(missing_docs)]
/// Video capture's property identifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CapProp {
    /// Current position of the video file in milliseconds or video capture
    /// timestamp.
    PosMsec = 0,

    /// 0-based index of the frame to be decoded/captured next.
    PosFrames = 1,

    /// Relative position of the video file: 0 - start of the film, 1 - end of
    /// the film.
    PosAviRatio = 2,

    /// Width of the frames in the video stream.
    FrameWidth = 3,

    /// Height of the frames in the video stream.
    FrameHeight = 4,

    /// Frame rate.
    Fps = 5,

    /// 4-character code of codec.
    Fourcc = 6,

    /// Number of frames in the video file.
    FrameCount = 7,

    /// Format of the Mat objects returned by retrieve() .
    Format = 8,

    /// Backend-specific value indicating the current capture mode.
    Mode = 9,

    /// Brightness of the image (only for cameras).
    Brightness = 10,

    /// Contrast of the image (only for cameras).
    Contrast = 11,

    /// Saturation of the image (only for cameras).
    Saturation = 12,

    /// Hue of the image (only for cameras).
    Hue = 13,

    /// Gain of the image (only for cameras).
    Gain = 14,

    /// Exposure (only for cameras).
    Exposure = 15,

    /// Boolean flags indicating whether images should be converted to RGB.
    ConvertRgb = 16,

    /// Currently not supported
    WhiteBalanceBlueU = 17,

    /// Rectification flag for stereo cameras (note: only supported by DC1394 v
    /// 2.x backend currently)
    Rectification = 18,
    Monochrome = 19,
    Sharpness = 20,
    AutoExposure = 21,
    Gamma = 22,
    Temperature = 23,
    Trigger = 24,
    TriggerDelay = 25,
    WhiteBalanceRedV = 26,
    Zoom = 27,
    Focus = 28,
    Guid = 29,
    IsoSpeed = 30,
    Backlight = 32,
    Pan = 33,
    Tilt = 34,
    Roll = 35,
    Iris = 36,
    Settings = 37,
    Buffersize = 38,
    Autofocus = 39,
}

impl VideoCapture {
    /// Creates a capture device with specified camera id. If there is a single
    /// camera connected, just pass 0.
    pub fn new(index: i32) -> Self {
        let cap = unsafe { cv_videocapture_new(index) };
        VideoCapture { inner: cap }
    }

    /// Creates a capture device with the path of a video file (eg. video.avi).
    /// This also supports image sequence, eg. img_%02d.jpg, which will read
    /// samples like img_00.jpg, img_01.jpg, img_02.jpg, ...).
    pub fn from_path(path: &str) -> Self {
        let s = ::std::ffi::CString::new(path).unwrap();
        let cap = unsafe { cv_videocapture_from_file((&s).as_ptr()) };
        VideoCapture { inner: cap }
    }

    /// Returns true if video capturing has been initialized already.
    pub fn is_open(&self) -> bool {
        unsafe { cv_videocapture_is_opened(self.inner) }
    }

    /// Grabs, decodes and returns the next video frame. `read` combines
    /// `VideoCapture::grab` and `VideoCapture::retrieve` in one call. This is
    /// the most convenient method for reading video files or capturing data
    /// from decode and return the just grabbed frame.
    ///
    /// If no frames has been grabbed (camera has been disconnected, or there
    /// are no more frames in video file), the methods return `None`.
    pub fn read(&self) -> Option<Mat> {
        let inner = CMat::new();
        let status = unsafe { cv_videocapture_read(self.inner, inner) };
        if status {
            Some(Mat::from_raw(inner))
        } else {
            None
        }
    }

    /// Sets a property in the `VideoCapture`.
    pub fn set(&self, property: CapProp, value: f64) -> bool {
        unsafe { cv_videocapture_set(self.inner, property as c_int, value) }
    }

    /// Gets a property in the `VideoCapture`.
    pub fn get(&self, property: CapProp) -> Option<f64> {
        let ret = unsafe { cv_videocapture_get(self.inner, property as c_int) };
        if ret != 0.0 { Some(ret) } else { None }
    }
}

impl Drop for VideoCapture {
    fn drop(&mut self) {
        unsafe {
            cv_videocapture_drop(self.inner);
        }
    }
}

// =============================================================================
//   VideoWriter
// =============================================================================

/// Opaque VideoWriter type.
enum CvVideoWriter {}

/// `VideoWriter` provides easy access to write videos to files.
/// - On Linux FFMPEG is used to write videos;
/// - On Windows FFMPEG or VFW is used;
/// - On MacOSX QTKit is used.
#[derive(Debug)]
pub struct VideoWriter {
    inner: *mut CvVideoWriter,
}

extern "C" {
    fn cv_videowriter_default() -> *mut CvVideoWriter;
    fn cv_videowriter_new(path: *const c_char,
                          fourcc: c_int,
                          fps: c_double,
                          frame_size: Size2i,
                          is_color: bool)
                          -> *mut CvVideoWriter;
    fn cv_videowriter_drop(w: *mut CvVideoWriter);

    fn cv_videowriter_open(w: *mut CvVideoWriter,
                           path: *const c_char,
                           fourcc: c_int,
                           fps: c_double,
                           frame_size: Size2i,
                           is_color: bool)
                           -> bool;
    fn cv_videowriter_is_opened(w: *mut CvVideoWriter) -> bool;
    fn cv_videowriter_write(w: *mut CvVideoWriter, m: *mut CMat);
    fn cv_videowriter_set(w: *mut CvVideoWriter, property: c_int, value: c_double) -> bool;
    fn cv_videowriter_get(w: *mut CvVideoWriter, property: c_int) -> c_double;
}

impl VideoWriter {
    /// `VideoWriter` constructor.
    /// * path – Name of the output video file.
    /// * fourcc – 4-character code of codec used to compress the frames. For
    ///   example, VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec,
    ///   VideoWriter::fourcc('M','J','P','G') is a motion-jpeg codec etc. List
    ///   of codes can be obtained at Video Codecs by FOURCC page.
    /// * fps – Framerate of the created video stream.
    /// * frame_size – Size of the video frames.
    /// * is_color – If it is not zero, the encoder will expect and encode color
    ///   frames, otherwise it will work with grayscale frames (the flag is
    ///   currently supported on Windows only).
    pub fn new(path: &str, fourcc: i32, fps: f64, frame_size: Size2i, is_color: bool) -> VideoWriter {
        let s = ::std::ffi::CString::new(path).unwrap();
        let writer = unsafe { cv_videowriter_new((&s).as_ptr(), fourcc, fps, frame_size, is_color) };
        VideoWriter { inner: writer }
    }

    /// `VideoWriter` constructor.
    /// * path – Name of the output video file.
    /// * fourcc – 4-character code of codec used to compress the frames. For
    ///   example, VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec,
    ///   VideoWriter::fourcc('M','J','P','G') is a motion-jpeg codec etc. List
    ///   of codes can be obtained at Video Codecs by FOURCC page.
    /// * fps – Framerate of the created video stream.
    /// * frame_size – Size of the video frames.
    /// * is_color – If it is not zero, the encoder will expect and encode color
    ///   frames, otherwise it will work with grayscale frames (the flag is
    ///   currently supported on Windows only).
    pub fn open(&self, path: &str, fourcc: i32, fps: f64, frame_size: Size2i, is_color: bool) -> bool {
        let s = ::std::ffi::CString::new(path).unwrap();
        unsafe { cv_videowriter_open(self.inner, (&s).as_ptr(), fourcc, fps, frame_size, is_color) }
    }

    /// Writes the specified image to video file. It must have the same size as
    /// has been specified when opening the video writer.
    pub fn write(&self, mat: &Mat) {
        unsafe { cv_videowriter_write(self.inner, mat.inner) }
    }

    /// Returns true if video writer has been initialized already.
    pub fn is_open(&self) -> bool {
        unsafe { cv_videowriter_is_opened(self.inner) }
    }

    /// Sets a property in the `VideoWriter`.
    /// Note: `VideoWriterProperty::FrameBytes` is read-only.
    pub fn set(&self, property: VideoWriterProperty, value: f64) -> bool {
        unsafe { cv_videowriter_set(self.inner, property as c_int, value) }
    }

    /// Gets a property in the `VideoWriter`.
    pub fn get(&self, property: VideoWriterProperty) -> Option<f64> {
        let ret = unsafe { cv_videowriter_get(self.inner, property as c_int) };
        if ret != 0.0 { Some(ret) } else { None }
    }
}

impl Default for VideoWriter {
    fn default() -> VideoWriter {
        VideoWriter { inner: unsafe { cv_videowriter_default() } }
    }
}

impl Drop for VideoWriter {
    fn drop(&mut self) {
        unsafe {
            cv_videowriter_drop(self.inner);
        }
    }
}

/// `VideoWriter`'s property identifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VideoWriterProperty {
    /// Current quality of the encoded videostream.
    Quality = 1,

    /// (Read-only) Size of just encoded video frame; note that the encoding
    /// order may be different from representation order.
    FrameBytes = 2,

    /// Number of stripes for parallel encoding
    NStripes = 3,
}

// =============================================================================
//   Utility functions
// =============================================================================
extern "C" {
    fn cv_fourcc(c1: c_char, c2: c_char, c3: c_char, c4: c_char) -> c_int;
}

/// Converts from [four character code](https://www.fourcc.org/) to `i32` for
/// OpenCV.
pub fn fourcc(c1: char, c2: char, c3: char, c4: char) -> i32 {
    unsafe { cv_fourcc(c1 as c_char, c2 as c_char, c3 as c_char, c4 as c_char) }
}

/// Converts from OpenCV's int to [four character
/// code](https://www.fourcc.org/).
pub fn codec_name(fourcc: i32) -> Option<String> {
    let ex = fourcc as u32;
    let vec = vec![(ex & 0xFFu32) as u8,
                   ((ex & 0xFF00u32) >> 8) as u8,
                   ((ex & 0xFF0000u32) >> 16) as u8,
                   ((ex & 0xFF000000u32) >> 24) as u8];
    String::from_utf8(vec).ok()
}
<|endoftext|>


<commit_before>use libc::{c_int, c_uint, uint8_t, c_char};
use std::slice;
use std::ptr;
use rustc_serialize::hex::ToHex;
use std::fmt::Error;

#[repr(C)]
struct YK_KEY;

#[link(name="ykpers-1")]
extern {
    fn yk_init() -> c_int;
    fn yk_open_first_key() -> *const YK_KEY;
    fn yk_close_key(yk: *const YK_KEY) -> c_int;
    fn yk_get_serial(yk: *const YK_KEY, slot: uint8_t, flags: c_uint,
                     serial: *mut c_uint) -> c_int;
    fn yk_challenge_response(yk: *const YK_KEY, yk_cmd: uint8_t, may_block: c_int,
                             challenge_len: c_uint, challenge: *const uint8_t,
                             response_len: c_uint, response: *mut u8) -> c_int;
}

/* When a YK_KEY goes out of scope, close the handle */
impl Drop for YK_KEY {
    fn drop(&mut self) {
        unsafe { yk_close_key(self) };
    }
}

/*****************************
*  Safe interface to ykpers  *
*****************************/

pub enum YubikeyError { InvalidYubikeySlot,
                        EmptyCRChallenge,
                        UnknownError }

/* Opaque pointer to foreign Yubikey type. Under the hood this is just a handle
*  for a USB device. */
pub type Yubikey = *const YK_KEY;

/* This function must be called at least once before using any of the Yubikey
*  functionality. It initializes the Yubikey C library. */
pub fn yubikey_init() {
    unsafe { yk_init() };
}

/* Returns the first plugged in Yubikey. */
pub fn get_yubikey() -> Yubikey {
    unsafe { yk_open_first_key() }
}

/* Returns the serial number of the Yubikey */
pub fn get_serial(yk: Yubikey) -> u32 {
    unsafe {
        let mut serial: c_uint = 0;
        yk_get_serial(yk, 0, 0, &mut serial);
        serial as u32
    }
}

//#define SLOT_CHAL_HMAC1		0x30	/* Write 64 byte challenge to slot 1, get HMAC-SHA1 response */
//#define SLOT_CHAL_HMAC2		0x38	/* Write 64 byte challenge to slot 2, get HMAC-SHA1 response */

pub fn challenge_response(yk: Yubikey, slot: u8, challenge: &[u8], may_block: bool) -> Result<String, YubikeyError> {
    // Yubikey commands are defined in ykdef.h
    let yk_cmd = try!(match slot {
        1 => Ok(0x30), //#define SLOT_CHAL_HMAC1 0x30
        2 => Ok(0x38), //#define SLOT_CHAL_HMAC2 0x38
        _ => Err(YubikeyError::InvalidYubikeySlot)
    });

    let challenge_len = challenge.len() as c_uint;

    if (challenge_len == 0) {
        return Err(YubikeyError::EmptyCRChallenge);
    }

    let response_len = 64; // Length of HMAC-SHA1 response

    let mut response = Vec::with_capacity(response_len as usize);
    let mut cr_status = 0; // Return code to check *after* unsafe block

    unsafe {
        cr_status = yk_challenge_response(yk, yk_cmd, may_block as c_int,
                                          challenge_len, challenge.as_ptr(),
                                          response_len, response.as_mut_ptr());

        response.set_len(response_len as usize);
    }

    if (cr_status == 0) {
        // There's some way to get a better error code from the Yubikey, but
        // that's not needed right now.
        Err(YubikeyError::UnknownError)
    } else {
        // There must be a better way to do this, but I'm not sure what it is yet
        let response_str =
            String::from_str(response.as_slice().to_hex().as_str().slice_chars(0,40));
        Ok(response_str)
    }
}
<commit_msg>[yubikey] Improve error handling<commit_after>use core::fmt;
use libc::{c_int, c_uint, uint8_t};
use rustc_serialize::hex::ToHex;
use std::error::Error;
use std::fmt::{Display, Formatter};

#[repr(C)]
struct YK_KEY;

#[link(name="ykpers-1")]
extern {
    fn yk_init() -> c_int;
    fn yk_open_first_key() -> *const YK_KEY;
    fn yk_close_key(yk: *const YK_KEY) -> c_int;
    fn yk_get_serial(yk: *const YK_KEY, slot: uint8_t, flags: c_uint,
                     serial: *mut c_uint) -> c_int;
    fn yk_challenge_response(yk: *const YK_KEY, yk_cmd: uint8_t, may_block: c_int,
                             challenge_len: c_uint, challenge: *const uint8_t,
                             response_len: c_uint, response: *mut u8) -> c_int;
}

/* When a YK_KEY goes out of scope, close the handle */
impl Drop for YK_KEY {
    fn drop(&mut self) {
        unsafe { yk_close_key(self) };
    }
}

/*****************************
 *  Safe interface to ykpers *
 *****************************/

#[derive(Debug)]
pub enum YubikeyError { InvalidYubikeySlot,
                        EmptyCRChallenge,
                        UnknownError }

impl Error for YubikeyError {
    fn description(&self) -> &str {
        match *self {
            YubikeyError::InvalidYubikeySlot => "The selected Yubikey slot is invalid. Valid are 1, 2",
            YubikeyError::EmptyCRChallenge   => "The specified challenge was empty",
            YubikeyError::UnknownError       => "An unknown error occured"
        }
}

impl Display for YubikeyError {
    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
        formatter.write_str(self.description())
    }
}

/* Opaque pointer to foreign Yubikey type. Under the hood this is just a handle
 *  for a USB device. */
pub type Yubikey = *const YK_KEY;

/* This function must be called at least once before using any of the Yubikey
 *  functionality. It initializes the Yubikey C library. */
pub fn yubikey_init() {
    unsafe { yk_init() };
}

/* Returns the first plugged in Yubikey. */
pub fn get_yubikey() -> Yubikey {
    unsafe { yk_open_first_key() }
}

/* Returns the serial number of the Yubikey */
pub fn get_serial(yk: Yubikey) -> u32 {
    unsafe {
        let mut serial: c_uint = 0;
        yk_get_serial(yk, 0, 0, &mut serial);
        serial as u32
    }
}

pub fn challenge_response(yk: Yubikey, slot: u8, challenge: &[u8], may_block: bool) -> Result<String, YubikeyError> {
    // Yubikey commands are defined in ykdef.h
    let yk_cmd = try!(match slot {
        1 => Ok(0x30), //#define SLOT_CHAL_HMAC1 0x30
        2 => Ok(0x38), //#define SLOT_CHAL_HMAC2 0x38
        _ => Err(YubikeyError::InvalidYubikeySlot)
    });

    let challenge_len = challenge.len() as c_uint;

    if challenge_len == 0 {
        return Err(YubikeyError::EmptyCRChallenge);
    }

    let response_len = 64; // Length of HMAC-SHA1 response

    let mut response = Vec::with_capacity(response_len as usize);

    let rc = unsafe {
        let cr_status = yk_challenge_response(yk, yk_cmd, may_block as c_int,
                                              challenge_len, challenge.as_ptr(),
                                              response_len, response.as_mut_ptr());

        response.set_len(response_len as usize);
        cr_status
    };

    if rc == 0 {
        // There's some way to get a better error code from the Yubikey, but
        // that's not needed right now.
        Err(YubikeyError::UnknownError)
    } else {
        // There must be a better way to do this, but I'm not sure what it is yet
        let response_str =
            String::from_str(response.as_slice().to_hex().as_str().slice_chars(0,40));
        Ok(response_str)
    }
}
<|endoftext|>


<commit_before>/*
 * This is a WIP of implementing an alternative
 * serialization strategy. It attempts to follow Vitalik's
 * "simpleserialize" format here:
 * https://github.com/ethereum/beacon_chain/blob/master/beacon_chain/utils/simpleserialize.py
 *
 * This implementation is not final and would almost certainly
 * have issues.
 */
extern crate bytes;
extern crate ethereum_types;

mod impls;

pub const LENGTH_BYTES: usize = 4;

pub trait Encodable {
    fn ssz_append(&self, s: &mut SszStream);
}

pub struct SszStream {
    buffer: Vec<u8>
}

impl SszStream {
    /// Create a new, empty steam for writing ssz values.
    pub fn new() -> Self {
        SszStream {
            buffer: Vec::new()
        }
    }

    /// Append some ssz encodable value to the stream.
    pub fn append<E>(&mut self, value: &E) -> &mut Self
        where E: Encodable
    {
        value.ssz_append(self);
        self
    }

    pub fn extend_buffer(&mut self, vec: &Vec<u8>) {
        self.buffer.extend_from_slice(
            &encode_length(vec.len(),
            LENGTH_BYTES));
        self.buffer.extend_from_slice(&vec);
    }

    /// Append some vector (list) of encoded values to the stream.
    pub fn append_vec<E>(&mut self, vec: &Vec<E>)
        where E: Encodable
    {
        self.buffer.extend_from_slice(&encode_length(vec.len(), LENGTH_BYTES));
        for v in vec {
            v.ssz_append(self);
        }
    }

    /// Append some array (list) of encoded values to the stream.
    pub fn append_encoded_array(&mut self, a: &mut [u8]) {
        let len = a.len();
        self.buffer.append(&mut encode_length(len, LENGTH_BYTES));
        self.buffer.extend_from_slice(&a[0..len]);
    }

    /// Consume the stream and return the underlying bytes.
    pub fn drain(self) -> Vec<u8> {
        self.buffer
    }
}

fn encode_length(len: usize, length_bytes: usize) -> Vec<u8> {
    assert!(length_bytes > 0);  // For sanity
    assert!((len as usize) < 2usize.pow(length_bytes as u32 * 8));
    let mut header: Vec<u8> = vec![0; length_bytes];
    for i in 0..length_bytes {
        let offset = (length_bytes - i - 1) * 8;
        header[i] = ((len >> offset) & 0xff) as u8;
    };
    header
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::ethereum_types::{ H256, U256 };

    #[test]
    #[should_panic]
    fn test_encode_length_0_bytes_panic() {
        encode_length(0, 0);
    }

    #[test]
    fn test_encode_length_4_bytes() {
        assert_eq!(
            encode_length(0, 4),
            vec![0; 4]
        );
        assert_eq!(
            encode_length(1, 4),
            vec![0, 0, 0, 1]
        );
        assert_eq!(
            encode_length(255, 4),
            vec![0, 0, 0, 255]
        );
        assert_eq!(
            encode_length(256, 4),
            vec![0, 0, 1, 0]
        );
        assert_eq!(
            encode_length(4294967295, 4),  // 2^(4*8) - 1
            vec![255, 255, 255, 255]
        );
    }

    #[test]
    #[should_panic]
    fn test_encode_length_4_bytes_panic() {
        encode_length(4294967296, 4);  // 2^(4*8)
    }

    #[test]
    fn test_serialization() {
        pub struct TestStruct {
            pub one: u32,
            pub two: H256,
            pub three: u64,
            pub four: U256,
        }

        impl Encodable for TestStruct {
            fn ssz_append(&self, s: &mut SszStream) {
                s.append(&self.one);
                s.append(&self.two);
                s.append(&self.three);
                s.append(&self.four);
            }
        }

        let t = TestStruct {
            one: 1,
            two: H256::zero(),
            three: 100,
            four: U256::zero(),
        };

        let mut s = SszStream::new();
        s.append(&t);
        let e = s.drain();

        let expected_len = {
            4 + 4 +
            4 + 32 +
            4 + 8 +
            4 + 32
        };

        assert_eq!(e[0..4], [0, 0, 0, 4]);
        assert_eq!(e[4..8], [0, 0, 0, 1]);
        assert_eq!(e[8..12], [0, 0, 0, 32]);
        assert_eq!(e[12..44], [0; 32]);
        assert_eq!(e[44..48], [0, 0, 0, 8]);
        assert_eq!(e[48..56], [0, 0, 0, 0, 0, 0, 0, 100]);
        assert_eq!(e[56..60], [0, 0, 0, 32]);
        assert_eq!(e[60..92], [0; 32]);
        assert_eq!(e.len(), expected_len);
    }
}
<commit_msg>Implement ssz length decoding<commit_after>/*
 * This is a WIP of implementing an alternative
 * serialization strategy. It attempts to follow Vitalik's
 * "simpleserialize" format here:
 * https://github.com/ethereum/beacon_chain/blob/master/beacon_chain/utils/simpleserialize.py
 *
 * This implementation is not final and would almost certainly
 * have issues.
 */
extern crate bytes;
extern crate ethereum_types;

mod impls;

pub const LENGTH_BYTES: usize = 4;

pub trait Encodable {
    fn ssz_append(&self, s: &mut SszStream);
}

pub struct SszStream {
    buffer: Vec<u8>
}

#[derive(Debug)]
pub enum DecodeError {
    TooShort,
}

impl SszStream {
    /// Create a new, empty steam for writing ssz values.
    pub fn new() -> Self {
        SszStream {
            buffer: Vec::new()
        }
    }

    /// Append some ssz encodable value to the stream.
    pub fn append<E>(&mut self, value: &E) -> &mut Self
        where E: Encodable
    {
        value.ssz_append(self);
        self
    }

    pub fn extend_buffer(&mut self, vec: &Vec<u8>) {
        self.buffer.extend_from_slice(
            &encode_length(vec.len(),
            LENGTH_BYTES));
        self.buffer.extend_from_slice(&vec);
    }

    /// Append some vector (list) of encoded values to the stream.
    pub fn append_vec<E>(&mut self, vec: &Vec<E>)
        where E: Encodable
    {
        self.buffer.extend_from_slice(&encode_length(vec.len(), LENGTH_BYTES));
        for v in vec {
            v.ssz_append(self);
        }
    }

    /// Append some array (list) of encoded values to the stream.
    pub fn append_encoded_array(&mut self, a: &mut [u8]) {
        let len = a.len();
        self.buffer.append(&mut encode_length(len, LENGTH_BYTES));
        self.buffer.extend_from_slice(&a[0..len]);
    }

    /// Consume the stream and return the underlying bytes.
    pub fn drain(self) -> Vec<u8> {
        self.buffer
    }
}

fn encode_length(len: usize, length_bytes: usize) -> Vec<u8> {
    assert!(length_bytes > 0);  // For sanity
    assert!((len as usize) < 2usize.pow(length_bytes as u32 * 8));
    let mut header: Vec<u8> = vec![0; length_bytes];
    for i in 0..length_bytes {
        let offset = (length_bytes - i - 1) * 8;
        header[i] = ((len >> offset) & 0xff) as u8;
    };
    header
}

fn decode_length(bytes: &Vec<u8>, length_bytes: usize)
    -> Result<usize, DecodeError>
{
    if bytes.len() < length_bytes {
        return Err(DecodeError::TooShort);
    };
    let mut len: usize = 0;
    for i in 0..length_bytes {
        let offset = (length_bytes - i - 1) * 8;
        len = ((bytes[i] as usize) << offset) | len;
    };
    Ok(len)
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::ethereum_types::{ H256, U256 };

    #[test]
    #[should_panic]
    fn test_encode_length_0_bytes_panic() {
        encode_length(0, 0);
    }

    #[test]
    fn test_encode_length_4_bytes() {
        assert_eq!(
            encode_length(0, 4),
            vec![0; 4]
        );
        assert_eq!(
            encode_length(1, 4),
            vec![0, 0, 0, 1]
        );
        assert_eq!(
            encode_length(255, 4),
            vec![0, 0, 0, 255]
        );
        assert_eq!(
            encode_length(256, 4),
            vec![0, 0, 1, 0]
        );
        assert_eq!(
            encode_length(4294967295, 4),  // 2^(4*8) - 1
            vec![255, 255, 255, 255]
        );
    }

    #[test]
    #[should_panic]
    fn test_encode_length_4_bytes_panic() {
        encode_length(4294967296, 4);  // 2^(4*8)
    }

    #[test]
    fn test_decode_length() {
        let decoded = decode_length(
            &vec![0, 0, 0, 1],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 1);

        let decoded = decode_length(
            &vec![0, 0, 1, 0],
            LENGTH_BYTES);
        assert_eq!(decoded.unwrap(), 256);
    }

    #[test]
    fn test_encode_decode_length() {
        let params: Vec<usize> = vec![
            0,
            1,
            2,
            3,
            7,
            8,
            16,
            2^8,
            2^8 + 1,
            2^16,
            2^16 + 1,
            2^24,
            2^24 + 1,
            2^32,
        ];
        for i in params {
            let decoded = decode_length(
                &encode_length(i, LENGTH_BYTES),
                LENGTH_BYTES).unwrap();
            assert_eq!(i, decoded);
        }
    }

    #[test]
    fn test_serialization() {
        pub struct TestStruct {
            pub one: u32,
            pub two: H256,
            pub three: u64,
            pub four: U256,
        }

        impl Encodable for TestStruct {
            fn ssz_append(&self, s: &mut SszStream) {
                s.append(&self.one);
                s.append(&self.two);
                s.append(&self.three);
                s.append(&self.four);
            }
        }

        let t = TestStruct {
            one: 1,
            two: H256::zero(),
            three: 100,
            four: U256::zero(),
        };

        let mut s = SszStream::new();
        s.append(&t);
        let e = s.drain();

        let expected_len = {
            4 + 4 +
            4 + 32 +
            4 + 8 +
            4 + 32
        };

        assert_eq!(e[0..4], [0, 0, 0, 4]);
        assert_eq!(e[4..8], [0, 0, 0, 1]);
        assert_eq!(e[8..12], [0, 0, 0, 32]);
        assert_eq!(e[12..44], [0; 32]);
        assert_eq!(e[44..48], [0, 0, 0, 8]);
        assert_eq!(e[48..56], [0, 0, 0, 0, 0, 0, 0, 100]);
        assert_eq!(e[56..60], [0, 0, 0, 32]);
        assert_eq!(e[60..92], [0; 32]);
        assert_eq!(e.len(), expected_len);
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;

use cobalt_config::SortOrder;

pub use cobalt_config::DateIndex;
pub use cobalt_config::Include;

#[derive(Clone, Debug, serde::Serialize, PartialEq, Eq)]
#[serde(deny_unknown_fields, default)]
pub struct PaginationConfig {
    pub include: Include,
    pub per_page: i32,
    pub front_permalink: cobalt_config::Permalink,
    pub permalink_suffix: String,
    pub order: SortOrder,
    pub sort_by: Vec<String>,
    pub date_index: Vec<DateIndex>,
}

impl PaginationConfig {
    pub fn from_config(
        config: cobalt_config::Pagination,
        permalink: &cobalt_config::Permalink,
    ) -> Option<Self> {
        let config = config.merge(&cobalt_config::Pagination::with_defaults());
        let cobalt_config::Pagination {
            include,
            per_page,
            permalink_suffix,
            order,
            sort_by,
            date_index,
        } = config;
        let include = include.expect("default applied");
        let per_page = per_page.expect("default applied");
        let permalink_suffix = permalink_suffix.expect("default applied");
        let order = order.expect("default applied");
        let sort_by = sort_by.expect("default applied");
        let date_index = date_index.expect("default applied");

        if include == Include::None {
            return None;
        }
        Some(Self {
            include,
            per_page,
            front_permalink: permalink.to_owned(),
            permalink_suffix,
            order,
            sort_by,
            date_index,
        })
    }
}

// TODO to be replaced by a call to `is_sorted()` once it's stabilized
pub fn is_date_index_sorted(v: &Vec<DateIndex>) -> bool {
    let mut copy = v.clone();
    copy.sort_unstable();
    copy.eq(v)
}
<commit_msg>style: Remove dead code<commit_after><|endoftext|>