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

use crate::core::Message;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;

use crate::reflect::accessor::FieldAccessor;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::reflect::reflect_deep_eq::ReflectDeepEq;
use crate::reflect::FieldDescriptor;

trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<dyn Message>;
    fn default_instance(&self) -> &dyn Message;
    fn clone(&self, message: &dyn Message) -> Box<dyn Message>;
    fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool;
}

struct MessageFactoryImpl<M>(marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + Message + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<dyn Message> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &dyn Message {
        M::default_instance() as &dyn Message
    }

    fn clone(&self, message: &dyn Message) -> Box<dyn Message> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

/// Dynamic representation of message type.
///
/// Used for reflection.
pub struct MessageDescriptor {
    full_name: String,
    file_descriptor_proto: &'static FileDescriptorProto,
    proto: &'static DescriptorProto,
    factory: &'static dyn MessageFactory,
    fields: Vec<FieldDescriptor>,

    index_by_name: HashMap<String, usize>,
    index_by_name_or_json_name: HashMap<String, usize>,
    index_by_number: HashMap<u32, usize>,
}

impl MessageDescriptor {
    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.proto
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> &'static MessageDescriptor {
        M::descriptor_static()
    }

    fn compute_full_name(package: &str, path_to_package: &str, proto: &DescriptorProto) -> String {
        let mut full_name = package.to_owned();
        if path_to_package.len() != 0 {
            if full_name.len() != 0 {
                full_name.push('.');
            }
            full_name.push_str(path_to_package);
        }
        if full_name.len() != 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.get_name());
        full_name
    }

    // Non-generic part of `new` is a separate function
    // to reduce code bloat from multiple instantiations.
    fn new_non_generic(
        protobuf_name_to_package: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
        factory: &'static dyn MessageFactory,
    ) -> MessageDescriptor {
        let (path_to_package, proto) =
            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
                (path_to_package, MessageOrEnum::Message(m)) => (path_to_package, m),
                (_, MessageOrEnum::Enum(_)) => panic!("not a message"),
            };

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.field {
            field_proto_by_name.insert(field_proto.get_name(), field_proto);
        }

        let mut index_by_name = HashMap::new();
        let mut index_by_name_or_json_name = HashMap::new();
        let mut index_by_number = HashMap::new();

        let fields: Vec<_> = fields
            .into_iter()
            .map(|f| {
                let proto = *field_proto_by_name.get(f.name).unwrap();
                FieldDescriptor::new(f, proto)
            })
            .collect();

        for (i, f) in fields.iter().enumerate() {
            assert!(index_by_number
                .insert(f.proto().get_number() as u32, i)
                .is_none());
            assert!(index_by_name
                .insert(f.proto().get_name().to_owned(), i)
                .is_none());
            assert!(index_by_name_or_json_name
                .insert(f.proto().get_name().to_owned(), i)
                .is_none());

            let json_name = f.json_name().to_owned();

            if json_name != f.proto().get_name() {
                assert!(index_by_name_or_json_name.insert(json_name, i).is_none());
            }
        }
        MessageDescriptor {
            full_name: MessageDescriptor::compute_full_name(
                file_descriptor_proto.get_package(),
                &path_to_package,
                &proto,
            ),
            proto,
            factory,
            fields,
            index_by_name,
            index_by_name_or_json_name,
            index_by_number,
            file_descriptor_proto,
        }
    }

    /// Construct a new message descriptor.
    ///
    /// This operation is called from generated code and rarely
    /// need to be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new<M: 'static + Message + Default + Clone + PartialEq>(
        protobuf_name_to_package: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> MessageDescriptor {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        MessageDescriptor::new_non_generic(
            protobuf_name_to_package,
            fields,
            file_descriptor_proto,
            factory,
        )
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor_proto
    }

    /// New empty message
    pub fn new_instance(&self) -> Box<dyn Message> {
        self.factory.new_instance()
    }

    /// Shared immutable empty message
    pub fn default_instance(&self) -> &dyn Message {
        self.factory.default_instance()
    }

    /// Clone a message
    pub fn clone(&self, message: &dyn Message) -> Box<dyn Message> {
        self.factory.clone(message)
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        self.factory.eq(a, b)
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn deep_eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(
            self as *const MessageDescriptor,
            a.descriptor() as *const MessageDescriptor
        );
        assert_eq!(
            self as *const MessageDescriptor,
            b.descriptor() as *const MessageDescriptor
        );

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_deep_eq(&bf) {
                return false;
            }
        }
        true
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    /// Message field descriptors.
    pub fn fields(&self) -> &[FieldDescriptor] {
        &self.fields
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    pub fn field_by_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name_or_json_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name
    pub fn field_by_number<'a>(&'a self, number: u32) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.fields[index])
    }

    /// This operation is not needed here
    // TODO: remove it
    pub fn cast<M: 'static>(&self, message: Box<dyn Message>) -> Result<M, Box<dyn Message>> {
        message.downcast_box::<M>().map(|m| *m)
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for MessageDescriptor {
    fn eq(&self, other: &MessageDescriptor) -> bool {
        self as *const MessageDescriptor == other as *const MessageDescriptor
    }
}
<commit_msg>Erase lifetimes<commit_after>use std::collections::HashMap;
use std::marker;

use crate::core::Message;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;

use crate::reflect::accessor::FieldAccessor;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;
use crate::reflect::reflect_deep_eq::ReflectDeepEq;
use crate::reflect::FieldDescriptor;

trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<dyn Message>;
    fn default_instance(&self) -> &dyn Message;
    fn clone(&self, message: &dyn Message) -> Box<dyn Message>;
    fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool;
}

struct MessageFactoryImpl<M>(marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + Message + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<dyn Message> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &dyn Message {
        M::default_instance() as &dyn Message
    }

    fn clone(&self, message: &dyn Message) -> Box<dyn Message> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

/// Dynamic representation of message type.
///
/// Used for reflection.
pub struct MessageDescriptor {
    full_name: String,
    file_descriptor_proto: &'static FileDescriptorProto,
    proto: &'static DescriptorProto,
    factory: &'static dyn MessageFactory,
    fields: Vec<FieldDescriptor>,

    index_by_name: HashMap<String, usize>,
    index_by_name_or_json_name: HashMap<String, usize>,
    index_by_number: HashMap<u32, usize>,
}

impl MessageDescriptor {
    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.proto
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> &'static MessageDescriptor {
        M::descriptor_static()
    }

    fn compute_full_name(package: &str, path_to_package: &str, proto: &DescriptorProto) -> String {
        let mut full_name = package.to_owned();
        if path_to_package.len() != 0 {
            if full_name.len() != 0 {
                full_name.push('.');
            }
            full_name.push_str(path_to_package);
        }
        if full_name.len() != 0 {
            full_name.push('.');
        }
        full_name.push_str(proto.get_name());
        full_name
    }

    // Non-generic part of `new` is a separate function
    // to reduce code bloat from multiple instantiations.
    fn new_non_generic(
        protobuf_name_to_package: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
        factory: &'static dyn MessageFactory,
    ) -> MessageDescriptor {
        let (path_to_package, proto) =
            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
                (path_to_package, MessageOrEnum::Message(m)) => (path_to_package, m),
                (_, MessageOrEnum::Enum(_)) => panic!("not a message"),
            };

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.field {
            field_proto_by_name.insert(field_proto.get_name(), field_proto);
        }

        let mut index_by_name = HashMap::new();
        let mut index_by_name_or_json_name = HashMap::new();
        let mut index_by_number = HashMap::new();

        let fields: Vec<_> = fields
            .into_iter()
            .map(|f| {
                let proto = *field_proto_by_name.get(f.name).unwrap();
                FieldDescriptor::new(f, proto)
            })
            .collect();

        for (i, f) in fields.iter().enumerate() {
            assert!(index_by_number
                .insert(f.proto().get_number() as u32, i)
                .is_none());
            assert!(index_by_name
                .insert(f.proto().get_name().to_owned(), i)
                .is_none());
            assert!(index_by_name_or_json_name
                .insert(f.proto().get_name().to_owned(), i)
                .is_none());

            let json_name = f.json_name().to_owned();

            if json_name != f.proto().get_name() {
                assert!(index_by_name_or_json_name.insert(json_name, i).is_none());
            }
        }
        MessageDescriptor {
            full_name: MessageDescriptor::compute_full_name(
                file_descriptor_proto.get_package(),
                &path_to_package,
                &proto,
            ),
            proto,
            factory,
            fields,
            index_by_name,
            index_by_name_or_json_name,
            index_by_number,
            file_descriptor_proto,
        }
    }

    /// Construct a new message descriptor.
    ///
    /// This operation is called from generated code and rarely
    /// need to be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new<M: 'static + Message + Default + Clone + PartialEq>(
        protobuf_name_to_package: &'static str,
        fields: Vec<FieldAccessor>,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> MessageDescriptor {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        MessageDescriptor::new_non_generic(
            protobuf_name_to_package,
            fields,
            file_descriptor_proto,
            factory,
        )
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor_proto
    }

    /// New empty message
    pub fn new_instance(&self) -> Box<dyn Message> {
        self.factory.new_instance()
    }

    /// Shared immutable empty message
    pub fn default_instance(&self) -> &dyn Message {
        self.factory.default_instance()
    }

    /// Clone a message
    pub fn clone(&self, message: &dyn Message) -> Box<dyn Message> {
        self.factory.clone(message)
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        self.factory.eq(a, b)
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn deep_eq(&self, a: &dyn Message, b: &dyn Message) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(
            self as *const MessageDescriptor,
            a.descriptor() as *const MessageDescriptor
        );
        assert_eq!(
            self as *const MessageDescriptor,
            b.descriptor() as *const MessageDescriptor
        );

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_deep_eq(&bf) {
                return false;
            }
        }
        true
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &'static str {
        self.proto.get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.full_name[..]
    }

    /// Message field descriptors.
    pub fn fields(&self) -> &[FieldDescriptor] {
        &self.fields
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    pub fn field_by_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<&'a FieldDescriptor> {
        let &index = self.index_by_name_or_json_name.get(name)?;
        Some(&self.fields[index])
    }

    /// Find message field by field name
    pub fn field_by_number(&self, number: u32) -> Option<&FieldDescriptor> {
        let &index = self.index_by_number.get(&number)?;
        Some(&self.fields[index])
    }

    /// This operation is not needed here
    // TODO: remove it
    pub fn cast<M: 'static>(&self, message: Box<dyn Message>) -> Result<M, Box<dyn Message>> {
        message.downcast_box::<M>().map(|m| *m)
    }
}

