<commit_before>use basic::{Type as PhysicalType, Repetition, LogicalType};
use errors::Result;
use errors::ParquetError;
use parquet_thrift::parquet::SchemaElement;

enum TypeKind {
  PRIMITIVE,
  GROUP
}

// TODO: how can we specify a return type for the methods?
// This seems tricky since Rust doesn't allow generic methods for trait objects.
pub trait TypeVisitor {
  fn visit_primitive_type(&mut self, tp: &mut PrimitiveType);
  fn visit_group_type(&mut self, tp: &mut GroupType);
}

/// A trait for a logical schema type. Structs who implement
/// this needs to implement the `get_basic_info()` function.
pub trait Type {
  fn is_primitive(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::PRIMITIVE => true,
      _ => false
    }
  }

  fn is_group(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::GROUP => true,
      _ => false
    }
  }

  fn name(&self) -> &str {
    return &self.get_basic_info().name;
  }

  fn repetition(&self) -> Repetition {
    return self.get_basic_info().repetition;
  }

  fn logical_type(&self) -> LogicalType {
    return self.get_basic_info().logical_type;
  }

  fn id(&self) -> Option<i32> {
    return self.get_basic_info().id;
  }

  /// Get the basic type information.
  fn get_basic_info(&self) -> &BasicTypeInfo;

  /// Accept a `TypeVisitor` to visit the concrete type of this trait.
  fn accept(&mut self, visitor: &mut TypeVisitor);
}

/// Basic type info. This contains information such as the name of the type,
/// the repetition level, the logical type and the kind of the type (group, primitive).
pub struct BasicTypeInfo {
  kind: TypeKind,
  name: String,
  repetition: Repetition,
  logical_type: LogicalType,
  id: Option<i32>
}

/// Metadata for a decimal type (scale, precision).
struct DecimalMetadata {
  scale: i32,
  precision: i32
}

/// Representation of primitive types
// TODO: add equality
pub struct PrimitiveType {
  basic_info: BasicTypeInfo,
  physical_type: PhysicalType,
  type_length: i32,
  decimal_metadata: Option<DecimalMetadata>
}

impl PrimitiveType {
  pub fn new(name: &str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             precision: i32, scale: i32, id: Option<i32>) -> Result<Self> {
    let mut decimal_metadata = None;
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: String::from(name), repetition: repetition,
      logical_type: logical_type, id: id};

    match logical_type {
      LogicalType::NONE => {
        decimal_metadata = Some(DecimalMetadata{precision, scale});
      },
      LogicalType::UTF8 | LogicalType::BSON | LogicalType::JSON => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(parse_err!("{} can only annotate BYTE_ARRAY fields", logical_type))
        }
      },
      LogicalType::DECIMAL => {
        match physical_type {
          PhysicalType::INT32 | PhysicalType::INT64 | PhysicalType::BYTE_ARRAY |
          PhysicalType::FIXED_LEN_BYTE_ARRAY => (),
          _ => {
            return Err(parse_err!("DECIMAL can only annotate INT32, INT64, BYTE_ARRAY and FIXED"))
          }
        };
        if precision < 0 {
          return Err(parse_err!("Invalid DECIMAL precision: {}", precision))
        }
        if scale < 0 {
          return Err(parse_err!("Invalid DECIMAL scale: {}", scale))
        }
        if scale > precision {
          return Err(parse_err!(
            "Invalid DECIMAL: scale ({}) cannot be greater than precision ({})",
            scale, precision))
        }
        decimal_metadata = Some(DecimalMetadata{precision, scale})
      }
      LogicalType::DATE | LogicalType::TIME_MILLIS | LogicalType::UINT_8 |
      LogicalType::UINT_16 | LogicalType::UINT_32 |
      LogicalType::INT_8 | LogicalType::INT_16 | LogicalType::INT_32 => {
        if physical_type != PhysicalType::INT32 {
          return Err(parse_err!("{} can only annotate INT32", logical_type))
        }
      }
      LogicalType::TIME_MICROS | LogicalType::TIMESTAMP_MILLIS |
      LogicalType::TIMESTAMP_MICROS | LogicalType::UINT_64 | LogicalType::INT_64 => {
        if physical_type != PhysicalType::INT64 {
          return Err(parse_err!("{} can only annotate INT64", logical_type))
        }
      }
      LogicalType::INTERVAL => {
        if physical_type != PhysicalType::FIXED_LEN_BYTE_ARRAY || length != 12 {
          return Err(parse_err!("INTERVAL can only annotate FIXED(12)"))
        }
      }
      LogicalType::ENUM => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(parse_err!("ENUM can only annotate BYTE_ARRAY fields"))
        }
      }
      _ => {
        return Err(parse_err!("{} cannot be applied to a primitive type", logical_type))
      }
    };
    if physical_type == PhysicalType::FIXED_LEN_BYTE_ARRAY && length < 0 {
      return Err(parse_err!("Invalid FIXED_LEN_BYTE_ARRAY length: {}", length))
    }
    Ok(PrimitiveType{
      basic_info: basic_info,
      physical_type: physical_type,
      type_length: length,
      decimal_metadata: decimal_metadata
    })
  }

  pub fn physical_type(&self) -> PhysicalType {
    self.physical_type
  }

  fn decimal_metadata(&self) -> &Option<DecimalMetadata> {
    &self.decimal_metadata
  }
}

impl Type for PrimitiveType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }

  fn accept(&mut self, visitor: &mut TypeVisitor) {
    visitor.visit_primitive_type(self)
  }
}

/// Representation of group types
// TODO: add equality
pub struct GroupType {
  basic_info: BasicTypeInfo,
  fields: Vec<Box<Type>>
}

impl GroupType {
  pub fn new(name: &str, repetition: Repetition,
             logical_type: LogicalType,
             fields: Vec<Box<Type>>, id: Option<i32>) -> Result<Self> {
    let basic_info = BasicTypeInfo{
      kind: TypeKind::GROUP, name: String::from(name), repetition: repetition,
      logical_type: logical_type, id: id};
    Ok(GroupType{
      basic_info: basic_info,
      fields: fields
    })
  }

  pub fn fields(&mut self) -> &mut Vec<Box<Type>> {
    &mut self.fields
  }

  pub fn num_fields(&self) -> usize {
    return self.fields.len()
  }

  pub fn field(&mut self, index: usize) -> &mut Box<Type> {
    return &mut self.fields[index]
  }
}

impl Type for GroupType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }

  fn accept(&mut self, visitor: &mut TypeVisitor) {
    visitor.visit_group_type(self)
  }
}

/// Conversion from Thrift equivalents

pub fn from_thrift(elements: &mut [SchemaElement]) -> Result<Vec<Box<Type>>> {
  let mut index = 1;
  let mut result = Vec::new();
  // TODO: do we need to process the root element?
  while index < elements.len() {
    let t = from_thrift_helper(elements, index)?;
    index = t.0;
    result.push(t.1);
  }
  Ok(result)
}

/// Construct a new Type from the `elements`, starting at index `index`.
/// The first result is the starting index for the next Type after this one.
/// If it is equal to `elements.len()`, then this Type is the last one.
/// The second result is the result Type.
fn from_thrift_helper(elements: &mut [SchemaElement], index: usize) -> Result<(usize, Box<Type>)> {
  if index < 0 {
    return Err(schema_err!("Illegal index ({}). Expect to be non-negative.", index))
  }
  if index > elements.len() {
    return Err(schema_err!("Index out of bound, index = {}, len = {}", index, elements.len()))
  }
  if elements[index].repetition_type.is_none() {
    return Err(schema_err!("Repetition is undefined"));
  }
  let repetition = Repetition::from(elements[index].repetition_type.unwrap());
  let logical_type = LogicalType::from(elements[index].converted_type);
  let field_id = elements[index].field_id;
  match elements[index].num_children {
    None => {
      // primitive type
      let physical_type = PhysicalType::from(elements[index].type_.unwrap());
      let length = elements[index].type_length.unwrap_or(-1);
      let scale = elements[index].scale.unwrap_or(-1);
      let precision = elements[index].precision.unwrap_or(-1);
      let name = &elements[index].name;
      let result = PrimitiveType::new(
        name, repetition, physical_type, logical_type, length, precision, scale, field_id)?;
      Ok((index + 1, Box::new(result)))
    },
    Some(n) => {
      let mut fields: Vec<Box<Type>> = Vec::new();
      let mut next_index = index + 1;
      for _ in 0..n {
        let child_result = from_thrift_helper(elements, next_index as usize)?;
        next_index = child_result.0;
        fields.push(child_result.1);
      }
      let name = &elements[index].name;
      let result = GroupType::new(
        name, repetition, logical_type, fields, field_id)?;
      Ok((next_index, Box::new(result)))
    }
  }
}

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

  #[test]
  fn test_primitive_type() {
    let mut result = PrimitiveType::new(
      "foo", Repetition::OPTIONAL, PhysicalType::INT32,
      LogicalType::INT_32, 0, 0, 0, Some(0));
    assert!(result.is_ok());

    if let Ok(tp) = result {
      assert!(tp.is_primitive());
      assert!(!tp.is_group());
      assert_eq!(tp.repetition(), Repetition::OPTIONAL);
      assert_eq!(tp.logical_type(), LogicalType::INT_32);
      assert_eq!(tp.physical_type(), PhysicalType::INT32);
      assert_eq!(tp.id(), Some(0));
      assert!(tp.decimal_metadata().is_none());
    }

    // Test illegal inputs
    result = PrimitiveType::new(
      "foo", Repetition::REPEATED, PhysicalType::INT64,
      LogicalType::BSON, 0, 0, 0, None);
    assert!(result.is_err());
    if let Err(e) = result {
      assert_eq!(e.description(), "BSON can only annotate BYTE_ARRAY fields");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT96,
      LogicalType::DECIMAL, 0, -1, -1, None);
    assert!(result.is_err());
    if let Err(e) = result {
      assert_eq!(e.description(), "DECIMAL can only annotate INT32, INT64, BYTE_ARRAY and FIXED");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, -1, -1, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid DECIMAL precision: -1");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, 0, -1, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid DECIMAL scale: -1");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, 1, 2, None);
    if let Err(e) = result {
      assert_eq!(
        e.description(),
        "Invalid DECIMAL: scale (2) cannot be greater than precision (1)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT64,
      LogicalType::UINT_8, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "UINT_8 can only annotate INT32");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::TIME_MICROS, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "TIME_MICROS can only annotate INT64");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::INTERVAL, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "INTERVAL can only annotate FIXED(12)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::FIXED_LEN_BYTE_ARRAY,
      LogicalType::INTERVAL, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "INTERVAL can only annotate FIXED(12)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::ENUM, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "ENUM can only annotate BYTE_ARRAY fields");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::MAP, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "MAP cannot be applied to a primitive type");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::FIXED_LEN_BYTE_ARRAY,
      LogicalType::DECIMAL, -1, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid FIXED_LEN_BYTE_ARRAY length: -1");
    }
  }

  #[test]
  fn test_group_type() {
    // TODO: why Rust require an explicit type annotation here?
    let mut fields: Vec<Box<Type>> = Vec::new();
    let f1 = PrimitiveType::new(
      "f1", Repetition::OPTIONAL, PhysicalType::INT32,
      LogicalType::INT_32, 0, 0, 0, Some(0));
    let f2 = PrimitiveType::new(
      "f2", Repetition::OPTIONAL, PhysicalType::BYTE_ARRAY,
      LogicalType::UTF8, 0, 0, 0, Some(1));
    assert!(f1.is_ok());
    assert!(f2.is_ok());
    fields.push(Box::new(f1.unwrap()));
    fields.push(Box::new(f2.unwrap()));
    let result = GroupType::new(
      "foo", Repetition::REPEATED, LogicalType::NONE, fields, Some(1));
    assert!(result.is_ok());
    if let Ok(tp) = result {
      assert_eq!(tp.repetition(), Repetition::REPEATED);
      assert_eq!(tp.logical_type(), LogicalType::NONE);
      assert_eq!(tp.id(), Some(1));
      assert_eq!(tp.num_fields(), 2);
      // TODO: test fields equality once that is implemented.
    }
  }
}
<commit_msg>Remove unnecessary "return"<commit_after>use basic::{Type as PhysicalType, Repetition, LogicalType};
use errors::Result;
use errors::ParquetError;
use parquet_thrift::parquet::SchemaElement;