/// Identity comparison: message descriptor are equal if their addresses are equal
impl PartialEq for MessageDescriptor {
    fn eq(&self, other: &MessageDescriptor) -> bool {
        self as *const MessageDescriptor == other as *const MessageDescriptor
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use rand::{thread_rng, sample};

struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn reveal<'a>(&self) -> Result<i32, &'a str> {
        match self.content.len() {
            1 => match self.digits.len() {
                0 => Ok(self.content[0]),
                _ => Err("Did not use all digits!"),
            },
            _ => Err("Invalid formula!"),
        }
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            //return answer;
            println!("Actual: {}", answer.unwrap_err());
            return Err("Program error");
        }
    }

    stack.reveal()
}

fn main() {
    let goal: i32 = 24;
    let mut rng = thread_rng();

    println!("GUESSING GAME!\n");

    loop {
        let mut program = String::new();
        let digits = sample(&mut rng, 1..9, 4);

        println!("Your digits are: {}\n", digits.iter().fold("".to_string(), |acc, &d| acc + &d.to_string()[..] + ", "));
        println!("Enter an expression:\n");

        io::stdin().read_line(&mut program)
            .ok()
            .expect("Could not read input.");

        let parsed = program
            .trim()
            .chars()
            .filter(|&c| c != ' ')
            .collect();

        match evaluate(parsed, digits) {
            Ok(n) => if n == goal {
                println!("\nWell done!\n");
                break;
            } else {
                println!("\nNice try, but {} is not {}!\n", n, goal);
            },
            Err(s) => {
                println!("\nOops: {}\n", s);
            },
        }
    }

}
<commit_msg>Added instructions<commit_after>extern crate rand;

use std::io;
use rand::{thread_rng, sample};

struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn reveal<'a>(&self) -> Result<i32, &'a str> {
        match self.content.len() {
            1 => match self.digits.len() {
                0 => Ok(self.content[0]),
                _ => Err("Did not use all digits!"),
            },
            _ => Err("Invalid formula!"),
        }
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            //return answer;
            println!("Actual: {}", answer.unwrap_err());
            return Err("Program error");
        }
    }

    stack.reveal()
}

fn main() {
    let goal: i32 = 24;
    let mut rng = thread_rng();

    println!("GUESSING GAME!

RULES

  * Using only the given digits, create an expression that evaluates to 24.
  * All digits must be used.
  * Each digit may only be used once.
  * Expressions must be in Reverse-Polish Notation (RPN).
  * Only +, -, * and / are allowed.
  * Order of the digits is not important.\n");

    loop {
        let mut program = String::new();
        let digits = sample(&mut rng, 1..9, 4);

        println!("Your digits are: {}\n", digits.iter().fold("".to_string(), |acc, &d| acc + &d.to_string()[..] + ", "));
        println!("Enter an expression:\n");

        io::stdin().read_line(&mut program)
            .ok()
            .expect("Could not read input.");

        let parsed = program
            .trim()
            .chars()
            .filter(|&c| c != ' ')
            .collect();

        match evaluate(parsed, digits) {
            Ok(n) => if n == goal {
                println!("\nWell done!\n");
                break;
            } else {
                println!("\nNice try, but {} is not {}!\n", n, goal);
            },
            Err(s) => {
                println!("\nOops: {}\n", s);
            },
        }
    }
}
<|endoftext|>


<commit_before>use DocId;
use postings::{Postings, DocSet};
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use query::MultiTermScorer;
use postings::ScoredDocSet;
use query::Scorer;
use fastfield::U32FastFieldReader;

#[derive(Eq, PartialEq)]
struct HeapItem(DocId, usize, u32);

impl PartialOrd for HeapItem {
    fn partial_cmp(&self, other:&Self) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl Ord for HeapItem {
    fn cmp(&self, other:&Self) -> Ordering {
         (self.0, self.1).cmp(&(other.0, other.1)).reverse()
    }
}

pub struct UnionPostings<TPostings: Postings> {
    fieldnorms_readers: Vec<U32FastFieldReader>,
    postings: Vec<TPostings>,
    queue: BinaryHeap<HeapItem>,
    doc: DocId,
    scorer: MultiTermScorer
}

impl<TPostings: Postings> UnionPostings<TPostings> {

    pub fn new(fieldnorms_reader: Vec<U32FastFieldReader>, postings: Vec<TPostings>, multi_term_scorer: MultiTermScorer) -> UnionPostings<TPostings> {
        let num_postings = postings.len();
        assert_eq!(fieldnorms_reader.len(), num_postings);
        let mut union_postings = UnionPostings {
            fieldnorms_readers: fieldnorms_reader,
            postings: postings,
            queue: BinaryHeap::new(),
            doc: 0,
            scorer: multi_term_scorer
        };
        for ord in 0..num_postings {
            union_postings.enqueue(ord);
        }
        union_postings
    }

    fn enqueue(&mut self, ord: usize) {
        let cur_postings = &mut self.postings[ord];
        if cur_postings.next() {
            let doc = cur_postings.doc();
            let tf = cur_postings.term_freq();
            self.queue.push(HeapItem(doc, ord, tf));
        }
    }

    fn get_field_norm(&self, ord:usize, doc:DocId) -> u32 {
        self.fieldnorms_readers[ord].get(doc)
    }

}

impl<TPostings: Postings> DocSet for UnionPostings<TPostings> {

    fn next(&mut self,) -> bool {
        self.scorer.clear();
        let head = self.queue.pop();
        match head {
            Some(HeapItem(doc, ord, tf)) => {
                // let fieldnorm = self.get_field_norm(ord, doc);
                let fieldnorm: u32 = 1u32;
                self.scorer.update(ord, tf, fieldnorm);
                self.enqueue(ord);
                self.doc = doc;
                loop {
                    match self.queue.peek() {
                        Some(&HeapItem(peek_doc, _, _))  => {
                            if peek_doc != doc {
                                break;
                            }
                        }
                        None => { break; }
                    }
                    let HeapItem(_, peek_ord, peek_tf) = self.queue.pop().unwrap();
                    let fieldnorm = self.get_field_norm(peek_ord, doc);
                    self.scorer.update(peek_ord, peek_tf, fieldnorm);
                    self.enqueue(peek_ord);
                }
                return true;
            }
            None => {
                return false;
            }
        }
    }

    // TODO implement a faster skip_next

    fn doc(&self,) -> DocId {
        self.doc
    }

    fn doc_freq(&self,) -> usize {
        panic!("Doc freq");
    }
}

impl<TPostings: Postings> ScoredDocSet for UnionPostings<TPostings> {
    fn score(&self,) -> f32 {
        self.scorer.score()
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use postings::{DocSet, VecPostings, ScoredDocSet};
    use query::MultiTermScorer;
    use directory::ReadOnlySource;
    use directory::SharedVec;
    use schema::Field;
    use fastfield::{U32FastFieldReader, U32FastFieldWriter, FastFieldSerializer};

    pub fn create_u32_fastfieldreader(field: Field, vals: Vec<u32>) -> U32FastFieldReader {
        let mut u32_field_writer = U32FastFieldWriter::new(field);
        for val in vals {
            u32_field_writer.add_val(val);
        }
        let data = SharedVec::new();
        let write: Box<SharedVec> = Box::new(data.clone());
        let mut serializer = FastFieldSerializer::new(write).unwrap();
        u32_field_writer.serialize(&mut serializer).unwrap();
        serializer.close().unwrap();
        U32FastFieldReader::open(ReadOnlySource::Anonymous(data.copy_vec())).unwrap()
    }

    fn abs_diff(left: f32, right: f32) -> f32 {
        (right - left).abs()
    }

    #[test]
    pub fn test_union_postings() {
        let left_fieldnorms = create_u32_fastfieldreader(Field(1), vec!(100,200,300));
        let right_fieldnorms = create_u32_fastfieldreader(Field(2), vec!(15,25,35));
        let left = VecPostings::new(vec!(1, 2, 3));
        let right = VecPostings::new(vec!(1, 3, 8));
        let multi_term_scorer = MultiTermScorer::new(vec!(1f32, 2f32), vec!(1f32, 4f32));
        let mut union = UnionPostings::new(
            vec!(left_fieldnorms, right_fieldnorms),
            vec!(left, right),
            multi_term_scorer
        );
        assert!(union.next());
        assert_eq!(union.doc(), 1);
        assert!(abs_diff(union.score(), 2.182179f32) < 0.001);
        assert!(union.next());
        assert_eq!(union.doc(), 2);
        assert!(abs_diff(union.score(), 0.2236068) < 0.001f32);
        assert!(union.next());
        assert_eq!(union.doc(), 3);
        assert!(union.next());
        assert!(abs_diff(union.score(), 0.8944272f32) < 0.001f32);
        assert_eq!(union.doc(), 8);
        assert!(!union.next());
    }

}

<commit_msg>fixing unit tests<commit_after>use DocId;
use postings::{Postings, DocSet};
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use query::MultiTermScorer;
use postings::ScoredDocSet;
use query::Scorer;
use fastfield::U32FastFieldReader;

#[derive(Eq, PartialEq)]
struct HeapItem(DocId, usize, u32);

impl PartialOrd for HeapItem {
    fn partial_cmp(&self, other:&Self) -> Option<Ordering> {
        Some(self.cmp(&other))
    }
}

impl Ord for HeapItem {
    fn cmp(&self, other:&Self) -> Ordering {
         (self.0, self.1).cmp(&(other.0, other.1)).reverse()
    }
}

pub struct UnionPostings<TPostings: Postings> {
    fieldnorms_readers: Vec<U32FastFieldReader>,
    postings: Vec<TPostings>,
    queue: BinaryHeap<HeapItem>,
    doc: DocId,
    scorer: MultiTermScorer
}

impl<TPostings: Postings> UnionPostings<TPostings> {

    pub fn new(fieldnorms_reader: Vec<U32FastFieldReader>, postings: Vec<TPostings>, multi_term_scorer: MultiTermScorer) -> UnionPostings<TPostings> {
        let num_postings = postings.len();
        assert_eq!(fieldnorms_reader.len(), num_postings);
        let mut union_postings = UnionPostings {
            fieldnorms_readers: fieldnorms_reader,
            postings: postings,
            queue: BinaryHeap::new(),
            doc: 0,
            scorer: multi_term_scorer
        };
        for ord in 0..num_postings {
            union_postings.enqueue(ord);
        }
        union_postings
    }

    fn enqueue(&mut self, ord: usize) {
        let cur_postings = &mut self.postings[ord];
        if cur_postings.next() {
            let doc = cur_postings.doc();
            let tf = cur_postings.term_freq();
            self.queue.push(HeapItem(doc, ord, tf));
        }
    }

    fn get_field_norm(&self, ord:usize, doc:DocId) -> u32 {
        self.fieldnorms_readers[ord].get(doc)
    }

}

impl<TPostings: Postings> DocSet for UnionPostings<TPostings> {

    fn next(&mut self,) -> bool {
        self.scorer.clear();
        let head = self.queue.pop();
        match head {
            Some(HeapItem(doc, ord, tf)) => {
                let fieldnorm = self.get_field_norm(ord, doc);
                self.scorer.update(ord, tf, fieldnorm);
                self.enqueue(ord);
                self.doc = doc;
                loop {
                    match self.queue.peek() {
                        Some(&HeapItem(peek_doc, _, _))  => {
                            if peek_doc != doc {
                                break;
                            }
                        }
                        None => { break; }
                    }
                    let HeapItem(_, peek_ord, peek_tf) = self.queue.pop().unwrap();
                    let fieldnorm = self.get_field_norm(peek_ord, doc);
                    self.scorer.update(peek_ord, peek_tf, fieldnorm);
                    self.enqueue(peek_ord);
                }
                return true;
            }
            None => {
                return false;
            }
        }
    }

    // TODO implement a faster skip_next

    fn doc(&self,) -> DocId {
        self.doc
    }

    fn doc_freq(&self,) -> usize {
        panic!("Doc freq");
    }
}

impl<TPostings: Postings> ScoredDocSet for UnionPostings<TPostings> {
    fn score(&self,) -> f32 {
        self.scorer.score()
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use postings::{DocSet, VecPostings, ScoredDocSet};
    use query::MultiTermScorer;
    use directory::ReadOnlySource;
    use directory::SharedVec;
    use schema::Field;
    use fastfield::{U32FastFieldReader, U32FastFieldWriter, FastFieldSerializer};

    pub fn create_u32_fastfieldreader(field: Field, vals: Vec<u32>) -> U32FastFieldReader {
        let mut u32_field_writer = U32FastFieldWriter::new(field);
        for val in vals {
            u32_field_writer.add_val(val);
        }
        let data = SharedVec::new();
        let write: Box<SharedVec> = Box::new(data.clone());
        let mut serializer = FastFieldSerializer::new(write).unwrap();
        u32_field_writer.serialize(&mut serializer).unwrap();
        serializer.close().unwrap();
        U32FastFieldReader::open(ReadOnlySource::Anonymous(data.copy_vec())).unwrap()
    }

    fn abs_diff(left: f32, right: f32) -> f32 {
        (right - left).abs()
    }

    #[test]
    pub fn test_union_postings() {
        let left_fieldnorms = create_u32_fastfieldreader(Field(1), vec!(100,200,300));
        let right_fieldnorms = create_u32_fastfieldreader(Field(2), vec!(15,25,35));
        let left = VecPostings::new(vec!(1, 2, 3));
        let right = VecPostings::new(vec!(1, 3, 8));
        let multi_term_scorer = MultiTermScorer::new(vec!(1f32, 2f32), vec!(1f32, 4f32));
        let mut union = UnionPostings::new(
            vec!(left_fieldnorms, right_fieldnorms),
            vec!(left, right),
            multi_term_scorer
        );
        assert!(union.next());
        assert_eq!(union.doc(), 1);
        assert!(abs_diff(union.score(), 2.182179f32) < 0.001);
        assert!(union.next());
        assert_eq!(union.doc(), 2);
        assert!(abs_diff(union.score(), 0.2236068) < 0.001f32);
        assert!(union.next());
        assert_eq!(union.doc(), 3);
        assert!(union.next());
        assert!(abs_diff(union.score(), 0.8944272f32) < 0.001f32);
        assert_eq!(union.doc(), 8);
        assert!(!union.next());
    }

}

<|endoftext|>


<commit_before>use std::process;
use std::sync::{Arc};
use std::path::{Path};
use std::collections::{HashMap};

use crossbeam::sync::{MsQueue};
use glium::{Surface, Program, DrawParameters, Depth, Frame};
use glium::backend::glutin_backend::{GlutinFacade};
use glium::draw_parameters::{DepthTest};

use model::{Model};
use render::render_command::{RenderCommand};
use scene::{Scene};
use input_event::{InputEvent};

// TODO: We can remove clear calls if we clear in the swapbuffers (and replace our old frame objec with a new one)
//
pub struct RenderProcessor {
	q: Arc<MsQueue<RenderCommand>>,
	context: GlutinFacade, // TODO: can we use a better type here
	frames: HashMap<u64, Frame>,
	player: Model,
	scene: Scene,
	program: Program,
	draw_parameters: DrawParameters<'static>,
}

impl RenderProcessor {
	pub fn new(q: Arc<MsQueue<RenderCommand>>, context: GlutinFacade) -> RenderProcessor {
		const PLAYER_PATH_STRING: &'static str = "./data/player.obj";
		let player = Model::new(&context, &Path::new(PLAYER_PATH_STRING));

		let scene = Scene::new(&context);

		let vertex_source = r#"
			#version 140

			in vec3 position;
			in vec3 normal;

			out vec3 v_normal;

			uniform mat4 mvp;

			void main() {
				v_normal = normalize((mvp * vec4(normal, 0.0)).xyz);
				gl_Position = mvp * vec4(position, 1.0);
			}
		"#;
		let fragment_source = r#"
			#version 140

			in vec3 v_normal;

			out vec4 color;

			void main() {
				float value = dot(v_normal, vec3(0.707, 0.707, 0.0));
				float intensity = max(0.0, value);
				color = vec4(intensity, intensity, intensity, 1.0);
//				color = value > 0.0 ? vec4(0.5, 0.25, 0.125, 1.0) : vec4(0.9, 0.45, 0.45, 1.0);
			}
		"#;
		// TODO: make sure constants are right

		let program = match Program::from_source(&context, vertex_source, fragment_source, None) {
			Ok(p) => p,
			Err(e) => {
				println!("Unable to compile shaders: {}", e);
				process::exit(-3);
			},
		};

		RenderProcessor {
			q: q,
			context: context,
			frames: HashMap::new(),
			player: player,
			scene: scene,
			program: program,
			draw_parameters: DrawParameters {
				depth: Depth {
					test: DepthTest::IfLess,
					write: true,
					.. Default::default()
				},
				.. Default::default()
			},
		}
	}

	// returns true to signal caller to exit program and event loop
	// TODO: should std::process::exit(i32) be used instead?
	//
	pub fn handle_system_events(&self) -> Option<Vec<InputEvent>> {
		use glium::glutin::{Event, VirtualKeyCode, ElementState};

		let mut out = Vec::new();

		for event in self.context.poll_events() {
			match event {
				Event::Closed => {
					println!("Exiting due to quit event");
					out.push(InputEvent::Quit);
					return None;
				},
				Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) => {
					println!("Exiting due to escape key");
					return None;
				},
				Event::KeyboardInput(state, _, Some(key_code)) => {
					out.push(InputEvent::KeyboardInput {
						pressed: state == ElementState::Pressed,
						id: key_code,
					});
				},
				_ => ()
			}
		}
		Some(out)
	}

	pub fn handle_render_commands(&mut self) {

		// macro required because we want to pass different models and use mut member variables
		//
		macro_rules! draw_model {
			($model:expr, $frame_counter:expr, $uniforms:expr) => {{
				// TODO: do something about this terrible syntax
				// and try to dump the macro
				//
				let mut frame = self.frames.get_mut(&$frame_counter).unwrap();

				let uniform_buffer = uniform! {
					mvp: $uniforms.mvp,
				};

				frame.draw(
					&$model.vertex_buffer,
					&$model.index_buffer,
					&self.program,
					&uniform_buffer,
					&self.draw_parameters).unwrap();
			}}
		}

		loop {
			let job = match self.q.try_pop() {
				Some(j) => j,
				None    => break,
			};

			match job {
				RenderCommand::ClearScreen{ render_frame } => {
					let mut frame = self.context.draw();
					frame.clear_color_and_depth((0.125f32, 0.25f32, 0.5f32, 1.0f32), 1.0);
					self.frames.insert(render_frame.frame_counter, frame);
				},
				RenderCommand::SwapBuffers{ frame_counter } => {
					let mut frame = self.frames.remove(&frame_counter).unwrap();

					frame.set_finish().unwrap();
				},
				RenderCommand::DrawScene{ frame_counter, uniforms } => {
					draw_model!(&self.scene.model, frame_counter, uniforms);
				},
				RenderCommand::DrawPlayer{ frame_counter, uniforms } => {
					draw_model!(&self.player, frame_counter, uniforms);
				},
			}
		}
	}
}
<commit_msg>Refactor 'use' location for consistency<commit_after>use std::process;
use std::sync::{Arc};
use std::path::{Path};
use std::collections::{HashMap};

use crossbeam::sync::{MsQueue};
use glium::{Surface, Program, DrawParameters, Depth, Frame};
use glium::glutin::{Event, VirtualKeyCode, ElementState};
use glium::backend::glutin_backend::{GlutinFacade};
use glium::draw_parameters::{DepthTest};

use model::{Model};
use render::render_command::{RenderCommand};
use scene::{Scene};
use input_event::{InputEvent};

// TODO: We can remove clear calls if we clear in the swapbuffers (and replace our old frame objec with a new one)
//
pub struct RenderProcessor {
	q: Arc<MsQueue<RenderCommand>>,
	context: GlutinFacade, // TODO: can we use a better type here
	frames: HashMap<u64, Frame>,
	player: Model,
	scene: Scene,
	program: Program,
	draw_parameters: DrawParameters<'static>,
}

impl RenderProcessor {
	pub fn new(q: Arc<MsQueue<RenderCommand>>, context: GlutinFacade) -> RenderProcessor {
		const PLAYER_PATH_STRING: &'static str = "./data/player.obj";
		let player = Model::new(&context, &Path::new(PLAYER_PATH_STRING));

		let scene = Scene::new(&context);

		let vertex_source = r#"
			#version 140

			in vec3 position;
			in vec3 normal;

			out vec3 v_normal;

			uniform mat4 mvp;

			void main() {
				v_normal = normalize((mvp * vec4(normal, 0.0)).xyz);
				gl_Position = mvp * vec4(position, 1.0);
			}
		"#;
		let fragment_source = r#"
			#version 140

			in vec3 v_normal;

			out vec4 color;

			void main() {
				float value = dot(v_normal, vec3(0.707, 0.707, 0.0));
				float intensity = max(0.0, value);
				color = vec4(intensity, intensity, intensity, 1.0);
//				color = value > 0.0 ? vec4(0.5, 0.25, 0.125, 1.0) : vec4(0.9, 0.45, 0.45, 1.0);
			}
		"#;
		// TODO: make sure constants are right

		let program = match Program::from_source(&context, vertex_source, fragment_source, None) {
			Ok(p) => p,
			Err(e) => {
				println!("Unable to compile shaders: {}", e);
				process::exit(-3);
			},
		};

		RenderProcessor {
			q: q,
			context: context,
			frames: HashMap::new(),
			player: player,
			scene: scene,
			program: program,
			draw_parameters: DrawParameters {
				depth: Depth {
					test: DepthTest::IfLess,
					write: true,
					.. Default::default()
				},
				.. Default::default()
			},
		}
	}

	// returns true to signal caller to exit program and event loop
	// TODO: should std::process::exit(i32) be used instead?
	//
	pub fn handle_system_events(&self) -> Option<Vec<InputEvent>> {
		let mut out = Vec::new();

		for event in self.context.poll_events() {
			match event {
				Event::Closed => {
					println!("Exiting due to quit event");
					out.push(InputEvent::Quit);
					return None;
				},
				Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) => {
					println!("Exiting due to escape key");
					return None;
				},
				Event::KeyboardInput(state, _, Some(key_code)) => {
					out.push(InputEvent::KeyboardInput {
						pressed: state == ElementState::Pressed,
						id: key_code,
					});
				},
				_ => ()
			}
		}
		Some(out)
	}

	pub fn handle_render_commands(&mut self) {

		// macro required because we want to pass different models and use mut member variables
		//
		macro_rules! draw_model {
			($model:expr, $frame_counter:expr, $uniforms:expr) => {{
				// TODO: do something about this terrible syntax
				// and try to dump the macro
				//
				let mut frame = self.frames.get_mut(&$frame_counter).unwrap();

				let uniform_buffer = uniform! {
					mvp: $uniforms.mvp,
				};

				frame.draw(
					&$model.vertex_buffer,
					&$model.index_buffer,
					&self.program,
					&uniform_buffer,
					&self.draw_parameters).unwrap();
			}}
		}

		loop {
			let job = match self.q.try_pop() {
				Some(j) => j,
				None    => break,
			};

			match job {
				RenderCommand::ClearScreen{ render_frame } => {
					let mut frame = self.context.draw();
					frame.clear_color_and_depth((0.125f32, 0.25f32, 0.5f32, 1.0f32), 1.0);
					self.frames.insert(render_frame.frame_counter, frame);
				},
				RenderCommand::SwapBuffers{ frame_counter } => {
					let mut frame = self.frames.remove(&frame_counter).unwrap();

					frame.set_finish().unwrap();
				},
				RenderCommand::DrawScene{ frame_counter, uniforms } => {
					draw_model!(&self.scene.model, frame_counter, uniforms);
				},
				RenderCommand::DrawPlayer{ frame_counter, uniforms } => {
					draw_model!(&self.player, frame_counter, uniforms);
				},
			}
		}
	}
}
<|endoftext|>


<commit_before>// xfail-stage0
use std;

import std._int;
import std._str.eq;

fn test_to_str() {
  check (eq(_int.to_str(0, 10u), "0"));
  check (eq(_int.to_str(1, 10u), "1"));
  check (eq(_int.to_str(-1, 10u), "-1"));
  check (eq(_int.to_str(255, 16u), "ff"));
  check (eq(_int.to_str(100, 10u), "100"));
}

fn test_pow() {
  check (_int.pow(0, 0u) == 1);
  check (_int.pow(0, 1u) == 0);
  check (_int.pow(0, 2u) == 0);
  check (_int.pow(-1, 0u) == -1);
  check (_int.pow(1, 0u) == 1);
  check (_int.pow(-3, 2u) == 9);
  check (_int.pow(-3, 3u) == -27);
  check (_int.pow(4, 9u) == 262144);
}

fn main() {
  test_to_str();
}
<commit_msg>rustc: Un-XFAIL lib-int.rs.<commit_after>use std;

import std._int;
import std._str.eq;

fn test_to_str() {
  check (eq(_int.to_str(0, 10u), "0"));
  check (eq(_int.to_str(1, 10u), "1"));
  check (eq(_int.to_str(-1, 10u), "-1"));
  check (eq(_int.to_str(255, 16u), "ff"));
  check (eq(_int.to_str(100, 10u), "100"));
}

fn test_pow() {
  check (_int.pow(0, 0u) == 1);
  check (_int.pow(0, 1u) == 0);
  check (_int.pow(0, 2u) == 0);
  check (_int.pow(-1, 0u) == -1);
  check (_int.pow(1, 0u) == 1);
  check (_int.pow(-3, 2u) == 9);
  check (_int.pow(-3, 3u) == -27);
  check (_int.pow(4, 9u) == 262144);
}

fn main() {
  test_to_str();
}
<|endoftext|>


<commit_before>use elektra_sys::{keyDel, keyDup, keyName, keyNew, keySetName, keySetString};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr::NonNull;

#[derive(Debug, PartialEq)]
pub enum KeyError {
    InvalidName,
    TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            KeyError::TypeMismatch => write!(f, "Binary/String key mismatch, use the appropriate method for your key type, get_string or get_binary"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

#[derive(Debug)]
pub struct Key {
    ptr: NonNull<elektra_sys::Key>,
}

impl Drop for Key {
    fn drop(&mut self) {
        println!("Drop {:?}", self);
        unsafe { keyDel(self.ptr.as_ptr()) };
    }
}

impl PartialEq for Key {
    fn eq(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyCmp(
                self.ptr.as_ptr() as *const elektra_sys::Key,
                other.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 0
        }
    }
}

impl Eq for Key {}

impl Ord for Key {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        let cmp = unsafe {
            elektra_sys::keyCmp(
                self.ptr.as_ptr() as *const elektra_sys::Key,
                other.ptr.as_ptr() as *const elektra_sys::Key,
            )
        };

        if cmp < 0 {
            std::cmp::Ordering::Less
        } else if cmp == 0 {
            std::cmp::Ordering::Equal
        } else {
            std::cmp::Ordering::Greater
        }
    }
}

impl PartialOrd for Key {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Key {
    /// Construct a new key with a name
    pub fn new(name: &str) -> Result<Key, KeyError> {
        let mut key = Key::new_empty();
        key.set_name(name)?;
        Ok(key)
    }

    /// Construct a new empty key
    pub fn new_empty() -> Key {
        let key_ptr = unsafe { keyNew(0 as *const i8) };
        Key::from(key_ptr)
    }

    /// Construct a new key from a raw key pointer
    pub fn from(ptr: *mut elektra_sys::Key) -> Key {
        Key {
            ptr: NonNull::new(ptr).unwrap(),
        }
    }

    /// Set the name of a key. Must adhere to the rules for keynames otherwise an error is returned.
    /// Returns the size in bytes of this new key name including the ending NUL.
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let mut key = Key::new_empty();
    /// key.set_name("user/test/rust").unwrap();
    /// assert_eq!(key.get_name(), "user/test/rust");
    /// ```
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self.ptr.as_ptr(), cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice.
    pub fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self.ptr.as_ref())) };
        c_str.to_str().unwrap()
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    pub fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.ptr.as_ptr()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val as usize
    }

    /// Sets the value of the key to the supplied string.
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_string(&mut self, value: &str) {
        let cptr = CString::new(value).unwrap();
        unsafe { keySetString(self.ptr.as_ptr(), cptr.as_ptr()) };
    }

    /// Returns the string value of the key if the type of the key is string, an error if it's binary.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    pub fn get_string(&self) -> Result<&str, KeyError> {
        if self.is_binary() {
            return Err(KeyError::TypeMismatch);
        }
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyString(self.ptr.as_ref())) };
        Ok(c_str.to_str().unwrap())
    }

    /// Sets the key's binary content to the supplied data.
    pub fn set_binary(&mut self, data: &[u8]) {
        unsafe {
            elektra_sys::keySetBinary(
                self.ptr.as_ptr(),
                data.as_ptr() as *const std::os::raw::c_void,
                data.len(),
            );
        }
    }

    /// Returns the keys binary content
    /// Returns a TypeMismatch if the key is of type string
    pub fn get_binary(&self) -> Result<Vec<u8>, KeyError> {
        if self.is_string() {
            return Err(KeyError::TypeMismatch);
        }
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_value_size());

        let ret_val = unsafe {
            elektra_sys::keyGetBinary(
                self.ptr.as_ptr(),
                vec.as_mut_ptr() as *mut std::os::raw::c_void,
                vec.capacity(),
            )
        };

        if ret_val >= 0 {
            unsafe { vec.set_len(ret_val as usize) };
            Ok(vec)
        } else {
            // Since the function checks for is_string, a type mismatch is caught earlier
            // So this error can only occur as a result of a logic error in the program
            panic!("maxSize is 0, too small or too large.");
        }
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    pub fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if the key has a string value.
    pub fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if other is below self
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let key = Key::new("user/sw/app").unwrap();
    /// let key2 = Key::new("user/sw/app/folder/key").unwrap();
    /// assert!(key2.is_below(&key));
    /// ```
    pub fn is_below(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyIsBelow(
                other.ptr.as_ptr() as *const elektra_sys::Key,
                self.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 1
        }
    }

    /// Returns true if other is *directly* below self
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let key = Key::new("user/sw/app").unwrap();
    /// let key2 = Key::new("user/sw/app/key").unwrap();
    /// assert!(key2.is_direct_below(&key));
    /// ```
    pub fn is_direct_below(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyIsDirectBelow(
                other.ptr.as_ptr() as *const elektra_sys::Key,
                self.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 1
        }
    }

    /// Returns true if the key is inactive.
    /// In Elektra terminology a hierarchy of keys is inactive if the
    /// rootkey's basename starts with '.'. So a key is also inactive
    /// if it is below an inactive key. For example, `user/key/.hidden`
    /// is inactive and so is `user/.hidden/below`.
    pub fn is_inactive(&self) -> bool {
        unsafe { elektra_sys::keyIsInactive(self.ptr.as_ptr() as *const elektra_sys::Key) == 1 }
    }

    // TODO: CPP Bindings do not implement this.
    // Since is_below flips the order, this should be the case here too.
    // But does this break any usage?
    /// Information about the relation in the hierarchy between two keys.
    // pub fn rel(&self, other: &Self) -> i32 {
    //     unsafe {
    //         elektra_sys::keyRel(
    //             self.ptr.as_ptr() as *const elektra_sys::Key,
    //             other.ptr.as_ptr() as *const elektra_sys::Key,
    //         )
    //     }
    // }

    /// Return a duplicate of the key.
    pub fn duplicate(&self) -> Key {
        let dup_ptr = unsafe { keyDup(self.ptr.as_ptr()) };
        Key::from(dup_ptr)
    }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let key = Key::new(key_name).unwrap();
        assert_eq!(key.get_name(), key_name);
    }

    #[test]
    fn can_write_read_key_value() {
        let key_name = "user/test/key";
        let utf8_value = "😃";
        let mut key = Key::new(key_name).unwrap();
        key.set_string(utf8_value);
        assert_eq!(key.get_name(), key_name);
        assert_eq!(key.get_string().unwrap(), utf8_value);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let key = Key::new(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().get_name(), key_name);
    }

    #[test]
    fn can_write_read_binary() {
        let mut key = Key::new("user/test/rust").unwrap();
        let binary_content: [u8; 7] = [25, 34, 0, 254, 1, 0, 7];
        key.set_binary(&binary_content);
        let read_content = key.get_binary().unwrap();
        assert_eq!(read_content, binary_content);
    }
    #[test]
    fn can_write_read_empty_binary() {
        let mut key = Key::new("user/test/binary").unwrap();
        let binary_content: [u8; 0] = [];
        key.set_binary(&binary_content);
        // set_binary does not set binary flag, size is 0
        // so get_binary returns error
        let err = key.get_binary().unwrap_err();
        assert_eq!(err, KeyError::TypeMismatch);
    }

    #[test]
    fn equality_is_exclusive() {
        let key = Key::new("user/test/exclusive").unwrap();
        let key2 = Key::new("dir/test/exclusive").unwrap();

        assert!(!(key != key));
        assert!(key == key);

        assert!(!(key == key2));
        assert!(key != key2);
    }

    #[test]
    fn equality_is_reflexive() {
        let key = Key::new("user/test/reflexive").unwrap();
        assert!(key == key);
    }

    #[test]
    fn equality_is_symmetric() {
        let key = Key::new("user/test/symmetric").unwrap();
        let key_dup = Key::new("user/test/symmetric").unwrap();

        assert!(key_dup == key);
        assert!(key == key_dup);
    }

    #[test]
    fn equality_is_transitive() {
        let key = Key::new("user/test/transitive").unwrap();
        let key2 = Key::new("user/test/transitive").unwrap();
        let key3 = Key::new("user/test/transitive").unwrap();

        assert!(key == key2);
        assert!(key2 == key3);
        assert!(key == key3);
    }

    #[test]
    fn keys_are_ordered() {
        let key = Key::new("user/test/a").unwrap();
        let key2 = Key::new("user/test/b").unwrap();
        let key3 = Key::new("user/test/c").unwrap();

        assert!(key != key2);
        assert!(key < key2);
        assert!(key2 > key);
        // Check for antisymmetry
        assert!(!(key > key2));
        assert!(!(key2 < key));

        // Check for transitivity
        assert!(key2 < key3);
        assert!(key < key3);
    }

    #[test]
    fn keys_are_ordered_with_metadata() {
        // TODO Add once it's possible to add metadata
        //Key * k1 = keyNew("user/a", KEY_OWNER, "markus", KEY_END);
        //Key * k2 = keyNew("user/a", KEY_OWNER, "max", KEY_END);
        // keyCmp(k1,k2) < 0
        // keyCmp(k2,k1) > 0
        assert!(5 + 2 == 7);
    }
}
<commit_msg>Rust: Implement clone & key methods<commit_after>use elektra_sys::{keyDel, keyDup, keyName, keyNew, keySetName, keySetString};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr::NonNull;