enum TypeKind {
  PRIMITIVE,
  GROUP
}

// TODO: how can we specify a return type for the methods?
// This seems tricky since Rust doesn't allow generic methods for trait objects.
pub trait TypeVisitor {
  fn visit_primitive_type(&mut self, tp: &mut PrimitiveType);
  fn visit_group_type(&mut self, tp: &mut GroupType);
}

/// A trait for a logical schema type. Structs who implement
/// this needs to implement the `get_basic_info()` function.
pub trait Type {
  fn is_primitive(&self) -> bool {
    match self.get_basic_info().kind {
      TypeKind::PRIMITIVE => true,
      _ => false
    }
  }

  fn is_group(&self) -> bool {
    match self.get_basic_info().kind {
      TypeKind::GROUP => true,
      _ => false
    }
  }

  fn name(&self) -> &str {
    &self.get_basic_info().name
  }

  fn repetition(&self) -> Repetition {
    self.get_basic_info().repetition
  }

  fn logical_type(&self) -> LogicalType {
    self.get_basic_info().logical_type
  }

  fn id(&self) -> Option<i32> {
    self.get_basic_info().id
  }

  /// Get the basic type information.
  fn get_basic_info(&self) -> &BasicTypeInfo;

  /// Accept a `TypeVisitor` to visit the concrete type of this trait.
  fn accept(&mut self, visitor: &mut TypeVisitor);
}

/// Basic type info. This contains information such as the name of the type,
/// the repetition level, the logical type and the kind of the type (group, primitive).
pub struct BasicTypeInfo {
  kind: TypeKind,
  name: String,
  repetition: Repetition,
  logical_type: LogicalType,
  id: Option<i32>
}

/// Metadata for a decimal type (scale, precision).
struct DecimalMetadata {
  scale: i32,
  precision: i32
}

/// Representation of primitive types
// TODO: add equality
pub struct PrimitiveType {
  basic_info: BasicTypeInfo,
  physical_type: PhysicalType,
  type_length: i32,
  decimal_metadata: Option<DecimalMetadata>
}

impl PrimitiveType {
  pub fn new(name: &str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             precision: i32, scale: i32, id: Option<i32>) -> Result<Self> {
    let mut decimal_metadata = None;
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: String::from(name), repetition: repetition,
      logical_type: logical_type, id: id};

    match logical_type {
      LogicalType::NONE => {
        decimal_metadata = Some(DecimalMetadata{precision, scale});
      },
      LogicalType::UTF8 | LogicalType::BSON | LogicalType::JSON => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(parse_err!("{} can only annotate BYTE_ARRAY fields", logical_type))
        }
      },
      LogicalType::DECIMAL => {
        match physical_type {
          PhysicalType::INT32 | PhysicalType::INT64 | PhysicalType::BYTE_ARRAY |
          PhysicalType::FIXED_LEN_BYTE_ARRAY => (),
          _ => {
            return Err(parse_err!("DECIMAL can only annotate INT32, INT64, BYTE_ARRAY and FIXED"))
          }
        };
        if precision < 0 {
          return Err(parse_err!("Invalid DECIMAL precision: {}", precision))
        }
        if scale < 0 {
          return Err(parse_err!("Invalid DECIMAL scale: {}", scale))
        }
        if scale > precision {
          return Err(parse_err!(
            "Invalid DECIMAL: scale ({}) cannot be greater than precision ({})",
            scale, precision))
        }
        decimal_metadata = Some(DecimalMetadata{precision, scale})
      }
      LogicalType::DATE | LogicalType::TIME_MILLIS | LogicalType::UINT_8 |
      LogicalType::UINT_16 | LogicalType::UINT_32 |
      LogicalType::INT_8 | LogicalType::INT_16 | LogicalType::INT_32 => {
        if physical_type != PhysicalType::INT32 {
          return Err(parse_err!("{} can only annotate INT32", logical_type))
        }
      }
      LogicalType::TIME_MICROS | LogicalType::TIMESTAMP_MILLIS |
      LogicalType::TIMESTAMP_MICROS | LogicalType::UINT_64 | LogicalType::INT_64 => {
        if physical_type != PhysicalType::INT64 {
          return Err(parse_err!("{} can only annotate INT64", logical_type))
        }
      }
      LogicalType::INTERVAL => {
        if physical_type != PhysicalType::FIXED_LEN_BYTE_ARRAY || length != 12 {
          return Err(parse_err!("INTERVAL can only annotate FIXED(12)"))
        }
      }
      LogicalType::ENUM => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(parse_err!("ENUM can only annotate BYTE_ARRAY fields"))
        }
      }
      _ => {
        return Err(parse_err!("{} cannot be applied to a primitive type", logical_type))
      }
    };
    if physical_type == PhysicalType::FIXED_LEN_BYTE_ARRAY && length < 0 {
      return Err(parse_err!("Invalid FIXED_LEN_BYTE_ARRAY length: {}", length))
    }
    Ok(PrimitiveType{
      basic_info: basic_info,
      physical_type: physical_type,
      type_length: length,
      decimal_metadata: decimal_metadata
    })
  }

  pub fn physical_type(&self) -> PhysicalType {
    self.physical_type
  }

  fn decimal_metadata(&self) -> &Option<DecimalMetadata> {
    &self.decimal_metadata
  }
}

impl Type for PrimitiveType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    &self.basic_info
  }

  fn accept(&mut self, visitor: &mut TypeVisitor) {
    visitor.visit_primitive_type(self)
  }
}

/// Representation of group types
// TODO: add equality
pub struct GroupType {
  basic_info: BasicTypeInfo,
  fields: Vec<Box<Type>>
}

impl GroupType {
  pub fn new(name: &str, repetition: Repetition,
             logical_type: LogicalType,
             fields: Vec<Box<Type>>, id: Option<i32>) -> Result<Self> {
    let basic_info = BasicTypeInfo{
      kind: TypeKind::GROUP, name: String::from(name), repetition: repetition,
      logical_type: logical_type, id: id};
    Ok(GroupType{
      basic_info: basic_info,
      fields: fields
    })
  }

  pub fn fields(&mut self) -> &mut Vec<Box<Type>> {
    &mut self.fields
  }

  pub fn num_fields(&self) -> usize {
    self.fields.len()
  }

  pub fn field(&mut self, index: usize) -> &mut Box<Type> {
    &mut self.fields[index]
  }
}

impl Type for GroupType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    &self.basic_info
  }

  fn accept(&mut self, visitor: &mut TypeVisitor) {
    visitor.visit_group_type(self)
  }
}

/// Conversion from Thrift equivalents

pub fn from_thrift(elements: &mut [SchemaElement]) -> Result<Vec<Box<Type>>> {
  let mut index = 1;
  let mut result = Vec::new();
  // TODO: do we need to process the root element?
  while index < elements.len() {
    let t = from_thrift_helper(elements, index)?;
    index = t.0;
    result.push(t.1);
  }
  Ok(result)
}