#[derive(Debug, PartialEq)]
pub enum KeyError {
    InvalidName,
    TypeMismatch,
    // TypeConversion,
    // NotFoundException
}

impl fmt::Display for KeyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match self {
            KeyError::InvalidName => write!(f, "Key has an invalid name"),
            KeyError::TypeMismatch => write!(f, "Binary/String key mismatch, use the appropriate method for your key type, get_string or get_binary"),
            // _ => unimplemented!(),
        }
    }
}

impl Error for KeyError {}

#[derive(Debug)]
pub struct Key {
    ptr: NonNull<elektra_sys::Key>,
}

impl Drop for Key {
    fn drop(&mut self) {
        println!("Drop {:?}", self);
        unsafe { keyDel(self.ptr.as_ptr()) };
    }
}

impl PartialEq for Key {
    fn eq(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyCmp(
                self.ptr.as_ptr() as *const elektra_sys::Key,
                other.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 0
        }
    }
}

impl Eq for Key {}

impl Ord for Key {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        let cmp = unsafe {
            elektra_sys::keyCmp(
                self.ptr.as_ptr() as *const elektra_sys::Key,
                other.ptr.as_ptr() as *const elektra_sys::Key,
            )
        };

        if cmp < 0 {
            std::cmp::Ordering::Less
        } else if cmp == 0 {
            std::cmp::Ordering::Equal
        } else {
            std::cmp::Ordering::Greater
        }
    }
}

impl PartialOrd for Key {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Clone for Key {
    fn clone(&self) -> Self {
        self.duplicate()
    }
}

impl Key {
    // key methods
    /// Construct a new key with a name
    pub fn new(name: &str) -> Result<Key, KeyError> {
        let mut key = Key::new_empty();
        key.set_name(name)?;
        Ok(key)
    }

    /// Construct a new empty key
    pub fn new_empty() -> Key {
        let key_ptr = unsafe { keyNew(0 as *const i8) };
        Key::from(key_ptr)
    }

    /// Return a duplicate of the key.
    pub fn duplicate(&self) -> Key {
        let dup_ptr = unsafe { keyDup(self.ptr.as_ptr()) };
        Key::from(dup_ptr)
    }

    /// Construct a new key from a raw key pointer
    pub fn from(ptr: *mut elektra_sys::Key) -> Key {
        Key {
            ptr: NonNull::new(ptr).unwrap(),
        }
    }

    /// Clears the key.
    /// After this call you will receive a fresh key.
    pub fn clear(&mut self) {
        unsafe {
            elektra_sys::keyClear(self.ptr.as_ptr());
        }
    }

    /// Decrement the viability of a key object.
    /// Returns the value of the new reference counter.
    pub fn dec_ref(&mut self) -> usize {
        unsafe { elektra_sys::keyDecRef(self.ptr.as_ptr()) as usize }
    }

    /// Increment the viability of a key object.
    /// Returns the value of the new reference counter.
    pub fn inc_ref(&mut self) -> usize {
        unsafe { elektra_sys::keyIncRef(self.ptr.as_ptr()) as usize }
    }