/// Construct a new Type from the `elements`, starting at index `index`.
/// The first result is the starting index for the next Type after this one.
/// If it is equal to `elements.len()`, then this Type is the last one.
/// The second result is the result Type.
fn from_thrift_helper(elements: &mut [SchemaElement], index: usize) -> Result<(usize, Box<Type>)> {
  if index < 0 {
    return Err(schema_err!("Illegal index ({}). Expect to be non-negative.", index))
  }
  if index > elements.len() {
    return Err(schema_err!("Index out of bound, index = {}, len = {}", index, elements.len()))
  }
  if elements[index].repetition_type.is_none() {
    return Err(schema_err!("Repetition is undefined"));
  }
  let repetition = Repetition::from(elements[index].repetition_type.unwrap());
  let logical_type = LogicalType::from(elements[index].converted_type);
  let field_id = elements[index].field_id;
  match elements[index].num_children {
    None => {
      // primitive type
      let physical_type = PhysicalType::from(elements[index].type_.unwrap());
      let length = elements[index].type_length.unwrap_or(-1);
      let scale = elements[index].scale.unwrap_or(-1);
      let precision = elements[index].precision.unwrap_or(-1);
      let name = &elements[index].name;
      let result = PrimitiveType::new(
        name, repetition, physical_type, logical_type, length, precision, scale, field_id)?;
      Ok((index + 1, Box::new(result)))
    },
    Some(n) => {
      let mut fields: Vec<Box<Type>> = Vec::new();
      let mut next_index = index + 1;
      for _ in 0..n {
        let child_result = from_thrift_helper(elements, next_index as usize)?;
        next_index = child_result.0;
        fields.push(child_result.1);
      }
      let name = &elements[index].name;
      let result = GroupType::new(
        name, repetition, logical_type, fields, field_id)?;
      Ok((next_index, Box::new(result)))
    }
  }
}

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

  #[test]
  fn test_primitive_type() {
    let mut result = PrimitiveType::new(
      "foo", Repetition::OPTIONAL, PhysicalType::INT32,
      LogicalType::INT_32, 0, 0, 0, Some(0));
    assert!(result.is_ok());

    if let Ok(tp) = result {
      assert!(tp.is_primitive());
      assert!(!tp.is_group());
      assert_eq!(tp.repetition(), Repetition::OPTIONAL);
      assert_eq!(tp.logical_type(), LogicalType::INT_32);
      assert_eq!(tp.physical_type(), PhysicalType::INT32);
      assert_eq!(tp.id(), Some(0));
      assert!(tp.decimal_metadata().is_none());
    }

    // Test illegal inputs
    result = PrimitiveType::new(
      "foo", Repetition::REPEATED, PhysicalType::INT64,
      LogicalType::BSON, 0, 0, 0, None);
    assert!(result.is_err());
    if let Err(e) = result {
      assert_eq!(e.description(), "BSON can only annotate BYTE_ARRAY fields");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT96,
      LogicalType::DECIMAL, 0, -1, -1, None);
    assert!(result.is_err());
    if let Err(e) = result {
      assert_eq!(e.description(), "DECIMAL can only annotate INT32, INT64, BYTE_ARRAY and FIXED");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, -1, -1, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid DECIMAL precision: -1");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, 0, -1, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid DECIMAL scale: -1");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::DECIMAL, 0, 1, 2, None);
    if let Err(e) = result {
      assert_eq!(
        e.description(),
        "Invalid DECIMAL: scale (2) cannot be greater than precision (1)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT64,
      LogicalType::UINT_8, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "UINT_8 can only annotate INT32");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::TIME_MICROS, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "TIME_MICROS can only annotate INT64");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::BYTE_ARRAY,
      LogicalType::INTERVAL, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "INTERVAL can only annotate FIXED(12)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::FIXED_LEN_BYTE_ARRAY,
      LogicalType::INTERVAL, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "INTERVAL can only annotate FIXED(12)");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::ENUM, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "ENUM can only annotate BYTE_ARRAY fields");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::INT32,
      LogicalType::MAP, 0, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "MAP cannot be applied to a primitive type");
    }

    result = PrimitiveType::new(
      "foo", Repetition::REQUIRED, PhysicalType::FIXED_LEN_BYTE_ARRAY,
      LogicalType::DECIMAL, -1, 0, 0, None);
    if let Err(e) = result {
      assert_eq!(e.description(), "Invalid FIXED_LEN_BYTE_ARRAY length: -1");
    }
  }

  #[test]
  fn test_group_type() {
    // TODO: why Rust require an explicit type annotation here?
    let mut fields: Vec<Box<Type>> = Vec::new();
    let f1 = PrimitiveType::new(
      "f1", Repetition::OPTIONAL, PhysicalType::INT32,
      LogicalType::INT_32, 0, 0, 0, Some(0));
    let f2 = PrimitiveType::new(
      "f2", Repetition::OPTIONAL, PhysicalType::BYTE_ARRAY,
      LogicalType::UTF8, 0, 0, 0, Some(1));
    assert!(f1.is_ok());
    assert!(f2.is_ok());
    fields.push(Box::new(f1.unwrap()));
    fields.push(Box::new(f2.unwrap()));
    let result = GroupType::new(
      "foo", Repetition::REPEATED, LogicalType::NONE, fields, Some(1));
    assert!(result.is_ok());
    if let Ok(tp) = result {
      assert_eq!(tp.repetition(), Repetition::REPEATED);
      assert_eq!(tp.logical_type(), LogicalType::NONE);
      assert_eq!(tp.id(), Some(1));
      assert_eq!(tp.num_fields(), 2);
      // TODO: test fields equality once that is implemented.
    }
  }
}
<|endoftext|>


<commit_before>use game::{Position, Move};
use types::{NumNodes, NumMoves, NumPlies};

#[derive(Clone, Debug)]
pub struct State {
    pub pos: Position,
    pub prev_pos: Option<Position>,
    pub prev_move: Option<Move>,
    pub param: Param,
}

#[derive(Clone, Debug)]
pub struct Param {
    pub ponder: bool,
    pub search_moves: Option<Vec<Move>>,
    pub depth: Option<NumPlies>,
    pub nodes: Option<NumNodes>,
    pub mate: Option<NumMoves>,
}
impl Param {
    pub fn new() -> Self {
        Param {
            ponder: false,
            search_moves: None,
            depth: None,
            nodes: None,
            mate: None,
        }
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Cmd {
    SetDebug(bool),
    PonderHit,
    Stop,
}

// TODO put actual data here
#[derive(Debug)]
pub struct Data(());
impl Data {
    pub fn one_node() -> Data { Data(()) }
    pub fn combine(self, _: Data) -> Data { Data(()) }
    pub fn increment(self) -> Data { Data(()) }
}
<commit_msg>Add NumNodes to search data<commit_after>use game::{Position, Move};
use types::{NumNodes, NumMoves, NumPlies};

#[derive(Clone, Debug)]
pub struct State {
    pub pos: Position,
    pub prev_pos: Option<Position>,
    pub prev_move: Option<Move>,
    pub param: Param,
}

#[derive(Clone, Debug)]
pub struct Param {
    pub ponder: bool,
    pub search_moves: Option<Vec<Move>>,
    pub depth: Option<NumPlies>,
    pub nodes: Option<NumNodes>,
    pub mate: Option<NumMoves>,
}
impl Param {
    pub fn new() -> Self {
        Param {
            ponder: false,
            search_moves: None,
            depth: None,
            nodes: None,
            mate: None,
        }
    }
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Cmd {
    SetDebug(bool),
    PonderHit,
    Stop,
}

// TODO put actual data here
#[derive(Debug)]
pub struct Data {
    pub nodes: NumNodes,
}
impl Data {
    pub fn one_node() -> Data { Data { nodes: NumNodes(1) } }
    pub fn combine(self, other: Data) -> Data {
        Data { nodes: NumNodes(self.nodes.0 + other.nodes.0) }
    }
    pub fn increment(self) -> Data {
        Data { nodes: NumNodes(self.nodes.0 + 1) }
    }
}
<|endoftext|>


<commit_before>//! Frequency (base unit hertz, s-1).

quantity! {
    /// Frequency (base unit hertz, s-1).
    quantity: Frequency; "frequency";
    /// Frequency dimension, s-1.
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        N1,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottahertz: prefix!(yotta); "YHz", "yottahertz", "yottahertz";
        @zettahertz: prefix!(zetta); "ZHz", "zettahertz", "zettahertz";
        @exahertz: prefix!(exa); "EHz", "exahertz", "exahertz";
        @petahertz: prefix!(peta); "PHz", "petahertz", "petahertz";
        @terahertz: prefix!(tera); "THz", "terahertz", "terahertz";
        @gigahertz: prefix!(giga); "GHz", "gigahertz", "gigahertz";
        @megahertz: prefix!(mega); "MHz", "megahertz", "megahertz";
        @kilohertz: prefix!(kilo); "kHz", "kilohertz", "kilohertz";
        @hectohertz: prefix!(hecto); "hHz", "hectohertz", "hectohertz";
        @decahertz: prefix!(deca); "daHz", "decahertz", "decahertz";
        /// The hertz is one cycle per second.
        @hertz: prefix!(none); "Hz", "hertz", "hertz";
        @decihertz: prefix!(deci); "dHz", "decihertz", "decihertz";
        @centihertz: prefix!(centi); "cHz", "centihertz", "centihertz";
        @millihertz: prefix!(milli); "mHz", "millihertz", "millihertz";
        @microhertz: prefix!(micro); "µHz", "microhertz", "microhertz";
        @nanohertz: prefix!(nano); "nHz", "nanohertz", "nanohertz";
        @picohertz: prefix!(pico); "pHz", "picohertz", "picohertz";
        @femtohertz: prefix!(femto); "fHz", "femtohertz", "femtohertz";
        @attohertz: prefix!(atto); "aHz", "attohertz", "attohertz";
        @zeptohertz: prefix!(zepto); "zHz", "zeptohertz", "zeptohertz";
        @yoctohertz: prefix!(yocto); "yHz", "yoctohertz", "yoctohertz";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use num::One;
        use si::quantities::*;
        use si::frequency as f;
        use si::time as t;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: Time<V> = V::one() / Frequency::new::<f::hertz>(V::one());
            let _: Frequency<V> = V::one() / Time::new::<t::second>(V::one());
        }

        #[test]
        fn check_units() {
            test::<t::yottasecond, f::yoctohertz>();
            test::<t::zettasecond, f::zeptohertz>();
            test::<t::exasecond, f::attohertz>();
            test::<t::petasecond, f::femtohertz>();
            test::<t::terasecond, f::picohertz>();
            test::<t::gigasecond, f::nanohertz>();
            test::<t::megasecond, f::microhertz>();
            test::<t::kilosecond, f::millihertz>();
            test::<t::hectosecond, f::centihertz>();
            test::<t::decasecond, f::decihertz>();
            test::<t::second, f::hertz>();
            test::<t::decisecond, f::decahertz>();
            test::<t::centisecond, f::hectohertz>();
            test::<t::millisecond, f::kilohertz>();
            test::<t::microsecond, f::megahertz>();
            test::<t::nanosecond, f::gigahertz>();
            test::<t::picosecond, f::terahertz>();
            test::<t::femtosecond, f::petahertz>();
            test::<t::attosecond, f::exahertz>();
            test::<t::zeptosecond, f::zettahertz>();
            test::<t::yoctosecond, f::yottahertz>();

            fn test<T: t::Conversion<V>, F: f::Conversion<V>>() {
                Test::assert_approx_eq(&(V::one() / Time::new::<T>(V::one())),
                    &Frequency::new::<F>(V::one()));
                Test::assert_approx_eq(&Time::new::<T>(V::one()),
                    &(V::one() / Frequency::new::<F>(V::one())));
            }
        }
    }
}
<commit_msg>Add respective frequency units for some time units.<commit_after>//! Frequency (base unit hertz, s-1).

quantity! {
    /// Frequency (base unit hertz, s-1).
    quantity: Frequency; "frequency";
    /// Frequency dimension, s-1.
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        N1,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottahertz: prefix!(yotta); "YHz", "yottahertz", "yottahertz";
        @zettahertz: prefix!(zetta); "ZHz", "zettahertz", "zettahertz";
        @exahertz: prefix!(exa); "EHz", "exahertz", "exahertz";
        @petahertz: prefix!(peta); "PHz", "petahertz", "petahertz";
        @terahertz: prefix!(tera); "THz", "terahertz", "terahertz";
        @gigahertz: prefix!(giga); "GHz", "gigahertz", "gigahertz";
        @megahertz: prefix!(mega); "MHz", "megahertz", "megahertz";
        @kilohertz: prefix!(kilo); "kHz", "kilohertz", "kilohertz";
        @hectohertz: prefix!(hecto); "hHz", "hectohertz", "hectohertz";
        @decahertz: prefix!(deca); "daHz", "decahertz", "decahertz";
        /// The hertz is one cycle per second.
        @hertz: prefix!(none); "Hz", "hertz", "hertz";
        @decihertz: prefix!(deci); "dHz", "decihertz", "decihertz";
        @centihertz: prefix!(centi); "cHz", "centihertz", "centihertz";
        @millihertz: prefix!(milli); "mHz", "millihertz", "millihertz";
        @microhertz: prefix!(micro); "µHz", "microhertz", "microhertz";
        @nanohertz: prefix!(nano); "nHz", "nanohertz", "nanohertz";
        @picohertz: prefix!(pico); "pHz", "picohertz", "picohertz";
        @femtohertz: prefix!(femto); "fHz", "femtohertz", "femtohertz";
        @attohertz: prefix!(atto); "aHz", "attohertz", "attohertz";
        @zeptohertz: prefix!(zepto); "zHz", "zeptohertz", "zeptohertz";
        @yoctohertz: prefix!(yocto); "yHz", "yoctohertz", "yoctohertz";

        @cycle_per_day: 1.157_407_407_407_407_4_E-5; "1/d", "cycle per day", "cycles per day";
        @cycle_per_hour: 2.777_777_777_777_777_E-4; "1/h", "cycle per hour", "cycles per hour";
        @cycle_per_minute: 1.666_666_666_666_666_6E-2; "1/min", "cycle per minute", "cycles per minute";
        @cycle_per_shake: 1.0_E8; "100 MHz", "cycle per shake", "cycles per shake";
        @cycle_per_year: 3.170_979_198_376_458_E-8; "1/a", "cycle per year", "cycles per year";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use num::One;
        use si::quantities::*;
        use si::frequency as f;
        use si::time as t;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: Time<V> = V::one() / Frequency::new::<f::hertz>(V::one());
            let _: Frequency<V> = V::one() / Time::new::<t::second>(V::one());
        }