    /// Return how many references the key has.
    pub fn get_ref(&self) -> usize {
        unsafe { elektra_sys::keyGetRef(self.ptr.as_ptr() as *const elektra_sys::Key) as usize }
    }

    // TODO keyCopy?

    // keyname methods

    /// Set the name of a key. Must adhere to the rules for keynames otherwise an error is returned.
    /// Returns the size in bytes of this new key name including the ending NUL.
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let mut key = Key::new_empty();
    /// key.set_name("user/test/rust").unwrap();
    /// assert_eq!(key.get_name(), "user/test/rust");
    /// ```
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_name(&mut self, name: &str) -> Result<u32, KeyError> {
        let cptr = CString::new(name).unwrap();
        let ret_val = unsafe { keySetName(self.ptr.as_ptr(), cptr.as_ptr()) };

        if ret_val > 0 {
            Ok(ret_val as u32)
        } else {
            Err(KeyError::InvalidName)
        }
    }

    /// Return the name of the key as a borrowed slice.
    pub fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(keyName(self.ptr.as_ref())) };
        c_str.to_str().unwrap()
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    pub fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.ptr.as_ptr()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val as usize
    }

    /// Sets the value of the key to the supplied string.
    /// # Panics
    /// Panics if the provided string contains internal nul bytes.
    pub fn set_string(&mut self, value: &str) {
        let cptr = CString::new(value).unwrap();
        unsafe { keySetString(self.ptr.as_ptr(), cptr.as_ptr()) };
    }

    /// Returns the string value of the key if the type of the key is string, an error if it's binary.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    pub fn get_string(&self) -> Result<&str, KeyError> {
        if self.is_binary() {
            return Err(KeyError::TypeMismatch);
        }
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyString(self.ptr.as_ref())) };
        Ok(c_str.to_str().unwrap())
    }

    /// Sets the key's binary content to the supplied data.
    pub fn set_binary(&mut self, data: &[u8]) {
        unsafe {
            elektra_sys::keySetBinary(
                self.ptr.as_ptr(),
                data.as_ptr() as *const std::os::raw::c_void,
                data.len(),
            );
        }
    }

    /// Returns the keys binary content
    /// Returns a TypeMismatch if the key is of type string
    pub fn get_binary(&self) -> Result<Vec<u8>, KeyError> {
        if self.is_string() {
            return Err(KeyError::TypeMismatch);
        }
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_value_size());

        let ret_val = unsafe {
            elektra_sys::keyGetBinary(
                self.ptr.as_ptr(),
                vec.as_mut_ptr() as *mut std::os::raw::c_void,
                vec.capacity(),
            )
        };

        if ret_val >= 0 {
            unsafe { vec.set_len(ret_val as usize) };
            Ok(vec)
        } else {
            // Since the function checks for is_string, a type mismatch is caught earlier
            // So this error can only occur as a result of a logic error in the program
            panic!("maxSize is 0, too small or too large.");
        }
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    pub fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if the key has a string value.
    pub fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.ptr.as_ptr()) == 1 }
    }

    /// Returns true if other is below self
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let key = Key::new("user/sw/app").unwrap();
    /// let key2 = Key::new("user/sw/app/folder/key").unwrap();
    /// assert!(key2.is_below(&key));
    /// ```
    pub fn is_below(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyIsBelow(
                other.ptr.as_ptr() as *const elektra_sys::Key,
                self.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 1
        }
    }

    /// Returns true if other is *directly* below self
    /// # Examples
    /// ```
    /// use elektra::Key;
    /// let key = Key::new("user/sw/app").unwrap();
    /// let key2 = Key::new("user/sw/app/key").unwrap();
    /// assert!(key2.is_direct_below(&key));
    /// ```
    pub fn is_direct_below(&self, other: &Self) -> bool {
        unsafe {
            elektra_sys::keyIsDirectBelow(
                other.ptr.as_ptr() as *const elektra_sys::Key,
                self.ptr.as_ptr() as *const elektra_sys::Key,
            ) == 1
        }
    }

    /// Returns true if the key is inactive.
    /// In Elektra terminology a hierarchy of keys is inactive if the
    /// rootkey's basename starts with '.'. So a key is also inactive
    /// if it is below an inactive key. For example, `user/key/.hidden`
    /// is inactive and so is `user/.hidden/below`.
    pub fn is_inactive(&self) -> bool {
        unsafe { elektra_sys::keyIsInactive(self.ptr.as_ptr() as *const elektra_sys::Key) == 1 }
    }
    // TODO: CPP Bindings do not implement this.
    // Since is_below flips the order, this should be the case here too.
    // But does this break any usage?
    // Information about the relation in the hierarchy between two keys.
    // pub fn rel(&self, other: &Self) -> i32 {
    //     unsafe {
    //         elektra_sys::keyRel(
    //             self.ptr.as_ptr() as *const elektra_sys::Key,
    //             other.ptr.as_ptr() as *const elektra_sys::Key,
    //         )
    //     }
    // }
}

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

    #[test]
    fn can_write_read_key() {
        let key_name = "user/test/key";
        let key = Key::new(key_name).unwrap();
        assert_eq!(key.get_name(), key_name);
    }

    #[test]
    fn can_write_read_key_value() {
        let key_name = "user/test/key";
        let utf8_value = "😃";
        let mut key = Key::new(key_name).unwrap();
        key.set_string(utf8_value);
        assert_eq!(key.get_name(), key_name);
        assert_eq!(key.get_string().unwrap(), utf8_value);
    }

    #[test]
    fn can_duplicate_key() {
        let key_name = "user/test/key";
        let mut key_dup;
        {
            let key = Key::new(key_name).unwrap();
            key_dup = Some(key.duplicate());
            // key is dropped here
        }
        assert_eq!(key_dup.unwrap().get_name(), key_name);
    }

    #[test]
    fn can_write_read_binary() {
        let mut key = Key::new("user/test/rust").unwrap();
        let binary_content: [u8; 7] = [25, 34, 0, 254, 1, 0, 7];
        key.set_binary(&binary_content);
        let read_content = key.get_binary().unwrap();
        assert_eq!(read_content, binary_content);
    }
    #[test]
    fn can_write_read_empty_binary() {
        let mut key = Key::new("user/test/binary").unwrap();
        let binary_content: [u8; 0] = [];
        key.set_binary(&binary_content);
        // set_binary does not set binary flag, size is 0
        // so get_binary returns error
        let err = key.get_binary().unwrap_err();
        assert_eq!(err, KeyError::TypeMismatch);
    }

    #[test]
    fn equality_is_exclusive() {
        let key = Key::new("user/test/exclusive").unwrap();
        let key2 = Key::new("dir/test/exclusive").unwrap();

        assert!(!(key != key));
        assert!(key == key);

        assert!(!(key == key2));
        assert!(key != key2);
    }

    #[test]
    fn equality_is_reflexive() {
        let key = Key::new("user/test/reflexive").unwrap();
        assert!(key == key);
    }

    #[test]
    fn equality_is_symmetric() {
        let key = Key::new("user/test/symmetric").unwrap();
        let key_dup = Key::new("user/test/symmetric").unwrap();

        assert!(key_dup == key);
        assert!(key == key_dup);
    }

    #[test]
    fn equality_is_transitive() {
        let key = Key::new("user/test/transitive").unwrap();
        let key2 = Key::new("user/test/transitive").unwrap();
        let key3 = Key::new("user/test/transitive").unwrap();

        assert!(key == key2);
        assert!(key2 == key3);
        assert!(key == key3);
    }

    #[test]
    fn keys_are_ordered() {
        let key = Key::new("user/test/a").unwrap();
        let key2 = Key::new("user/test/b").unwrap();
        let key3 = Key::new("user/test/c").unwrap();

        assert!(key != key2);
        assert!(key < key2);
        assert!(key2 > key);
        // Check for antisymmetry
        assert!(!(key > key2));
        assert!(!(key2 < key));

        // Check for transitivity
        assert!(key2 < key3);
        assert!(key < key3);
    }

    #[test]
    fn keys_are_ordered_with_metadata() {
        // TODO Add once it's possible to add metadata
        //Key * k1 = keyNew("user/a", KEY_OWNER, "markus", KEY_END);
        //Key * k2 = keyNew("user/a", KEY_OWNER, "max", KEY_END);
        // keyCmp(k1,k2) < 0
        // keyCmp(k2,k1) > 0
        assert!(5 + 2 == 7);
    }

    #[test]
    fn can_reference_count() {
        let mut key = Key::new("user/test/a").unwrap();
        assert_eq!(key.get_ref(), 0);
        key.inc_ref();
        assert_eq!(key.get_ref(), 1);
        key.dec_ref();
        assert_eq!(key.get_ref(), 0);
    }

}
<|endoftext|>


<commit_before>/// Character level parsers

use internal::{IResult, Needed};
use traits::{AsChar, InputIter, InputLength, Slice};
use std::ops::RangeFrom;
use traits::{need_more, AtEof};

/// matches one of the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(simple<char>, one_of!(&b"abc"[..]));
/// assert_eq!(simple(b"a123"), Ok((&b"123"[..], 'a')));
///
/// named!(a_or_b<&str, char>, one_of!("ab汉"));
/// assert_eq!(a_or_b("汉jiosfe"), Ok(("jiosfe", '汉')));
/// # }
/// ```
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, $inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches anything but the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(no_letter_a<char>, none_of!(&b"abc"[..]));
/// assert_eq!(no_letter_a(b"123"), Ok((&b"23"[..], '1')));
///
/// named!(err_on_single_quote<char>, none_of!(&b"'"[..]));
/// assert_eq!(err_on_single_quote(b"'jiosfe"), Err(Err::Error(error_position!(&b"'jiosfe"[..], ErrorKind::NoneOf))));
/// # }
/// ```
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, !$inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(match_letter_a<char>, char!('a'));
/// assert_eq!(match_letter_a(b"abc"), Ok((&b"bc"[..],'a')));
///
/// assert_eq!(match_letter_a(b"123cdef"), Err(Err::Error(error_position!(&b"123cdef"[..], ErrorKind::Char))));
/// # }
/// ```
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        let b = c.clone().as_char() == $c;
        (c, b)
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => {
          let e: $crate::ErrorKind<u32> = $crate::ErrorKind::Char;
          Err(Err::Error($crate::Context::Code($i, e)))
        },
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

named!(#[doc="Matches a newline character '\\n'"], pub newline<char>, char!('\n'));

named!(#[doc="Matches a tab character '\\t'"], pub tab<char>, char!('\t'));

/// matches one byte as a character. Note that the input type will
/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::anychar;
/// # fn main() {
/// assert_eq!(anychar("abc"), Ok(("bc",'a')));
/// # }
/// ```
pub fn anychar<T>(input: T) -> IResult<T, char>
where
  T: InputIter + InputLength + Slice<RangeFrom<usize>> + AtEof,
  <T as InputIter>::Item: AsChar,
{
  let mut it = input.iter_indices();
  match it.next() {
    None => need_more(input, Needed::Size(1)),
    Some((_, c)) => match it.next() {
      None => Ok((input.slice(input.input_len()..), c.as_char())),
      Some((idx, _)) => Ok((input.slice(idx..), c.as_char())),
    },
  }
}

#[cfg(test)]
mod tests {
  use internal::Err;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));

    let b = &b"cde"[..];
    assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));

    named!(utf8(&str) -> char,
      one_of!("+\u{FF0B}"));

    assert!(utf8("+").is_ok());
    assert!(utf8("\u{FF0B}").is_ok());
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));

    let b = &b"cde"[..];
    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &b"cde"[..];
    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char_str() {
    named!(f<&str, char>, char!('c'));

    let a = &"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &"cde"[..];
    assert_eq!(f(b), Ok((&"de"[..], 'c')));
  }

  #[test]
  fn anychar_str() {
    use super::anychar;
    assert_eq!(anychar("Ә"), Ok(("", 'Ә')));
  }
}
<commit_msg>avoid cloning the character when matching<commit_after>/// Character level parsers

use internal::{IResult, Needed};
use traits::{AsChar, InputIter, InputLength, Slice};
use std::ops::RangeFrom;
use traits::{need_more, AtEof};

/// matches one of the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(simple<char>, one_of!(&b"abc"[..]));
/// assert_eq!(simple(b"a123"), Ok((&b"123"[..], 'a')));
///
/// named!(a_or_b<&str, char>, one_of!("ab汉"));
/// assert_eq!(a_or_b("汉jiosfe"), Ok(("jiosfe", '汉')));
/// # }
/// ```
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, $inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches anything but the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(no_letter_a<char>, none_of!(&b"abc"[..]));
/// assert_eq!(no_letter_a(b"123"), Ok((&b"23"[..], '1')));
///
/// named!(err_on_single_quote<char>, none_of!(&b"'"[..]));
/// assert_eq!(err_on_single_quote(b"'jiosfe"), Err(Err::Error(error_position!(&b"'jiosfe"[..], ErrorKind::NoneOf))));
/// # }
/// ```
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, !$inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(match_letter_a<char>, char!('a'));
/// assert_eq!(match_letter_a(b"abc"), Ok((&b"bc"[..],'a')));
///
/// assert_eq!(match_letter_a(b"123cdef"), Err(Err::Error(error_position!(&b"123cdef"[..], ErrorKind::Char))));
/// # }
/// ```
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        let b = c.as_char() == $c;
        b
      }) {
        None        => $crate::need_more($i, Needed::Size(1)),
        Some(false) => {
          let e: $crate::ErrorKind<u32> = $crate::ErrorKind::Char;
          Err(Err::Error($crate::Context::Code($i, e)))
        },
        //the unwrap should be safe here
        Some(true)  => Ok(( $i.slice($c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

named!(#[doc="Matches a newline character '\\n'"], pub newline<char>, char!('\n'));

named!(#[doc="Matches a tab character '\\t'"], pub tab<char>, char!('\t'));

/// matches one byte as a character. Note that the input type will
/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::anychar;
/// # fn main() {
/// assert_eq!(anychar("abc"), Ok(("bc",'a')));
/// # }
/// ```
pub fn anychar<T>(input: T) -> IResult<T, char>
where
  T: InputIter + InputLength + Slice<RangeFrom<usize>> + AtEof,
  <T as InputIter>::Item: AsChar,
{
  let mut it = input.iter_indices();
  match it.next() {
    None => need_more(input, Needed::Size(1)),
    Some((_, c)) => match it.next() {
      None => Ok((input.slice(input.input_len()..), c.as_char())),
      Some((idx, _)) => Ok((input.slice(idx..), c.as_char())),
    },
  }
}

#[cfg(test)]
mod tests {
  use internal::Err;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));

    let b = &b"cde"[..];
    assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));

    named!(utf8(&str) -> char,
      one_of!("+\u{FF0B}"));

    assert!(utf8("+").is_ok());
    assert!(utf8("\u{FF0B}").is_ok());
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));

    let b = &b"cde"[..];
    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &b"cde"[..];
    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char_str() {
    named!(f<&str, char>, char!('c'));

    let a = &"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &"cde"[..];
    assert_eq!(f(b), Ok((&"de"[..], 'c')));
  }

  #[test]
  fn anychar_str() {
    use super::anychar;
    assert_eq!(anychar("Ә"), Ok(("", 'Ә')));
  }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::fmt;
use std::rc::{Rc, Weak};
use entity::{Vec3f64, Entity};

struct Address {
    x: u64,
    y: u64,
    z: u64,
}

struct Element {
    name: String,
}

pub enum ChunkOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>)
}

pub enum ChildOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub enum ParentOption {
    Local(Weak<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub struct LocalChunk {
    address: Address,
    center: Vec3f64,
    //children: [ChildOption; 8],
    //FIXME: remove these and uncomment above
    child0: ChildOption,
    child1: ChildOption,
    child2: ChildOption,
    child3: ChildOption,
    child4: ChildOption,
    child5: ChildOption,
    child6: ChildOption,
    child7: ChildOption,
    //END FIXME
    child_number: Option<u8>,
    entities: Vec<Rc<Entity>>,
    mass: f64,
    parent: ParentOption,
    scale: u8,
    structure: u64,
    summary: Rc<Element>,
}

pub struct RemoteChunk {
    connection: i32,
}

impl Address {
    fn from_string(address: String) -> Option<Address> {
        let mut xyz: (u64, u64, u64) = (1, 1, 1);
        let mut xyz_add: (u64, u64, u64);

        for (i, c) in address.chars().enumerate() {
            if i > 63 {
                break;
            }
            xyz_add =  match c.to_digit(8) {
                Some(0) => (0, 0, 0),
                Some(1) => (0, 0, 1),
                Some(2) => (0, 1, 0),
                Some(3) => (0, 1, 1),
                Some(4) => (1, 0, 0),
                Some(5) => (1, 0, 1),
                Some(6) => (1, 1, 0),
                Some(7) => (1, 1, 1),
                _ => return None,
            };
            xyz = (xyz.0 << 1, xyz.1 << 1, xyz.2 << 1);
            xyz = (xyz.0 + xyz_add.0, xyz.1 + xyz_add.1, xyz.2 + xyz_add.2);
        }
        Some(Address {x: xyz.0, y: xyz.1, z: xyz.2})
    }
}

impl ToString for Address {
    fn to_string(&self) -> String {
        String::from_str("")
    }
}

impl PartialEq for Address {
    fn eq(&self, other: &Self) -> bool {
        (((self.x == other.x) && (self.y == other.y)) && (self.z == other.z))
    }
}

impl fmt::Show for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address({}, {}, {})", self.x, self.y, self.z)
    }
}

pub trait Chunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption;
    fn tick(&self, time_delta: f64);
}

impl Chunk for LocalChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        let index = match (x, y, z) {
            (0, 0, 0) => Some(0),
            (0, 0, 1) => Some(1),
            (0, 1, 0) => Some(2),
            (0, 1, 1) => Some(3),
            (1, 0, 0) => Some(4),
            (1, 0, 1) => Some(5),
            (1, 1, 0) => Some(6),
            (1, 1, 1) => Some(7),
            _ => None,
        };

        if index == None {
            return ChildOption::None
        }

        match self.children[index] {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }
    }

    fn tick(&self, time_delta: f64) {
    }
}

impl Chunk for RemoteChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        ChildOption::None
    }
    fn tick (&self, time_delta: f64) {
    }
}

#[test]
fn test_address_from_string() {
    let known = Option::Some(Address {x: 0b11, y: 0b11, z: 0b11});
    let unknown = Address::from_string(String::from_str("7"));
    assert_eq!(known, unknown)
}
<commit_msg>Update mod.rs<commit_after>#![allow(dead_code)]
use std::fmt;
use std::rc::{Rc, Weak};
use entity::{Vec3f64, Entity};

struct Address {
    x: u64,
    y: u64,
    z: u64,
}

struct Element {
    name: String,
}

pub enum ChunkOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>)
}