        #[test]
        fn check_units() {
            test::<t::yottasecond, f::yoctohertz>();
            test::<t::zettasecond, f::zeptohertz>();
            test::<t::exasecond, f::attohertz>();
            test::<t::petasecond, f::femtohertz>();
            test::<t::terasecond, f::picohertz>();
            test::<t::gigasecond, f::nanohertz>();
            test::<t::megasecond, f::microhertz>();
            test::<t::kilosecond, f::millihertz>();
            test::<t::hectosecond, f::centihertz>();
            test::<t::decasecond, f::decihertz>();
            test::<t::second, f::hertz>();
            test::<t::decisecond, f::decahertz>();
            test::<t::centisecond, f::hectohertz>();
            test::<t::millisecond, f::kilohertz>();
            test::<t::microsecond, f::megahertz>();
            test::<t::nanosecond, f::gigahertz>();
            test::<t::picosecond, f::terahertz>();
            test::<t::femtosecond, f::petahertz>();
            test::<t::attosecond, f::exahertz>();
            test::<t::zeptosecond, f::zettahertz>();
            test::<t::yoctosecond, f::yottahertz>();
            test::<t::day, f::cycle_per_day>();
            test::<t::hour, f::cycle_per_hour>();
            test::<t::minute, f::cycle_per_minute>();
            test::<t::shake, f::cycle_per_shake>();
            test::<t::year, f::cycle_per_year>();

            fn test<T: t::Conversion<V>, F: f::Conversion<V>>() {
                Test::assert_approx_eq(&(V::one() / Time::new::<T>(V::one())),
                    &Frequency::new::<F>(V::one()));
                Test::assert_approx_eq(&Time::new::<T>(V::one()),
                    &(V::one() / Frequency::new::<F>(V::one())));
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    reactor::{ReactorHandle, Slot},
    Result,
};
use crossbeam_channel::{Receiver, Sender};
use log::trace;

pub(crate) struct SocketState {
    readable: bool,
    writable: bool,
    error: bool,
    closed: bool,
    events: Receiver<SocketEvent>,
    handle: SocketStateHandle,
}

impl Default for SocketState {
    fn default() -> Self {
        let (sender, receiver) = crossbeam_channel::unbounded();
        Self {
            readable: true,
            writable: true,
            error: false,
            closed: false,
            events: receiver,
            handle: SocketStateHandle { sender },
        }
    }
}

#[derive(Clone)]
pub struct SocketStateHandle {
    sender: Sender<SocketEvent>,
}

#[derive(Debug)]
pub enum SocketEvent {
    Readable,
    Writable,
    Error,
    Closed,
    Wake,
}

impl SocketState {
    pub(crate) fn readable(&mut self) -> bool {
        self.readable
    }

    pub(crate) fn writable(&mut self) -> bool {
        self.writable
    }

    pub(crate) fn error(&mut self) -> bool {
        self.error
    }

    pub(crate) fn closed(&mut self) -> bool {
        self.closed
    }

    pub(crate) fn wait(&mut self) {
        self.handle_event(self.events.recv().expect("waiting for socket event failed"))
    }

    pub(crate) fn handle_read_result(
        &mut self,
        result: Result<()>,
        reactor: &dyn ReactorHandle,
        slot: Slot,
    ) -> Result<()> {
        self.readable = self.handle_io_result(result)?;
        if !self.readable {
            reactor.poll_read(slot);
        }
        Ok(())
    }

    pub(crate) fn handle_write_result(
        &mut self,
        result: Result<()>,
        reactor: &dyn ReactorHandle,
        slot: Slot,
    ) -> Result<()> {
        self.writable = self.handle_io_result(result)?;
        if !self.writable {
            reactor.poll_write(slot);
        }
        Ok(())
    }

    pub(crate) fn handle(&self) -> SocketStateHandle {
        self.handle.clone()
    }

    fn handle_io_result(&self, result: Result<()>) -> Result<bool> {
        if let Err(err) = result {
            if err.wouldblock() {
                Ok(false)
            } else if err.interrupted() {
                self.handle.wake();
                Ok(true)
            } else {
                Err(err)
            }
        } else {
            Ok(true)
        }
    }

    pub(crate) fn poll_events(&mut self) {
        while let Ok(event) = self.events.try_recv() {
            self.handle_event(event);
        }
    }

    fn handle_event(&mut self, event: SocketEvent) {
        trace!("Got event for socket: {:?}", event);
        match event {
            SocketEvent::Readable => self.readable = true,
            SocketEvent::Writable => self.writable = true,
            SocketEvent::Error => self.error = true,
            SocketEvent::Closed => self.closed = true,
            SocketEvent::Wake => {}
        }
    }
}

impl SocketStateHandle {
    pub fn send(&self, event: SocketEvent) {
        let _ = self.sender.send(event);
    }

    pub fn wake(&self) {
        self.send(SocketEvent::Wake);
    }
}
<commit_msg>socket_state: avoid inadvertantly reset read/writable to true<commit_after>use crate::{
    reactor::{ReactorHandle, Slot},
    Result,
};
use crossbeam_channel::{Receiver, Sender};
use log::trace;

pub(crate) struct SocketState {
    readable: bool,
    writable: bool,
    error: bool,
    closed: bool,
    events: Receiver<SocketEvent>,
    handle: SocketStateHandle,
}

impl Default for SocketState {
    fn default() -> Self {
        let (sender, receiver) = crossbeam_channel::unbounded();
        Self {
            readable: true,
            writable: true,
            error: false,
            closed: false,
            events: receiver,
            handle: SocketStateHandle { sender },
        }
    }
}

#[derive(Clone)]
pub struct SocketStateHandle {
    sender: Sender<SocketEvent>,
}

#[derive(Debug)]
pub enum SocketEvent {
    Readable,
    Writable,
    Error,
    Closed,
    Wake,
}

impl SocketState {
    pub(crate) fn readable(&mut self) -> bool {
        self.readable
    }

    pub(crate) fn writable(&mut self) -> bool {
        self.writable
    }

    pub(crate) fn error(&mut self) -> bool {
        self.error
    }

    pub(crate) fn closed(&mut self) -> bool {
        self.closed
    }

    pub(crate) fn wait(&mut self) {
        self.handle_event(self.events.recv().expect("waiting for socket event failed"))
    }

    pub(crate) fn handle_read_result(
        &mut self,
        result: Result<()>,
        reactor: &dyn ReactorHandle,
        slot: Slot,
    ) -> Result<()> {
        self.readable = self.handle_io_result(result, self.readable)?;
        if !self.readable {
            reactor.poll_read(slot);
        }
        Ok(())
    }

    pub(crate) fn handle_write_result(
        &mut self,
        result: Result<()>,
        reactor: &dyn ReactorHandle,
        slot: Slot,
    ) -> Result<()> {
        self.writable = self.handle_io_result(result, self.writable)?;
        if !self.writable {
            reactor.poll_write(slot);
        }
        Ok(())
    }

    pub(crate) fn handle(&self) -> SocketStateHandle {
        self.handle.clone()
    }

    fn handle_io_result(&self, result: Result<()>, current: bool) -> Result<bool> {
        if let Err(err) = result {
            if err.wouldblock() {
                Ok(false)
            } else if err.interrupted() {
                self.handle.wake();
                Ok(current)
            } else {
                Err(err)
            }
        } else {
            Ok(current)
        }
    }

    pub(crate) fn poll_events(&mut self) {
        while let Ok(event) = self.events.try_recv() {
            self.handle_event(event);
        }
    }

    fn handle_event(&mut self, event: SocketEvent) {
        trace!("Got event for socket: {:?}", event);
        match event {
            SocketEvent::Readable => self.readable = true,
            SocketEvent::Writable => self.writable = true,
            SocketEvent::Error => self.error = true,
            SocketEvent::Closed => self.closed = true,
            SocketEvent::Wake => {}
        }
    }
}

impl SocketStateHandle {
    pub fn send(&self, event: SocketEvent) {
        let _ = self.sender.send(event);
    }

    pub fn wake(&self) {
        self.send(SocketEvent::Wake);
    }
}
<|endoftext|>


<commit_before>//! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types.
extern crate chrono;

use self::chrono::{NaiveDate, NaiveTime, NaiveDateTime, DateTime, TimeZone, UTC, Local};
use libc::c_int;

use {Error, Result};
use types::{FromSql, ToSql};

use ffi::sqlite3_stmt;

/// ISO 8601 calendar date without timezone => "YYYY-MM-DD"
impl ToSql for NaiveDate {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%Y-%m-%d").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
impl FromSql for NaiveDate {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveDate> {
        let s = try!(String::column_result(stmt, col));
        match NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// ISO 8601 time without timezone => "HH:MM:SS.SSS"
impl ToSql for NaiveTime {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%H:%M:%S%.f").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
impl FromSql for NaiveTime {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveTime> {
        let s = try!(String::column_result(stmt, col));
        let fmt = match s.len() {
            5 => "%H:%M",
            8 => "%H:%M:%S",
            _ => "%H:%M:%S%.f",
        };
        match NaiveTime::parse_from_str(&s, fmt) {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// ISO 8601 combined date and time without timezone => "YYYY-MM-DD HH:MM:SS.SSS"
impl ToSql for NaiveDateTime {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%Y-%m-%dT%H:%M:%S%.f").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "YYYY-MM-DD HH:MM:SS"/"YYYY-MM-DD HH:MM:SS.SSS" => ISO 8601 combined date and time without timezone.
/// ("YYYY-MM-DDTHH:MM:SS"/"YYYY-MM-DDTHH:MM:SS.SSS" also supported)
impl FromSql for NaiveDateTime {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveDateTime> {
        let s = try!(String::column_result(stmt, col));

        let fmt = if s.len() >= 11 && s.as_bytes()[10] == b'T' {
            "%Y-%m-%dT%H:%M:%S%.f"
        } else {
            "%Y-%m-%d %H:%M:%S%.f"
        };

        match NaiveDateTime::parse_from_str(&s, fmt) {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// Date and time with time zone => UTC RFC3339 timestamp ("YYYY-MM-DDTHH:MM:SS.SSS+00:00").
impl<Tz: TimeZone> ToSql for DateTime<Tz> {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let utc_dt = self.with_timezone(&UTC);
        utc_dt.to_rfc3339().bind_parameter(stmt, col)
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into DateTime<UTC>.
impl FromSql for DateTime<UTC> {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<DateTime<UTC>> {
        let s = try!(String::column_result(stmt, col));
        match DateTime::parse_from_rfc3339(&s) {
            Ok(dt) => Ok(dt.with_timezone(&UTC)),
            Err(_) => NaiveDateTime::column_result(stmt, col).map(|dt| UTC.from_utc_datetime(&dt)),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into DateTime<Local>.
impl FromSql for DateTime<Local> {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<DateTime<Local>> {
        let utc_dt = try!(DateTime::<UTC>::column_result(stmt, col));
        Ok(utc_dt.with_timezone(&Local))
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        DateTime::<UTC>::column_has_valid_sqlite_type(stmt, col)
    }
}

#[cfg(test)]
mod test {
    use Connection;
    use super::chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, UTC};

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)").unwrap();
        db
    }

    #[test]
    fn test_naive_date() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&date]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23", s);
        let t: NaiveDate = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(date, t);
    }

    #[test]
    fn test_naive_time() {
        let db = checked_memory_handle();
        let time = NaiveTime::from_hms(23, 56, 4);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&time]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("23:56:04", s);
        let v: NaiveTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(time, v);
    }

    #[test]
    fn test_naive_date_time() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms(23, 56, 4);
        let dt = NaiveDateTime::new(date, time);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23T23:56:04", s);
        let v: NaiveDateTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(dt, v);

        db.execute("UPDATE foo set b = datetime(t)", &[]).unwrap(); // "YYYY-MM-DD HH:MM:SS"
        let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(dt, hms);
    }

    #[test]
    fn test_date_time_utc() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let utc = UTC.from_utc_datetime(&dt);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23T23:56:04.789+00:00", s);
        let v: DateTime<UTC> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(utc, v);
    }

    #[test]
    fn test_date_time_local() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let local = Local.from_local_datetime(&dt).single().unwrap();

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&local]).unwrap();

        // Stored string should be in UTC
        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert!(s.ends_with("+00:00"));

        let v: DateTime<Local> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(local, v);
    }
}
<commit_msg>Add tests confirming DateTime works with " " seperator instead of "T"<commit_after>//! Convert most of the [Time Strings](http://sqlite.org/lang_datefunc.html) to chrono types.
extern crate chrono;

use self::chrono::{NaiveDate, NaiveTime, NaiveDateTime, DateTime, TimeZone, UTC, Local};
use libc::c_int;

use {Error, Result};
use types::{FromSql, ToSql};

use ffi::sqlite3_stmt;

/// ISO 8601 calendar date without timezone => "YYYY-MM-DD"
impl ToSql for NaiveDate {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%Y-%m-%d").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
impl FromSql for NaiveDate {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveDate> {
        let s = try!(String::column_result(stmt, col));
        match NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// ISO 8601 time without timezone => "HH:MM:SS.SSS"
impl ToSql for NaiveTime {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%H:%M:%S%.f").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
impl FromSql for NaiveTime {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveTime> {
        let s = try!(String::column_result(stmt, col));
        let fmt = match s.len() {
            5 => "%H:%M",
            8 => "%H:%M:%S",
            _ => "%H:%M:%S%.f",
        };
        match NaiveTime::parse_from_str(&s, fmt) {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// ISO 8601 combined date and time without timezone => "YYYY-MM-DD HH:MM:SS.SSS"
impl ToSql for NaiveDateTime {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let date_str = self.format("%Y-%m-%dT%H:%M:%S%.f").to_string();
        date_str.bind_parameter(stmt, col)
    }
}

/// "YYYY-MM-DD HH:MM:SS"/"YYYY-MM-DD HH:MM:SS.SSS" => ISO 8601 combined date and time without timezone.
/// ("YYYY-MM-DDTHH:MM:SS"/"YYYY-MM-DDTHH:MM:SS.SSS" also supported)
impl FromSql for NaiveDateTime {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<NaiveDateTime> {
        let s = try!(String::column_result(stmt, col));

        let fmt = if s.len() >= 11 && s.as_bytes()[10] == b'T' {
            "%Y-%m-%dT%H:%M:%S%.f"
        } else {
            "%Y-%m-%d %H:%M:%S%.f"
        };

        match NaiveDateTime::parse_from_str(&s, fmt) {
            Ok(dt) => Ok(dt),
            Err(err) => Err(Error::FromSqlConversionFailure(Box::new(err))),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// Date and time with time zone => UTC RFC3339 timestamp ("YYYY-MM-DDTHH:MM:SS.SSS+00:00").
impl<Tz: TimeZone> ToSql for DateTime<Tz> {
    unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
        let utc_dt = self.with_timezone(&UTC);
        utc_dt.to_rfc3339().bind_parameter(stmt, col)
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into DateTime<UTC>.
impl FromSql for DateTime<UTC> {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<DateTime<UTC>> {
        let s = try!(String::column_result(stmt, col));
        match DateTime::parse_from_rfc3339(&s) {
            Ok(dt) => Ok(dt.with_timezone(&UTC)),
            Err(_) => NaiveDateTime::column_result(stmt, col).map(|dt| UTC.from_utc_datetime(&dt)),
        }
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        String::column_has_valid_sqlite_type(stmt, col)
    }
}

/// RFC3339 ("YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM") into DateTime<Local>.
impl FromSql for DateTime<Local> {
    unsafe fn column_result(stmt: *mut sqlite3_stmt, col: c_int) -> Result<DateTime<Local>> {
        let utc_dt = try!(DateTime::<UTC>::column_result(stmt, col));
        Ok(utc_dt.with_timezone(&Local))
    }

    unsafe fn column_has_valid_sqlite_type(stmt: *mut sqlite3_stmt, col: c_int) -> bool {
        DateTime::<UTC>::column_has_valid_sqlite_type(stmt, col)
    }
}

#[cfg(test)]
mod test {
    use Connection;
    use super::chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, UTC, Duration};

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)").unwrap();
        db
    }

    #[test]
    fn test_naive_date() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&date]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23", s);
        let t: NaiveDate = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(date, t);
    }

    #[test]
    fn test_naive_time() {
        let db = checked_memory_handle();
        let time = NaiveTime::from_hms(23, 56, 4);
        db.execute("INSERT INTO foo (t) VALUES (?)", &[&time]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("23:56:04", s);
        let v: NaiveTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(time, v);
    }

    #[test]
    fn test_naive_date_time() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms(23, 56, 4);
        let dt = NaiveDateTime::new(date, time);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23T23:56:04", s);
        let v: NaiveDateTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(dt, v);

        db.execute("UPDATE foo set b = datetime(t)", &[]).unwrap(); // "YYYY-MM-DD HH:MM:SS"
        let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(dt, hms);
    }

    #[test]
    fn test_date_time_utc() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let utc = UTC.from_utc_datetime(&dt);

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc]).unwrap();

        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!("2016-02-23T23:56:04.789+00:00", s);

        let v1: DateTime<UTC> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(utc, v1);

        let v2: DateTime<UTC> = db.query_row("SELECT '2016-02-23 23:56:04.789'", &[], |r| r.get(0)).unwrap();
        assert_eq!(utc, v2);

        let v3: DateTime<UTC> = db.query_row("SELECT '2016-02-23 23:56:04'", &[], |r| r.get(0)).unwrap();
        assert_eq!(utc - Duration::milliseconds(789), v3);
    }

    #[test]
    fn test_date_time_local() {
        let db = checked_memory_handle();
        let date = NaiveDate::from_ymd(2016, 2, 23);
        let time = NaiveTime::from_hms_milli(23, 56, 4, 789);
        let dt = NaiveDateTime::new(date, time);
        let local = Local.from_local_datetime(&dt).single().unwrap();

        db.execute("INSERT INTO foo (t) VALUES (?)", &[&local]).unwrap();

        // Stored string should be in UTC
        let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert!(s.ends_with("+00:00"));

        let v: DateTime<Local> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(local, v);
    }
}
<|endoftext|>


<commit_before>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;
use std::fmt;
use std::error;

/// A specialized `std::result::Result` type for FBX exporting.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// I/O error.
    Io(io::Error),
    /// `EndNode` event is given but there's no node to close.
    ExtraEndNode,
    /// FBX not started but an event other than `StartFbx` is given.
    FbxNotStarted,
    /// FBX is already started but `StartFbx` is given.
    FbxAlreadyStarted,
    /// Unsupported FBX version.
    UnsupportedFbxVersion(u32),
    /// Given event is not writable in current format.
    UnwritableEvent,
    /// Unimplemented feature.
    Unimplemented(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => write!(f, "I/O error: {}", err),
            Error::ExtraEndNode => write!(f, "Extra end-of-node marker detected"),
            Error::FbxNotStarted => write!(f, "An writer event is given, but FBX data is not started yet"),
            Error::FbxAlreadyStarted => write!(f, "Got a writer event to start FBX, but FBX data is already started"),
            Error::UnsupportedFbxVersion(ver) => write!(f, "Unsupported FBX version ({})", ver),
            Error::UnwritableEvent => write!(f, "A given event is not writable in current format"),
            Error::Unimplemented(ref err) => write!(f, "Unimplemented feature: {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::ExtraEndNode => "Extra end-of-node marker detected",
            Error::FbxNotStarted => "An writer event is given, but FBX data is not started yet",
            Error::FbxAlreadyStarted => "Got a writer event to start FBX, but FBX data is already started",
            Error::UnsupportedFbxVersion(_) => "Unsupported FBX version",
            Error::UnwritableEvent => "A given event is not writable in current format",
            Error::Unimplemented(_) => "Attempt to use unimplemented feature",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err as &error::Error),
            _ => None,
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        use self::Error::*;
        use std::error::Error;
        match *self {
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            Unimplemented(ref e) => Unimplemented(e.clone()),
            ref e => e.clone(),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        match err {
            byteorder::Error::UnexpectedEOF => panic!("byteorder::Error::UnexpectedEOF shouldn't happen on write"),
            byteorder::Error::Io(err) => Error::Io(err),
        }
    }
}
<commit_msg>Add `writer::Error::InvalidOption`<commit_after>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;
use std::fmt;
use std::error;

/// A specialized `std::result::Result` type for FBX exporting.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// I/O error.
    Io(io::Error),
    /// `EndNode` event is given but there's no node to close.
    ExtraEndNode,
    /// FBX not started but an event other than `StartFbx` is given.
    FbxNotStarted,
    /// FBX is already started but `StartFbx` is given.
    FbxAlreadyStarted,
    /// Invalid writer option.
    InvalidOption(String),
    /// Unsupported FBX version.
    UnsupportedFbxVersion(u32),
    /// Given event is not writable in current format.
    UnwritableEvent,
    /// Unimplemented feature.
    Unimplemented(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => write!(f, "I/O error: {}", err),
            Error::ExtraEndNode => write!(f, "Extra end-of-node marker detected"),
            Error::FbxNotStarted => write!(f, "An writer event is given, but FBX data is not started yet"),
            Error::FbxAlreadyStarted => write!(f, "Got a writer event to start FBX, but FBX data is already started"),
            Error::InvalidOption(ref err) => write!(f, "Invalid writer option: {}", err),
            Error::UnsupportedFbxVersion(ver) => write!(f, "Unsupported FBX version ({})", ver),
            Error::UnwritableEvent => write!(f, "A given event is not writable in current format"),
            Error::Unimplemented(ref err) => write!(f, "Unimplemented feature: {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::ExtraEndNode => "Extra end-of-node marker detected",
            Error::FbxNotStarted => "An writer event is given, but FBX data is not started yet",
            Error::FbxAlreadyStarted => "Got a writer event to start FBX, but FBX data is already started",
            Error::InvalidOption(_) => "Invalid writer option",
            Error::UnsupportedFbxVersion(_) => "Unsupported FBX version",
            Error::UnwritableEvent => "A given event is not writable in current format",
            Error::Unimplemented(_) => "Attempt to use unimplemented feature",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err as &error::Error),
            _ => None,
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        use self::Error::*;
        use std::error::Error;
        match *self {
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            Unimplemented(ref e) => Unimplemented(e.clone()),
            ref e => e.clone(),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        match err {
            byteorder::Error::UnexpectedEOF => panic!("byteorder::Error::UnexpectedEOF shouldn't happen on write"),
            byteorder::Error::Io(err) => Error::Io(err),
        }
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

use crossbeam_channel::{unbounded, Receiver, Sender};

use crate::network::NetworkConnection;
use crate::proto::RawMessage;

pub trait IrcWriter {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()>;
}

pub trait IrcReader {
    fn read_message(&mut self) -> Result<RawMessage>;
}

impl<T: Write> IrcWriter for T {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        let msg_str = msg.to_string();
        self.write_all(msg_str.as_bytes())?;
        self.write_all(b"\r\n")?;

        Ok(())
    }
}

impl<T: BufRead> IrcReader for T {
    fn read_message(&mut self) -> Result<RawMessage> {
        let mut buf = String::new();
        self.read_line(&mut buf)?;

        let line = buf.trim_end_matches(|c| c == '\r' || c == '\n');
        RawMessage::parse(line).ok_or_else(|| {
            Error::new(ErrorKind::Other, "failed to parse message from line")
        })
    }
}

#[derive(Clone)]
pub struct IrcChannel(pub Sender<RawMessage>);

impl IrcChannel {
    pub fn new() -> (Self, Receiver<RawMessage>) {
        let (sender, receiver) = unbounded();
        (IrcChannel(sender), receiver)
    }
}

impl IrcWriter for IrcChannel {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        if let Err(err) = self.0.send(msg.clone()) {
            println!("Failed to write to client: {:?}", err);
            return Err(Error::new(ErrorKind::Other, "other end disconnected"));
        }
        Ok(())
    }
}

pub struct IrcSocketConfig<'a> {
    pub nick: &'a str,
    pub addr: &'a str,
    pub max_retries: Option<usize>,
}

pub struct IrcSocket<'a> {
    config: IrcSocketConfig<'a>,

    to_network: (Sender<RawMessage>, Receiver<RawMessage>),
    to_users: (Sender<RawMessage>, Receiver<RawMessage>),
    from_network: (Sender<RawMessage>, Receiver<RawMessage>),
    new_user: (Sender<IrcChannel>, Receiver<IrcChannel>),
}

impl<'a> IrcSocket<'a> {
    pub fn new(config: IrcSocketConfig<'a>) -> Self {
        Self {
            config,

            to_network: unbounded(),
            to_users: unbounded(),
            from_network: unbounded(),
            new_user: unbounded(),
        }
    }

    pub fn network_channel(&self) -> Sender<RawMessage> {
        self.to_network.0.clone()
    }

    pub fn new_user_channel(&self) -> Sender<IrcChannel> {
        self.new_user.0.clone()
    }

    // TODO: this is kind of gross, clean this up
    fn create_stream(&self) -> Result<TcpStream> {
        let _create_stream = || {
            let stream = TcpStream::connect(self.config.addr)?;
            stream.set_read_timeout(Some(Duration::from_secs(180)))?;
            Ok(stream)
        };

        let max_retries = self.config.max_retries;

        let mut i = 0;
        loop {
            let stream = _create_stream();
            let over_max_tries = max_retries.map(|max| i > max).unwrap_or(false);

            if stream.is_ok() || over_max_tries {
                return stream;
            }

            i += 1
        }
    }

    /// On connection close, return `true` when the connection should
    /// be restarted, and false otherwise. If there is a
    /// non-recoverable exception, return the error.
    ///
    /// TODO: Need to come up with the clean exit concept.
    fn connect(&self, users: &mut dyn IrcWriter) -> Result<bool> {
        let from_net_sender = self.from_network.0.clone();

        let mut network = NetworkConnection::new(
            self.config.nick,
            self.to_network.0.clone(),
            self.to_users.0.clone(),
        );

        let stream = self.create_stream()?;
        let mut write_stream = stream.try_clone().expect("clone failed");

        let recv_err = || Error::new(ErrorKind::Other, "receiver disconnected");

        thread::spawn(move || {
            let mut reader = BufReader::new(stream);
            loop {
                let result = reader
                    .read_message()
                    .and_then(|msg| from_net_sender.send(msg).map_err(|_| recv_err()));

                if let Err(err) = result {
                    println!("Read from network failed: {:?}", err);
                    break;
                }
            }
        });

        if network.initialize().is_err() {
            return Ok(true);
        }

        loop {
            let result = crossbeam_channel::select! {
                recv(self.from_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                            network.handle(&msg)
                        })
                },
                recv(self.to_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
                            write_stream.write_message(&msg)
                        })
                },
                recv(self.to_users.1) -> msg => {
                    msg.map_err(|_| recv_err()).and_then(|msg| {
                        users.write_message(&msg)
                    })
                },
                recv(self.new_user.1) -> chan => {
                    chan.map_err(|_| recv_err()).and_then(|mut chan| {
                        network.state.welcome_user(&mut chan)
                    })
                }
            };

            if let Err(err) = result {
                println!("read failed: {}", err);
                break;
            }
        }

        Ok(true)
    }

    pub fn start_loop(&mut self, users: &mut dyn IrcWriter) -> Result<()> {
        loop {
            match self.connect(users) {
                Ok(true) => println!("connection terminated, restarting"),
                Ok(false) => break,
                Err(err) => {
                    println!("connection failed: {:?}", err);
                    return Err(err);
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Reset network connection after inactivity<commit_after>use std::io::prelude::*;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::net::TcpStream;
use std::thread;
use std::time::Duration;

use crossbeam_channel::{unbounded, Receiver, Sender};

use crate::network::NetworkConnection;
use crate::proto::RawMessage;

pub trait IrcWriter {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()>;
}

pub trait IrcReader {
    fn read_message(&mut self) -> Result<RawMessage>;
}

impl<T: Write> IrcWriter for T {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        let msg_str = msg.to_string();
        self.write_all(msg_str.as_bytes())?;
        self.write_all(b"\r\n")?;

        Ok(())
    }
}

impl<T: BufRead> IrcReader for T {
    fn read_message(&mut self) -> Result<RawMessage> {
        let mut buf = String::new();
        self.read_line(&mut buf)?;

        let line = buf.trim_end_matches(|c| c == '\r' || c == '\n');
        RawMessage::parse(line).ok_or_else(|| {
            Error::new(ErrorKind::Other, "failed to parse message from line")
        })
    }
}

#[derive(Clone)]
pub struct IrcChannel(pub Sender<RawMessage>);

impl IrcChannel {
    pub fn new() -> (Self, Receiver<RawMessage>) {
        let (sender, receiver) = unbounded();
        (IrcChannel(sender), receiver)
    }
}

impl IrcWriter for IrcChannel {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        if let Err(err) = self.0.send(msg.clone()) {
            println!("Failed to write to client: {:?}", err);
            return Err(Error::new(ErrorKind::Other, "other end disconnected"));
        }
        Ok(())
    }
}

pub struct IrcSocketConfig<'a> {
    pub nick: &'a str,
    pub addr: &'a str,
    pub max_retries: Option<usize>,
}

pub struct IrcSocket<'a> {
    config: IrcSocketConfig<'a>,

    to_network: (Sender<RawMessage>, Receiver<RawMessage>),
    to_users: (Sender<RawMessage>, Receiver<RawMessage>),
    from_network: (Sender<RawMessage>, Receiver<RawMessage>),
    new_user: (Sender<IrcChannel>, Receiver<IrcChannel>),
}

impl<'a> IrcSocket<'a> {
    pub fn new(config: IrcSocketConfig<'a>) -> Self {
        Self {
            config,

            to_network: unbounded(),
            to_users: unbounded(),
            from_network: unbounded(),
            new_user: unbounded(),
        }
    }

    pub fn network_channel(&self) -> Sender<RawMessage> {
        self.to_network.0.clone()
    }

    pub fn new_user_channel(&self) -> Sender<IrcChannel> {
        self.new_user.0.clone()
    }

    // TODO: this is kind of gross, clean this up
    fn create_stream(&self) -> Result<TcpStream> {
        let _create_stream = || {
            let stream = TcpStream::connect(self.config.addr)?;
            stream.set_read_timeout(Some(Duration::from_secs(180)))?;
            Ok(stream)
        };

        let max_retries = self.config.max_retries;

        let mut i = 0;
        loop {
            let stream = _create_stream();
            let over_max_tries = max_retries.map(|max| i > max).unwrap_or(false);

            if stream.is_ok() || over_max_tries {
                return stream;
            }

            i += 1
        }
    }

    /// On connection close, return `true` when the connection should
    /// be restarted, and false otherwise. If there is a
    /// non-recoverable exception, return the error.
    ///
    /// TODO: Need to come up with the clean exit concept.
    fn connect(&self, users: &mut dyn IrcWriter) -> Result<bool> {
        let from_net_sender = self.from_network.0.clone();

        let mut network = NetworkConnection::new(
            self.config.nick,
            self.to_network.0.clone(),
            self.to_users.0.clone(),
        );

        let stream = self.create_stream()?;
        let mut write_stream = stream.try_clone().expect("clone failed");

        let recv_err = || Error::new(ErrorKind::Other, "receiver disconnected");

        thread::spawn(move || {
            let mut reader = BufReader::new(stream);
            loop {
                let result = reader
                    .read_message()
                    .and_then(|msg| from_net_sender.send(msg).map_err(|_| recv_err()));

                if let Err(err) = result {
                    println!("Read from network failed: {:?}", err);
                    break;
                }
            }
        });

        if network.initialize().is_err() {
            return Ok(true);
        }

        loop {
            let result = crossbeam_channel::select! {
                recv(self.from_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[birch <- \u{1b}[37;1mnet\u{1b}[0m] {}", msg);
                            network.handle(&msg)
                        })
                },
                recv(self.to_network.1) -> msg => {
                    msg.map_err(|_| recv_err())
                        .and_then(|msg| {
                            println!("[\u{1b}[37;1mbirch\u{1b}[0m -> net] {}", msg);
                            write_stream.write_message(&msg)
                        })
                },
                recv(self.to_users.1) -> msg => {
                    msg.map_err(|_| recv_err()).and_then(|msg| {
                        users.write_message(&msg)
                    })
                },
                recv(self.new_user.1) -> chan => {
                    chan.map_err(|_| recv_err()).and_then(|mut chan| {
                        network.state.welcome_user(&mut chan)
                    })
                },
                // If we haven't received ANYTHING in 4 minutes,
                // network connection likely failed.
                // TODO: this is a jank way of doing this.
                default(Duration::from_secs(240)) => {
                    println!("no network activity in 240 seconds...");
                    break
                }
            };

            if let Err(err) = result {
                println!("read failed: {}", err);
                break;
            }
        }

        Ok(true)
    }

    pub fn start_loop(&mut self, users: &mut dyn IrcWriter) -> Result<()> {
        loop {
            match self.connect(users) {
                Ok(true) => println!("connection terminated, restarting"),
                Ok(false) => break,
                Err(err) => {
                    println!("connection failed: {:?}", err);
                    return Err(err);
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use super::*;

// test param_list
// fn a() {}
// fn b(x: i32) {}
// fn c(x: i32, ) {}
// fn d(x: i32, y: ()) {}
// fn g1(#[attr1] #[attr2] pat: Type) {}
// fn g2(#[attr1] x: u8) {}
pub(super) fn param_list(p: &mut Parser) {
    list_(p, Flavor::Normal)
}

// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
// fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
pub(super) fn param_list_opt_patterns(p: &mut Parser) {
    list_(p, Flavor::OptionalPattern)
}

pub(super) fn param_list_opt_types(p: &mut Parser) {
    list_(p, Flavor::OptionalType)
}

#[derive(Clone, Copy, Eq, PartialEq)]
enum Flavor {
    OptionalType,
    OptionalPattern,
    Normal,
}

impl Flavor {
    fn type_required(self) -> bool {
        match self {
            Flavor::OptionalType => false,
            _ => true,
        }
    }
}

fn list_(p: &mut Parser, flavor: Flavor) {
    let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
    assert!(p.at(bra));
    let m = p.start();
    p.bump();
    if flavor.type_required() {
        attributes::outer_attributes(p);
        opt_self_param(p);
    }
    while !p.at(EOF) && !p.at(ket) && !(flavor.type_required() && p.at(T![...])) {
        attributes::outer_attributes(p);

        if !p.at_ts(VALUE_PARAMETER_FIRST) {
            p.error("expected value parameter");
            break;
        }
        value_parameter(p, flavor);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
    // test param_list_vararg
    // extern "C" { fn printf(format: *const i8, ...) -> i32; }
    // extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
    if flavor.type_required() {
        p.eat(T![...]);
    }
    p.expect(ket);
    m.complete(p, PARAM_LIST);
}

const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);

fn value_parameter(p: &mut Parser, flavor: Flavor) {
    let m = p.start();
    match flavor {
        Flavor::OptionalType | Flavor::Normal => {
            patterns::pattern(p);
            if p.at(T![:]) || flavor.type_required() {
                types::ascription(p)
            }
        }
        // test value_parameters_no_patterns
        // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
        Flavor::OptionalPattern => {
            let la0 = p.current();
            let la1 = p.nth(1);
            let la2 = p.nth(2);
            let la3 = p.nth(3);

            // test trait_fn_placeholder_parameter
            // trait Foo {
            //     fn bar(_: u64, mut x: i32);
            //     fn bar(#[attr] _: u64, #[attr] mut x: i32);
            // }
            if (la0 == IDENT || la0 == T![_]) && la1 == T![:]
                || la0 == T![mut] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:]
            {
                patterns::pattern(p);
                types::ascription(p);
            } else {
                types::type_(p);
            }
        }
    }
    m.complete(p, PARAM);
}

// test self_param
// impl S {
//     fn a(self) {}
//     fn b(&self,) {}
//     fn c(&'a self,) {}
//     fn d(&'a mut self, x: i32) {}
//     fn e(mut self) {}
//     fn f(#[must_use] self) {}
//     fn g1(#[attr] self) {}
//     fn g2(#[attr] &self) {}
//     fn g3<'a>(#[attr] &mut self) {}
//     fn g4<'a>(#[attr] &'a self) {}
//     fn g5<'a>(#[attr] &'a mut self) {}
// }
fn opt_self_param(p: &mut Parser) {
    let m;
    if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
        m = p.start();
        p.eat(T![mut]);
        p.eat(T![self]);
        // test arb_self_types
        // impl S {
        //     fn a(self: &Self) {}
        //     fn b(mut self: Box<Self>) {}
        //     fn c(#[attr] self: Self) {}
        //     fn d(#[attr] self: Rc<Self>) {}
        // }
        if p.at(T![:]) {
            types::ascription(p);
        }
    } else {
        let la1 = p.nth(1);
        let la2 = p.nth(2);
        let la3 = p.nth(3);
        let n_toks = match (p.current(), la1, la2, la3) {
            (T![&], T![self], _, _) => 2,
            (T![&], T![mut], T![self], _) => 3,
            (T![&], LIFETIME, T![self], _) => 3,
            (T![&], LIFETIME, T![mut], T![self]) => 4,
            _ => return,
        };
        m = p.start();
        for _ in 0..n_toks {
            p.bump();
        }
    }
    m.complete(p, SELF_PARAM);
    if !p.at(T![')']) {
        p.expect(T![,]);
    }
}
<commit_msg>Fix parser to correctly consume outer attrs before ellipsis param<commit_after>use super::*;

// test param_list
// fn a() {}
// fn b(x: i32) {}
// fn c(x: i32, ) {}
// fn d(x: i32, y: ()) {}
// fn g1(#[attr1] #[attr2] pat: Type) {}
// fn g2(#[attr1] x: u8) {}
pub(super) fn param_list(p: &mut Parser) {
    list_(p, Flavor::Normal)
}

// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
// fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
pub(super) fn param_list_opt_patterns(p: &mut Parser) {
    list_(p, Flavor::OptionalPattern)
}

pub(super) fn param_list_opt_types(p: &mut Parser) {
    list_(p, Flavor::OptionalType)
}

#[derive(Clone, Copy, Eq, PartialEq)]
enum Flavor {
    OptionalType,
    OptionalPattern,
    Normal,
}

impl Flavor {
    fn type_required(self) -> bool {
        match self {
            Flavor::OptionalType => false,
            _ => true,
        }
    }
}

fn list_(p: &mut Parser, flavor: Flavor) {
    let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
    assert!(p.at(bra));
    let m = p.start();
    p.bump();
    if flavor.type_required() {
        attributes::outer_attributes(p);
        opt_self_param(p);
    }
    while !p.at(EOF) && !p.at(ket) && !(flavor.type_required() && p.at(T![...])) {
        attributes::outer_attributes(p);

        if p.at(T![...]) {
            break;
        }

        if !p.at_ts(VALUE_PARAMETER_FIRST) {
            p.error("expected value parameter");
            break;
        }
        value_parameter(p, flavor);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
    // test param_list_vararg
    // extern "C" { fn printf(format: *const i8, ...) -> i32; }
    // extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
    if flavor.type_required() {
        p.eat(T![...]);
    }
    p.expect(ket);
    m.complete(p, PARAM_LIST);
}

const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);

fn value_parameter(p: &mut Parser, flavor: Flavor) {
    let m = p.start();
    match flavor {
        Flavor::OptionalType | Flavor::Normal => {
            patterns::pattern(p);
            if p.at(T![:]) || flavor.type_required() {
                types::ascription(p)
            }
        }
        // test value_parameters_no_patterns
        // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
        Flavor::OptionalPattern => {
            let la0 = p.current();
            let la1 = p.nth(1);
            let la2 = p.nth(2);
            let la3 = p.nth(3);

            // test trait_fn_placeholder_parameter
            // trait Foo {
            //     fn bar(_: u64, mut x: i32);
            //     fn bar(#[attr] _: u64, #[attr] mut x: i32);
            // }
            if (la0 == IDENT || la0 == T![_]) && la1 == T![:]
                || la0 == T![mut] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:]
            {
                patterns::pattern(p);
                types::ascription(p);
            } else {
                types::type_(p);
            }
        }
    }
    m.complete(p, PARAM);
}

// test self_param
// impl S {
//     fn a(self) {}
//     fn b(&self,) {}
//     fn c(&'a self,) {}
//     fn d(&'a mut self, x: i32) {}
//     fn e(mut self) {}
//     fn f(#[must_use] self) {}
//     fn g1(#[attr] self) {}
//     fn g2(#[attr] &self) {}
//     fn g3<'a>(#[attr] &mut self) {}
//     fn g4<'a>(#[attr] &'a self) {}
//     fn g5<'a>(#[attr] &'a mut self) {}
// }
fn opt_self_param(p: &mut Parser) {
    let m;
    if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
        m = p.start();
        p.eat(T![mut]);
        p.eat(T![self]);
        // test arb_self_types
        // impl S {
        //     fn a(self: &Self) {}
        //     fn b(mut self: Box<Self>) {}
        //     fn c(#[attr] self: Self) {}
        //     fn d(#[attr] self: Rc<Self>) {}
        // }
        if p.at(T![:]) {
            types::ascription(p);
        }
    } else {
        let la1 = p.nth(1);
        let la2 = p.nth(2);
        let la3 = p.nth(3);
        let n_toks = match (p.current(), la1, la2, la3) {
            (T![&], T![self], _, _) => 2,
            (T![&], T![mut], T![self], _) => 3,
            (T![&], LIFETIME, T![self], _) => 3,
            (T![&], LIFETIME, T![mut], T![self]) => 4,
            _ => return,
        };
        m = p.start();
        for _ in 0..n_toks {
            p.bump();
        }
    }
    m.complete(p, SELF_PARAM);
    if !p.at(T![')']) {
        p.expect(T![,]);
    }
}
<|endoftext|>


<commit_before>//! A list of independent dataflow computations.

use std::rc::Rc;
use std::cell::RefCell;

use progress::timestamp::RootTimestamp;
use progress::{Timestamp, Operate, Subgraph};
use progress::nested::{Source, Target};
use timely_communication::{Allocate, Data};
use {Push, Pull};

use super::Scope;

// TODO: This should probably not be a scope, but just the allocation facilities.

pub struct List<S: Scope> {
    parent: S,
    dataflows: Rc<RefCell<Vec<Box<Operate<RootTimestamp>>>>>,
}

impl<A: Allocate> List<A> {
    /// Allocates a new `Root` bound to a channel allocator.
    pub fn new(c: A) -> Root<A> {
        let mut result = Root {
            allocator: Rc::new(RefCell::new(c)),
            graph: Rc::new(RefCell::new(Vec::new())),
            identifiers: Rc::new(RefCell::new(0)),
        };

        // LOGGING
        if cfg!(feature = "logging") {
            ::logging::initialize(&mut result);
        }

        result
    }
    /// Performs one step of the computation.
    ///
    /// A step gives each dataflow operator a chance to run, and is the
    /// main way to ensure that a computation procedes.
    pub fn step(&mut self) -> bool {

        if cfg!(feature = "logging") {
            ::logging::flush_logs();
        }

        let mut active = false;
        for scope in self.graph.borrow_mut().iter_mut() {
            let sub_active = scope.pull_internal_progress(&mut [], &mut [], &mut []);
            active = active || sub_active;
        }
        active
    }
    /// Calls `self.step()` as long as `func` evaluates to true.
    ///
    /// The method is most commonly used with a dataflow probe, which indicates progress
    /// in the dataflow computation.
    pub fn step_while<F: FnMut()->bool>(&mut self, mut func: F) {
        while func() { self.step(); }
    }

    /// The index of the worker out of its peers.
    pub fn index(&self) -> usize { self.allocator.borrow().index() }
    /// The total number of peer workers.
    pub fn peers(&self) -> usize { self.allocator.borrow().peers() }
}

impl<A: Allocate> Scope for Root<A> {
    type Timestamp = RootTimestamp;

    fn name(&self) -> String { format!("Worker[{}]", self.allocator.borrow().index()) }
    fn addr(&self) -> Vec<usize> { vec![self.allocator.borrow().index() ] }
    fn add_edge(&self, _source: Source, _target: Target) {
        panic!("Root::connect(): root doesn't maintain edges; who are you, how did you get here?")
    }

    fn add_operator<SC: Operate<Self::Timestamp>+'static>(&mut self, scope: SC) -> usize {
        let index = self.graph.borrow().len();
        self.add_operator_with_index(scope, index);
        index
    }

    fn add_operator_with_index<SC: Operate<RootTimestamp>+'static>(&mut self, mut scope: SC, index: usize) {
        assert_eq!(index, self.graph.borrow().len());

        scope.get_internal_summary();
        scope.set_external_summary(Vec::new(), &mut []);
        self.graph.borrow_mut().push(Box::new(scope));
    }
    fn new_identifier(&mut self) -> usize {
        *self.identifiers.borrow_mut() += 1;
        *self.identifiers.borrow() - 1
    }

    fn new_subscope<T: Timestamp>(&mut self) -> Subgraph<RootTimestamp, T>  {
        let addr = vec![self.allocator.borrow().index()];
        Subgraph::new_from(&mut (*self.allocator.borrow_mut()), self.graph.borrow().len(), addr)
    }
}

impl<A: Allocate> Allocate for Root<A> {
    fn index(&self) -> usize { self.allocator.borrow().index() }
    fn peers(&self) -> usize { self.allocator.borrow().peers() }
    fn allocate<D: Data>(&mut self) -> (Vec<Box<Push<D>>>, Box<Pull<D>>) {
        self.allocator.borrow_mut().allocate()
    }
}

impl<A: Allocate> Clone for Root<A> {
    fn clone(&self) -> Self {
        Root {
            allocator: self.allocator.clone(),
            graph: self.graph.clone(),
            identifiers: self.identifiers.clone(),
        }
    }
}
<commit_msg>Revert "added msb implementation, tweaked benchmarks"<commit_after><|endoftext|>


<commit_before>//! Error handling types based on `failure` crate.

pub type Result<T> = std::result::Result<T, failure::Error>;
pub use crate::unexpected;
pub use failure::{bail, ensure, err_msg, Error, ResultExt};
use log::log;
use std::env;

pub trait FancyUnwrap {
    type Output;
    fn fancy_unwrap(self) -> Self::Output;
}

pub fn print_trace(err: failure::Error, log_level: log::Level) {
    log!(log_level, "\nError:");
    for cause in err.iter_chain() {
        log!(log_level, "   {}", cause);
    }
    let backtrace = err.backtrace().to_string();
    if !backtrace.is_empty() {
        if env::var("RUST_BACKTRACE").as_ref().map(|v| v.as_str()) == Ok("full") {
            log!(log_level, "{}", backtrace);
        } else {
            log!(log_level, "Short backtrace:");
            let mut lines: Vec<_> = backtrace.split('\n').collect();
            if let Some(position) = lines
                .iter()
                .position(|line| line.contains("std::rt::lang_start::"))
            {
                lines.truncate(position);
            }
            if let Some(position) = lines
                .iter()
                .position(|line| line.contains("failure::backtrace::Backtrace::new::"))
            {
                lines.drain(0..position + 2);
            }
            log!(log_level, "{}", lines.join("\n"));
        }
    }
}

impl<T> FancyUnwrap for Result<T> {
    type Output = T;

    fn fancy_unwrap(self) -> T {
        match self {
            Ok(value) => value,
            Err(err) => {
                print_trace(err, log::Level::Error);
                std::process::exit(1);
            }
        }
    }
}

// TODO: replace with a proper mechanism
pub fn should_panic_on_unexpected() -> bool {
    true
}

#[macro_export]
macro_rules! unexpected {
    ($e:expr) => {
        if $crate::errors::should_panic_on_unexpected() {
            panic!($e);
        } else {
            bail!($e);
        }
    };
    ($fmt:expr, $($arg:tt)*) => {
        if $crate::errors::should_panic_on_unexpected() {
            panic!($fmt, $($arg)*);
        } else {
            bail!($fmt, $($arg)*);
        }
    };
}
<commit_msg>fix backtrace formatting in logs<commit_after>//! Error handling types based on `failure` crate.

pub type Result<T> = std::result::Result<T, failure::Error>;
pub use crate::unexpected;
pub use failure::{bail, ensure, err_msg, Error, ResultExt};
use log::log;
use std::env;

pub trait FancyUnwrap {
    type Output;
    fn fancy_unwrap(self) -> Self::Output;
}

pub fn print_trace(err: failure::Error, log_level: log::Level) {
    log!(log_level, "");
    log!(log_level, "Error:");
    for cause in err.iter_chain() {
        log!(log_level, "   {}", cause);
    }
    let backtrace = err.backtrace().to_string();
    if !backtrace.is_empty() {
        if env::var("RUST_BACKTRACE").as_ref().map(|v| v.as_str()) == Ok("full") {
            log!(log_level, "{}", backtrace);
        } else {
            log!(log_level, "Short backtrace:");
            let mut lines: Vec<_> = backtrace.split('\n').collect();
            if let Some(position) = lines
                .iter()
                .position(|line| line.contains("std::rt::lang_start::"))
            {
                lines.truncate(position);
            }
            if let Some(position) = lines
                .iter()
                .position(|line| line.contains("failure::backtrace::Backtrace::new::"))
            {
                lines.drain(0..position + 2);
            }
            log!(log_level, "{}", lines.join("\n"));
        }
    }
}

impl<T> FancyUnwrap for Result<T> {
    type Output = T;

    fn fancy_unwrap(self) -> T {
        match self {
            Ok(value) => value,
            Err(err) => {
                print_trace(err, log::Level::Error);
                std::process::exit(1);
            }
        }
    }
}

// TODO: replace with a proper mechanism
pub fn should_panic_on_unexpected() -> bool {
    true
}

#[macro_export]
macro_rules! unexpected {
    ($e:expr) => {
        if $crate::errors::should_panic_on_unexpected() {
            panic!($e);
        } else {
            bail!($e);
        }
    };
    ($fmt:expr, $($arg:tt)*) => {
        if $crate::errors::should_panic_on_unexpected() {
            panic!($fmt, $($arg)*);
        } else {
            bail!($fmt, $($arg)*);
        }
    };
}
<|endoftext|>