pub enum ChildOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub enum ParentOption {
    Local(Weak<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub struct LocalChunk {
    address: Address,
    center: Vec3f64,
    //children: [ChildOption; 8],
    //FIXME: remove these and uncomment above
    child0: ChildOption,
    child1: ChildOption,
    child2: ChildOption,
    child3: ChildOption,
    child4: ChildOption,
    child5: ChildOption,
    child6: ChildOption,
    child7: ChildOption,
    //END FIXME
    child_number: Option<u8>,
    entities: Vec<Rc<Entity>>,
    mass: f64,
    parent: ParentOption,
    scale: u8,
    structure: u64,
    summary: Rc<Element>,
}

pub struct RemoteChunk {
    connection: i32,
}

impl Address {
    fn from_string(address: String) -> Option<Address> {
        let mut xyz: (u64, u64, u64) = (1, 1, 1);
        let mut xyz_add: (u64, u64, u64);

        for (i, c) in address.chars().enumerate() {
            if i > 63 {
                break;
            }
            xyz_add =  match c.to_digit(8) {
                Some(0) => (0, 0, 0),
                Some(1) => (0, 0, 1),
                Some(2) => (0, 1, 0),
                Some(3) => (0, 1, 1),
                Some(4) => (1, 0, 0),
                Some(5) => (1, 0, 1),
                Some(6) => (1, 1, 0),
                Some(7) => (1, 1, 1),
                _ => return None,
            };
            xyz = (xyz.0 << 1, xyz.1 << 1, xyz.2 << 1);
            xyz = (xyz.0 + xyz_add.0, xyz.1 + xyz_add.1, xyz.2 + xyz_add.2);
        }
        Some(Address {x: xyz.0, y: xyz.1, z: xyz.2})
    }
}

impl ToString for Address {
    fn to_string(&self) -> String {
        String::from_str("")
    }
}

impl PartialEq for Address {
    fn eq(&self, other: &Self) -> bool {
        (((self.x == other.x) && (self.y == other.y)) && (self.z == other.z))
    }
}

impl fmt::Show for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address({}, {}, {})", self.x, self.y, self.z)
    }
}

pub trait Chunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption;
    fn tick(&self, time_delta: f64);
}

impl Chunk for LocalChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        let index = match (x, y, z) {
            (0, 0, 0) => Some(0),
            (0, 0, 1) => Some(1),
            (0, 1, 0) => Some(2),
            (0, 1, 1) => Some(3),
            (1, 0, 0) => Some(4),
            (1, 0, 1) => Some(5),
            (1, 1, 0) => Some(6),
            (1, 1, 1) => Some(7),
            _ => None,
        };

        /* FIXME: remove
        if index == None {
            return ChildOption::None
        }

        match self.children[index] {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }*/
        //SLOP
        let child = match index {
            Some(0) => self.child0,
            Some(1) => self.child1,
            Some(2) => self.child2,
            Some(3) => self.child3,
            Some(4) => self.child4,
            Some(5) => self.child5,
            Some(6) => self.child6,
            Some(7) => self.child7,
            _ => return None
        };
        match child {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }
        //ENDSLOP
    }

    fn tick(&self, time_delta: f64) {
    }
}

impl Chunk for RemoteChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        ChildOption::None
    }
    fn tick (&self, time_delta: f64) {
    }
}

#[test]
fn test_address_from_string() {
    let known = Option::Some(Address {x: 0b11, y: 0b11, z: 0b11});
    let unknown = Address::from_string(String::from_str("7"));
    assert_eq!(known, unknown)
}
<|endoftext|>


<commit_before>use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Gcc,
        vec![
            // Tell GCC to avoid linker plugins, because we are not bundling
            // them with Windows installer, and Rust does its own LTO anyways.
            "-fno-use-linker-plugin".to_string(),
            // Always enable DEP (NX bit) when it is available
            "-Wl,--nxcompat".to_string(),
            // Do not use the standard system startup files or libraries when linking
            "-nostdlib".to_string(),
        ],
    );

    let mut late_link_args = LinkArgs::new();
    let mut late_link_args_dynamic = LinkArgs::new();
    let mut late_link_args_static = LinkArgs::new();
    late_link_args.insert(
        LinkerFlavor::Gcc,
        vec![
            "-lmingwex".to_string(),
            "-lmingw32".to_string(),
            "-lmsvcrt".to_string(),
            // mingw's msvcrt is a weird hybrid import library and static library.
            // And it seems that the linker fails to use import symbols from msvcrt
            // that are required from functions in msvcrt in certain cases. For example
            // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
            // Listing the library twice seems to fix that, and seems to also be done
            // by mingw's gcc (Though not sure if it's done on purpose, or by mistake).
            //
            // See https://github.com/rust-lang/rust/pull/47483
            "-lmsvcrt".to_string(),
            "-luser32".to_string(),
            "-lkernel32".to_string(),
        ],
    );
    late_link_args_dynamic.insert(
        LinkerFlavor::Gcc,
        vec![
            // If any of our crates are dynamically linked then we need to use
            // the shared libgcc_s-dw2-1.dll. This is required to support
            // unwinding across DLL boundaries.
            "-lgcc_s".to_string(),
            "-lgcc".to_string(),
            "-lkernel32".to_string(),
        ],
    );
    late_link_args_static.insert(
        LinkerFlavor::Gcc,
        vec![
            // If all of our crates are statically linked then we can get away
            // with statically linking the libgcc unwinding code. This allows
            // binaries to be redistributed without the libgcc_s-dw2-1.dll
            // dependency, but unfortunately break unwinding across DLL
            // boundaries when unwinding across FFI boundaries.
            "-lgcc".to_string(),
            "-lgcc_eh".to_string(),
            "-lpthread".to_string(),
            "-lkernel32".to_string(),
        ],
    );

    TargetOptions {
        // FIXME(#13846) this should be enabled for windows
        function_sections: false,
        linker: Some("gcc".to_string()),
        dynamic_linking: true,
        executables: true,
        dll_prefix: String::new(),
        dll_suffix: ".dll".to_string(),
        exe_suffix: ".exe".to_string(),
        staticlib_prefix: String::new(),
        staticlib_suffix: ".lib".to_string(),
        no_default_libraries: true,
        target_family: Some("windows".to_string()),
        is_like_windows: true,
        allows_weak_linkage: false,
        pre_link_args,
        pre_link_objects_exe: vec![
            "crt2.o".to_string(),    // mingw C runtime initialization for executables
            "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
        ],
        pre_link_objects_dll: vec![
            "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
            "rsbegin.o".to_string(),
        ],
        late_link_args,
        late_link_args_dynamic,
        late_link_args_static,
        post_link_objects: vec!["rsend.o".to_string()],
        abi_return_struct_as_int: true,
        emit_debug_gdb_scripts: false,
        requires_uwtable: true,

        ..Default::default()
    }
}
<commit_msg>Add missing -lmsvcrt on mingw after -lpthread<commit_after>use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(
        LinkerFlavor::Gcc,
        vec![
            // Tell GCC to avoid linker plugins, because we are not bundling
            // them with Windows installer, and Rust does its own LTO anyways.
            "-fno-use-linker-plugin".to_string(),
            // Always enable DEP (NX bit) when it is available
            "-Wl,--nxcompat".to_string(),
            // Do not use the standard system startup files or libraries when linking
            "-nostdlib".to_string(),
        ],
    );

    let mut late_link_args = LinkArgs::new();
    let mut late_link_args_dynamic = LinkArgs::new();
    let mut late_link_args_static = LinkArgs::new();
    late_link_args.insert(
        LinkerFlavor::Gcc,
        vec![
            "-lmingwex".to_string(),
            "-lmingw32".to_string(),
            "-lmsvcrt".to_string(),
            // mingw's msvcrt is a weird hybrid import library and static library.
            // And it seems that the linker fails to use import symbols from msvcrt
            // that are required from functions in msvcrt in certain cases. For example
            // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
            // Listing the library twice seems to fix that, and seems to also be done
            // by mingw's gcc (Though not sure if it's done on purpose, or by mistake).
            //
            // See https://github.com/rust-lang/rust/pull/47483
            "-lmsvcrt".to_string(),
            "-luser32".to_string(),
            "-lkernel32".to_string(),
        ],
    );
    late_link_args_dynamic.insert(
        LinkerFlavor::Gcc,
        vec![
            // If any of our crates are dynamically linked then we need to use
            // the shared libgcc_s-dw2-1.dll. This is required to support
            // unwinding across DLL boundaries.
            "-lgcc_s".to_string(),
            "-lgcc".to_string(),
            "-lkernel32".to_string(),
        ],
    );
    late_link_args_static.insert(
        LinkerFlavor::Gcc,
        vec![
            // If all of our crates are statically linked then we can get away
            // with statically linking the libgcc unwinding code. This allows
            // binaries to be redistributed without the libgcc_s-dw2-1.dll
            // dependency, but unfortunately break unwinding across DLL
            // boundaries when unwinding across FFI boundaries.
            "-lgcc".to_string(),
            "-lgcc_eh".to_string(),
            "-lpthread".to_string(),
            // libpthread depends on libmsvcrt, so we need to link it *again*.
            "-lmsvcrt".to_string(),
            "-lkernel32".to_string(),
        ],
    );

    TargetOptions {
        // FIXME(#13846) this should be enabled for windows
        function_sections: false,
        linker: Some("gcc".to_string()),
        dynamic_linking: true,
        executables: true,
        dll_prefix: String::new(),
        dll_suffix: ".dll".to_string(),
        exe_suffix: ".exe".to_string(),
        staticlib_prefix: String::new(),
        staticlib_suffix: ".lib".to_string(),
        no_default_libraries: true,
        target_family: Some("windows".to_string()),
        is_like_windows: true,
        allows_weak_linkage: false,
        pre_link_args,
        pre_link_objects_exe: vec![
            "crt2.o".to_string(),    // mingw C runtime initialization for executables
            "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
        ],
        pre_link_objects_dll: vec![
            "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
            "rsbegin.o".to_string(),
        ],
        late_link_args,
        late_link_args_dynamic,
        late_link_args_static,
        post_link_objects: vec!["rsend.o".to_string()],
        abi_return_struct_as_int: true,
        emit_debug_gdb_scripts: false,
        requires_uwtable: true,

        ..Default::default()
    }
}
<|endoftext|>