<commit_before>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// This example shows how to play a wav file using the cpal crate.

extern crate hound;
extern crate cpal;

use std::env;
use std::fs;
use std::io;

fn main() {
    // Make a WavReader that reads the file provided as program argument.
    let fname = env::args().nth(1).unwrap();
    let input = fs::File::open(&fname).unwrap();
    let buf_reader = io::BufReader::new(input);
    let mut reader = hound::WavReader::new(buf_reader).unwrap();
    let spec = reader.spec().clone(); // TODO: by value might be better in this case.

    // A voice in cpal is used for playback.
    let mut voice = cpal::Voice::new();

    let mut append_data = |voice: &mut cpal::Voice| {
        let mut buffer: cpal::Buffer<u16> =
            voice.append_data(spec.channels,
                              cpal::SamplesRate(spec.sample_rate),
                              1024); // TODO: Do I know the number of samples?
        // Fill the cpal buffer with data from the wav file.
        for (dest, src) in buffer.iter_mut().zip(reader.samples::<i16>()) {
            // TODO: Without the cast, there are a lot of artefacts. This
            // suggests that samples are actually unsigned. We can find out by
            // computing the mean: if it is around 0i16, then samples are signed.
            // If it is around 32000u16, then samples are unsigned.
            *dest = src.unwrap() as u16;
        }
        // TODO: check when reader is done, then exit.
    };

    // The voice must have some data before playing for the first time.
    append_data(&mut voice);
    voice.play();

    // Then we keep providing new data until the end of the audio.
    loop {
        append_data(&mut voice); // TODO exit when done
    }
}
<commit_msg>handle errors better in cpal example<commit_after>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// This example shows how to play a wav file using the cpal crate.

extern crate hound;
extern crate cpal;

use std::env;
use std::fs;
use std::io;

fn main() {
    // Make a WavReader that reads the file provided as program argument.
    let fname = env::args().nth(1).expect("no file given");
    let input = fs::File::open(&fname).ok().expect("invalid file");
    let buf_reader = io::BufReader::new(input);
    let mut reader = hound::WavReader::new(buf_reader).unwrap();
    let spec = reader.spec().clone(); // TODO: by value might be better in this case.

    // A voice in cpal is used for playback.
    let mut voice = cpal::Voice::new();

    let mut append_data = |voice: &mut cpal::Voice| {
        let mut buffer: cpal::Buffer<u16> =
            voice.append_data(spec.channels,
                              cpal::SamplesRate(spec.sample_rate),
                              1024); // TODO: Do I know the number of samples?
        // Fill the cpal buffer with data from the wav file.
        for (dest, src) in buffer.iter_mut().zip(reader.samples::<i16>()) {
            // TODO: Without the cast, there are a lot of artefacts. This
            // suggests that samples are actually unsigned. We can find out by
            // computing the mean: if it is around 0i16, then samples are signed.
            // If it is around 32000u16, then samples are unsigned.
            *dest = src.unwrap() as u16;
        }
        // TODO: check when reader is done, then exit.
    };

    // The voice must have some data before playing for the first time.
    append_data(&mut voice);
    voice.play();

    // Then we keep providing new data until the end of the audio.
    loop {
        append_data(&mut voice); // TODO exit when done
    }
}
<|endoftext|>


<commit_before>extern crate xmpp;
use xmpp::XmppStream;
use xmpp::stanzas::Stanza;

fn main() {
    let mut stream = XmppStream::new("alice", "localhost", "test");
    match stream.connect() {
        Ok(_) => (),
        Err(e) => {
            println!("{}", e);
            return;
        }
    }
    loop {
        let response = match stream.handle() {
            xmpp::Event::StreamClosed => break,
            xmpp::Event::Message(msg) => {
                let mut response = msg.clone();
                let to = response.from().map(|x| x.into());
                response.set_to(to);
                response.set_from(None);
                response
            }
            _ => continue
        };
        stream.send(response);
    }
}
<commit_msg>examples/echo: send Presence after Bound<commit_after>extern crate xmpp;
use xmpp::XmppStream;
use xmpp::stanzas::{Stanza, Presence, PresenceType};

fn main() {
    let mut stream = XmppStream::new("alice", "localhost", "test");
    match stream.connect() {
        Ok(_) => (),
        Err(e) => {
            println!("{}", e);
            return;
        }
    }
    loop {
        let (opt_response, send_presence) = match stream.handle() {
            xmpp::Event::StreamClosed => break,
            xmpp::Event::Message(msg) => {
                let mut response = msg.clone();
                let to = response.from().map(|x| x.into());
                response.set_to(to);
                response.set_from(None);
                (Some(response), false)
            }
            xmpp::Event::Bound => {
                (None, true)
            }
            _ => continue
        };
        match opt_response {
            Some(response) => stream.send(response).unwrap(),
            None => ()
        }
        if send_presence {
            stream.send(Presence::new(PresenceType::Available, "".to_owned())).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>//! The `Parse` trait for CSS properties, and utilities for parsers.

use cssparser::{Parser, ParserInput, Token};
use markup5ever::QualName;

use std::str;

use crate::error::{NodeError, ValueErrorKind};

/// Trait to parse values using `cssparser::Parser`.
pub trait Parse: Sized {
    /// Parses a value out of the `parser`.
    ///
    /// All value types should implement this for composability.
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind>;

    /// Convenience function to parse a value out of a `&str`.
    ///
    /// This is useful mostly for tests which want to avoid creating a
    /// `cssparser::Parser` by hand.
    fn parse_str(s: &str) -> Result<Self, ValueErrorKind> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

/// Extra utility methods for `cssparser::Parser`.
pub trait CssParserExt {
    /// Avoid infinities.
    fn expect_finite_number(&mut self) -> Result<f32, ValueErrorKind>;

    /// Consumes a comma if it exists, or does nothing.
    fn optional_comma(&mut self);
}

impl<'i, 't> CssParserExt for Parser<'i, 't> {
    fn expect_finite_number(&mut self) -> Result<f32, ValueErrorKind> {
        finite_f32(self.expect_number()?)
    }

    fn optional_comma(&mut self) {
        let _ = self.try_parse(|p| p.expect_comma());
    }
}

pub fn finite_f32(n: f32) -> Result<f32, ValueErrorKind> {
    if n.is_finite() {
        Ok(n)
    } else {
        Err(ValueErrorKind::Value("expected finite number".to_string()))
    }
}

pub trait ParseValue<T: Parse> {
    /// Parses a `value` string into a type `T`.
    fn parse(&self, value: &str) -> Result<T, NodeError>;

    /// Parses a `value` string into a type `T` with an optional validation function.
    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError>;
}

impl<T: Parse> ParseValue<T> for QualName {
    fn parse(&self, value: &str) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser).map_err(|e| NodeError::new(self.clone(), e))
    }

    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser)
            .and_then(validate)
            .map_err(|e| NodeError::new(self.clone(), e))
    }
}

impl Parse for f64 {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<f64, ValueErrorKind> {
        Ok(f64::from(parser.expect_finite_number().map_err(|_| {
            ValueErrorKind::parse_error("expected number")
        })?))
    }
}

// number
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeNumber
pub fn number(s: &str) -> Result<f64, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(f64::from(parser.expect_finite_number()?))
}

// number-optional-number
//
// https://www.w3.org/TR/SVG/types.html#DataTypeNumberOptionalNumber

pub fn number_optional_number(s: &str) -> Result<(f64, f64), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = f64::from(parser.expect_finite_number()?);

    if !parser.is_exhausted() {
        let state = parser.state();

        match *parser.next()? {
            Token::Comma => {}
            _ => parser.reset(&state),
        };

        let y = f64::from(parser.expect_finite_number()?);

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

// integer
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeInteger
pub fn integer(s: &str) -> Result<i32, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(parser.expect_integer()?)
}

// integer-optional-integer
//
// Like number-optional-number but with integers.
pub fn integer_optional_integer(s: &str) -> Result<(i32, i32), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = parser.expect_integer()?;

    if !parser.is_exhausted() {
        let state = parser.state();

        match *parser.next()? {
            Token::Comma => {}
            _ => parser.reset(&state),
        };

        let y = parser.expect_integer()?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

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

    #[test]
    fn parses_number_optional_number() {
        assert_eq!(number_optional_number("1, 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1"), Ok((1.0, 1.0)));

        assert_eq!(number_optional_number("-1, -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1 -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1"), Ok((-1.0, -1.0)));
    }

    #[test]
    fn invalid_number_optional_number() {
        assert!(number_optional_number("").is_err());
        assert!(number_optional_number("1x").is_err());
        assert!(number_optional_number("x1").is_err());
        assert!(number_optional_number("1 x").is_err());
        assert!(number_optional_number("1 , x").is_err());
        assert!(number_optional_number("1 , 2x").is_err());
        assert!(number_optional_number("1 2 x").is_err());
    }

    #[test]
    fn parses_integer() {
        assert_eq!(integer("1"), Ok(1));
        assert_eq!(integer("-1"), Ok(-1));
    }

    #[test]
    fn invalid_integer() {
        assert!(integer("").is_err());
        assert!(integer("1x").is_err());
        assert!(integer("1.5").is_err());
    }

    #[test]
    fn parses_integer_optional_integer() {
        assert_eq!(integer_optional_integer("1, 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1"), Ok((1, 1)));

        assert_eq!(integer_optional_integer("-1, -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1 -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1"), Ok((-1, -1)));
    }

    #[test]
    fn invalid_integer_optional_integer() {
        assert!(integer_optional_integer("").is_err());
        assert!(integer_optional_integer("1x").is_err());
        assert!(integer_optional_integer("x1").is_err());
        assert!(integer_optional_integer("1 x").is_err());
        assert!(integer_optional_integer("1 , x").is_err());
        assert!(integer_optional_integer("1 , 2x").is_err());
        assert!(integer_optional_integer("1 2 x").is_err());
        assert!(integer_optional_integer("1.5").is_err());
        assert!(integer_optional_integer("1 2.5").is_err());
        assert!(integer_optional_integer("1, 2.5").is_err());
    }
}
<commit_msg>parsers.rs: Don't create a NodeError directly<commit_after>//! The `Parse` trait for CSS properties, and utilities for parsers.

use cssparser::{Parser, ParserInput, Token};
use markup5ever::QualName;

use std::str;

use crate::error::*;

/// Trait to parse values using `cssparser::Parser`.
pub trait Parse: Sized {
    /// Parses a value out of the `parser`.
    ///
    /// All value types should implement this for composability.
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind>;

    /// Convenience function to parse a value out of a `&str`.
    ///
    /// This is useful mostly for tests which want to avoid creating a
    /// `cssparser::Parser` by hand.
    fn parse_str(s: &str) -> Result<Self, ValueErrorKind> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

/// Extra utility methods for `cssparser::Parser`.
pub trait CssParserExt {
    /// Avoid infinities.
    fn expect_finite_number(&mut self) -> Result<f32, ValueErrorKind>;

    /// Consumes a comma if it exists, or does nothing.
    fn optional_comma(&mut self);
}

impl<'i, 't> CssParserExt for Parser<'i, 't> {
    fn expect_finite_number(&mut self) -> Result<f32, ValueErrorKind> {
        finite_f32(self.expect_number()?)
    }

    fn optional_comma(&mut self) {
        let _ = self.try_parse(|p| p.expect_comma());
    }
}

pub fn finite_f32(n: f32) -> Result<f32, ValueErrorKind> {
    if n.is_finite() {
        Ok(n)
    } else {
        Err(ValueErrorKind::Value("expected finite number".to_string()))
    }
}

pub trait ParseValue<T: Parse> {
    /// Parses a `value` string into a type `T`.
    fn parse(&self, value: &str) -> Result<T, NodeError>;

    /// Parses a `value` string into a type `T` with an optional validation function.
    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError>;
}

impl<T: Parse> ParseValue<T> for QualName {
    fn parse(&self, value: &str) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser).attribute(self.clone())
    }

    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser).and_then(validate).attribute(self.clone())
    }
}

impl Parse for f64 {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<f64, ValueErrorKind> {
        Ok(f64::from(parser.expect_finite_number().map_err(|_| {
            ValueErrorKind::parse_error("expected number")
        })?))
    }
}

// number
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeNumber
pub fn number(s: &str) -> Result<f64, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(f64::from(parser.expect_finite_number()?))
}

// number-optional-number
//
// https://www.w3.org/TR/SVG/types.html#DataTypeNumberOptionalNumber

pub fn number_optional_number(s: &str) -> Result<(f64, f64), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = f64::from(parser.expect_finite_number()?);

    if !parser.is_exhausted() {
        let state = parser.state();

        match *parser.next()? {
            Token::Comma => {}
            _ => parser.reset(&state),
        };

        let y = f64::from(parser.expect_finite_number()?);

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

// integer
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeInteger
pub fn integer(s: &str) -> Result<i32, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(parser.expect_integer()?)
}

// integer-optional-integer
//
// Like number-optional-number but with integers.
pub fn integer_optional_integer(s: &str) -> Result<(i32, i32), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = parser.expect_integer()?;

    if !parser.is_exhausted() {
        let state = parser.state();

        match *parser.next()? {
            Token::Comma => {}
            _ => parser.reset(&state),
        };

        let y = parser.expect_integer()?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

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

    #[test]
    fn parses_number_optional_number() {
        assert_eq!(number_optional_number("1, 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1"), Ok((1.0, 1.0)));

        assert_eq!(number_optional_number("-1, -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1 -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1"), Ok((-1.0, -1.0)));
    }

    #[test]
    fn invalid_number_optional_number() {
        assert!(number_optional_number("").is_err());
        assert!(number_optional_number("1x").is_err());
        assert!(number_optional_number("x1").is_err());
        assert!(number_optional_number("1 x").is_err());
        assert!(number_optional_number("1 , x").is_err());
        assert!(number_optional_number("1 , 2x").is_err());
        assert!(number_optional_number("1 2 x").is_err());
    }

    #[test]
    fn parses_integer() {
        assert_eq!(integer("1"), Ok(1));
        assert_eq!(integer("-1"), Ok(-1));
    }

    #[test]
    fn invalid_integer() {
        assert!(integer("").is_err());
        assert!(integer("1x").is_err());
        assert!(integer("1.5").is_err());
    }

    #[test]
    fn parses_integer_optional_integer() {
        assert_eq!(integer_optional_integer("1, 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1"), Ok((1, 1)));

        assert_eq!(integer_optional_integer("-1, -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1 -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1"), Ok((-1, -1)));
    }

    #[test]
    fn invalid_integer_optional_integer() {
        assert!(integer_optional_integer("").is_err());
        assert!(integer_optional_integer("1x").is_err());
        assert!(integer_optional_integer("x1").is_err());
        assert!(integer_optional_integer("1 x").is_err());
        assert!(integer_optional_integer("1 , x").is_err());
        assert!(integer_optional_integer("1 , 2x").is_err());
        assert!(integer_optional_integer("1 2 x").is_err());
        assert!(integer_optional_integer("1.5").is_err());
        assert!(integer_optional_integer("1 2.5").is_err());
        assert!(integer_optional_integer("1, 2.5").is_err());
    }
}
<|endoftext|>


<commit_before>//#![feature(custom_derive)]

fn main() {
    println!("Hello, world!");
    let x = 5;
    let y = 8;
    let z = &y;
    if *z == y {
        println!("{:p} {} {}",z,*z, z);
    }

    let mut i: i32 = 1;
    //    foo(&mut i);//error: cannot borrow immutable borrowed content `*z` as mutable
    let z=&mut i;
    foo(z);//error: cannot borrow immutable borrowed content `*z` as mutable
    println!("{} {}",*z,z);

    //reference:
    let x = 5;
    let y = &x;

    println!("{}", *y);
    println!("{:p}", y);
    println!("{}", y);//because println! will automatically dereference it for us.

    let x = 5;
    let y = &x;
    println!("{}", succ(y));
    println!("{}", succ(&x));
    println!("{}", x);//unchanged

    let mut x = 5;
    let y = &mut x;

    let x = 5;
    let y = &x;
    let z = &x;

    let mut x = 5;
    let y = &mut x;
    //    let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time

    //boxes:
    let x = Box::new(5);//Boxes are appropriate to use in two situations: Recursive data structures, and occasionally, when returning data.
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));

    //recursive data structure
    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
    println!("{:?}", list);

    let x = &mut 5;
    if *x < 10 {
        let y = &x; // uhm https://github.com/rust-lang/rust/issues/21575
        println!("Oh no: {} {:p}", y,y);
        println!("Oh no: {} {:p}", x,x);
        //*y=&mut 6;
    }
    println!("Oh no: {} {:p}", x,x);
    *x -= 1;
    println!("Oh no: {} {:p}", x,x);

    //src: https://doc.rust-lang.org/nightly/book/functions.html#function-pointers
    //function pointers
    fn plus_one(i: i32) -> i32 {
            i + 1
    }
    // without type inference
    let f: fn(i32) -> i32 = plus_one;
    println!("{}",f(10));

    // with type inference
    let f = plus_one;
    println!("{}",f(10));
}//main //Box::new freed here

#[derive(Debug)]
enum List<T> {
    Cons(T, Box<List<T>>),
    //The reference to another List inside of the Cons enum variant must be a box, because we don't
    //know the length of the list. Because we don't know the length, we don't know the size, and
    //therefore, we need to heap allocate our list.
    //Working with recursive or other unknown-sized data structures is the primary use-case for boxes.
    Nil,
}

fn foo(x: &mut i32) {
    *x = 5
}

fn succ(x: &i32) -> i32 { *x + 1 }

fn realsucc(x: i32) -> i32 { x + 1 }

<commit_msg>question arised<commit_after>//#![feature(custom_derive)]

fn main() {
    println!("Hello, world!");
    let x = 5;
    let y = 8;
    let z = &y;
    if *z == y {
        println!("{:p} {} {}",z,*z, z);
    }

    let mut i: i32 = 1;
    //    foo(&mut i);//error: cannot borrow immutable borrowed content `*z` as mutable
    let z=&mut i;
    foo(z);//error: cannot borrow immutable borrowed content `*z` as mutable
    println!("{} {}",*z,z);

    //reference:
    let x = 5;
    let y = &x;

    println!("{}", *y);
    println!("{:p}", y);
    println!("{}", y);//because println! will automatically dereference it for us.

    let x = 5;
    let y = &x;
    println!("{}", succ(y));
    println!("{}", succ(&x));
    println!("{}", x);//unchanged

    let mut x = 5;
    let y = &mut x;

    let x = 5;
    let y = &x;
    let z = &x;

    let mut x = 5;
    let y = &mut x;
    //    let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time

    //boxes:
    let mut x = Box::new(5);//Boxes are appropriate to use in two situations: Recursive data structures, and occasionally, when returning data.
    println!("mooooooooooo {}", succ(&*x));
    println!("{}", succ(&*x));
    println!("{}", succ(&*x));
    println!("{}", succ(&x));
    println!("{:?}", *x);
    *x=4; // TODO: find out what happened to '5' if 5 were an object that could be freed, is it freed now? or later? or never? src: https://youtu.be/-dxqbhLIgdM?t=24m48s
    println!("{:?}", *x);

    //recursive data structure
    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
    println!("{:?}", list);

    let x = &mut 5;
    if *x < 10 {
        let y = &x; // uhm https://github.com/rust-lang/rust/issues/21575
        println!("Oh no: {} {:p}", y,y);
        println!("Oh no: {} {:p}", x,x);
        //*y=&mut 6;
    }
    println!("Oh no: {} {:p}", x,x);
    *x -= 1;
    println!("Oh no: {} {:p}", x,x);

    //src: https://doc.rust-lang.org/nightly/book/functions.html#function-pointers
    //function pointers
    fn plus_one(i: i32) -> i32 {
            i + 1
    }
    // without type inference
    let f: fn(i32) -> i32 = plus_one;
    println!("{}",f(10));

    // with type inference
    let f = plus_one;
    println!("{}",f(10));
}//main //Box::new freed here

#[derive(Debug)]
enum List<T> {
    Cons(T, Box<List<T>>),
    //The reference to another List inside of the Cons enum variant must be a box, because we don't
    //know the length of the list. Because we don't know the length, we don't know the size, and
    //therefore, we need to heap allocate our list.
    //Working with recursive or other unknown-sized data structures is the primary use-case for boxes.
    Nil,
}

fn foo(x: &mut i32) {
    *x = 5
}

fn succ(x: &i32) -> i32 { *x + 1 }

fn realsucc(x: i32) -> i32 { x + 1 }

<|endoftext|>


<commit_before>use once_cell::sync::OnceCell;
use std::sync::RwLock;
use serde_json;
use serde_json::json;

struct ConfigData {
    def:  serde_json::Value,
    main: serde_json::Value,
}

// default = empty Object (map)
impl Default for ConfigData {
    fn default() -> Self {
        Self { def: json!({}), main: json!({}) }
    }
}

static CONFIG: OnceCell<RwLock<ConfigData>> = OnceCell::new();

/// 設定データを json 文字列からロードして設定データシステムを初期化する。
pub fn init_and_load(def_json: &str, main_json: &str) -> Result<(), String>
{
    // lazy inialize + wlock
    let mut config = CONFIG
        .get_or_init(|| RwLock::new(Default::default()))
        .write()
        .unwrap();

    config.def = match serde_json::from_str(def_json) {
        Ok(json) => json,
        Err(e) => return Err(format!("{}", e)),
    };
    config.main = match serde_json::from_str(main_json) {
        Ok(json) => json,
        Err(e) => return Err(format!("{}", e)),
    };

    Ok(())
}
<commit_msg>key 配列で json tree を検索する<commit_after>use once_cell::sync::OnceCell;
use std::sync::RwLock;
use serde_json;
use serde_json::json;

struct ConfigData {
    def:  serde_json::Value,
    main: serde_json::Value,
}

// default = empty Object (map)
impl Default for ConfigData {
    fn default() -> Self {
        Self { def: json!({}), main: json!({}) }
    }
}

static CONFIG: OnceCell<RwLock<ConfigData>> = OnceCell::new();

/// 設定データを json 文字列からロードして設定データシステムを初期化する。
pub fn init_and_load(def_json: &str, main_json: &str) -> Result<(), String>
{
    // lazy inialize + wlock
    let mut config = CONFIG
        .get_or_init(|| RwLock::new(Default::default()))
        .write()
        .unwrap();

    config.def = match serde_json::from_str(def_json) {
        Ok(json) => json,
        Err(e) => return Err(format!("{}", e)),
    };
    config.main = match serde_json::from_str(main_json) {
        Ok(json) => json,
        Err(e) => return Err(format!("{}", e)),
    };

    Ok(())
}

/// Object tree を keys: 文字列の配列 (スライス) で検索する。
/// 見つからなかった場合、および
/// 数値, 真偽値, 文字列, 配列 以外が見つかった場合は null を返す。
/// 結果はコピーして返す。
fn search(root: &serde_json::Value, keys: &[&str]) -> serde_json::Value {
    let null_value = serde_json::Value::Null;

    let mut value = root;
    for key in keys.iter() {
        value = match value.as_object() {
            Some(map) => map.get(*key).unwrap_or(&null_value),
            None => &null_value,
        };
    }

    if value.is_number() || value.is_boolean() || value.is_string() || value.is_array() {
        value.clone()
    }
    else {
        serde_json::Value::Null
    }
}

/// main -> def の順番で検索する。
fn search_all(keys: &[&str]) -> serde_json::Value {
    // rlock
    let config = CONFIG
        .get().unwrap()
        .read().unwrap();

    let value = search(&config.main, keys);
    if !value.is_null() {
        value
    }
    else {
        search(&config.def, keys)
    }
}

/// 文字列設定データを取得する。
/// 見つからない場合や文字列でない場合は None を返す。
pub fn get_string(keys: &[&str]) -> Option<String>
{
    search_all(keys).as_str().map(|s| s.into())
}

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

    #[test]
    fn basic() {
        let main = r#"{"a": {"b": {"c": "main"}}}"#;
        let def = r#"{"a": {"b": {"d": "default"}}}"#;

        let result = init_and_load(def, main);
        assert!(result.is_ok());

        let v = get_string(&["a", "b", "c"]);
        assert!(v.unwrap_or_default() == "main");
        let v = get_string(&["a", "b", "C"]);
        assert!(v.is_none());
        let v = get_string(&["a", "b", "d"]);
        assert!(v.unwrap_or_default() == "default");
        let v = get_string(&["a", "b", "D"]);
        assert!(v.is_none());
    }
}
<|endoftext|>


<commit_before>//! A presence event is represented by a struct with a set content field.
//!
//! The only content valid for this event is `PresenceEventContent.

use js_int::UInt;
use ruma_events_macros::{Event, EventContent};
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};

/// Presence event.
#[derive(Clone, Debug, Event)]
pub struct PresenceEvent {
    /// Data specific to the event type.
    pub content: PresenceEventContent,

    /// Contains the fully-qualified ID of the user who sent this event.
    pub sender: UserId,
}

/// Informs the room of members presence.
///
/// This is the only event content a `PresenceEvent` can contain as it's
/// `content` field.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.presence")]
pub struct PresenceEventContent {
    /// The current avatar URL for this user.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_url: Option<String>,

    /// Whether or not the user is currently active.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currently_active: Option<bool>,

    /// The current display name for this user.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub displayname: Option<String>,

    /// The last time since this user performed some action, in milliseconds.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub last_active_ago: Option<UInt>,

    /// The presence state for this user.
    pub presence: PresenceState,

    /// An optional description to accompany the presence.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status_msg: Option<String>,
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use js_int::uint;
    use matches::assert_matches;
    use ruma_identifiers::UserId;
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{PresenceEvent, PresenceEventContent, PresenceState};

    #[test]
    fn serialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".into()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(uint!(2_478_593)),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".into()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json = json!({
            "content": {
                "avatar_url": "mxc://localhost:wefuiwegh8742w",
                "currently_active": false,
                "last_active_ago": 2_478_593,
                "presence": "online",
                "status_msg": "Making cupcakes"
            },
            "sender": "@example:localhost",
            "type": "m.presence"
        });

        assert_eq!(to_json_value(&event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let json = json!({
            "content": {
                "avatar_url": "mxc://localhost:wefuiwegh8742w",
                "currently_active": false,
                "last_active_ago": 2_478_593,
                "presence": "online",
                "status_msg": "Making cupcakes"
            },
            "sender": "@example:localhost",
            "type": "m.presence"
        });

        assert_matches!(
            from_json_value::<PresenceEvent>(json).unwrap(),
            PresenceEvent {
                content: PresenceEventContent {
                    avatar_url: Some(avatar_url),
                    currently_active: Some(false),
                    displayname: None,
                    last_active_ago: Some(last_active_ago),
                    presence: PresenceState::Online,
                    status_msg: Some(status_msg),
                },
                sender,
            } if avatar_url == "mxc://localhost:wefuiwegh8742w"
                && status_msg == "Making cupcakes"
                && sender == "@example:localhost"
                && last_active_ago == uint!(2_478_593)
        );
    }
}
<commit_msg>fixup<commit_after>//! A presence event is represented by a struct with a set content field.
//!
//! The only content valid for this event is `PresenceEventContent.

use js_int::UInt;
use ruma_common::presence::PresenceState;
use ruma_events_macros::{Event, EventContent};
use ruma_identifiers::UserId;
use serde::{Deserialize, Serialize};

/// Presence event.
#[derive(Clone, Debug, Event)]
pub struct PresenceEvent {
    /// Data specific to the event type.
    pub content: PresenceEventContent,

    /// Contains the fully-qualified ID of the user who sent this event.
    pub sender: UserId,
}

/// Informs the room of members presence.
///
/// This is the only event content a `PresenceEvent` can contain as it's
/// `content` field.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.presence")]
pub struct PresenceEventContent {
    /// The current avatar URL for this user.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_url: Option<String>,

    /// Whether or not the user is currently active.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub currently_active: Option<bool>,

    /// The current display name for this user.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub displayname: Option<String>,

    /// The last time since this user performed some action, in milliseconds.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub last_active_ago: Option<UInt>,

    /// The presence state for this user.
    pub presence: PresenceState,

    /// An optional description to accompany the presence.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status_msg: Option<String>,
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use js_int::uint;
    use matches::assert_matches;
    use ruma_common::presence::PresenceState;
    use ruma_identifiers::UserId;
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{PresenceEvent, PresenceEventContent};

    #[test]
    fn serialization() {
        let event = PresenceEvent {
            content: PresenceEventContent {
                avatar_url: Some("mxc://localhost:wefuiwegh8742w".into()),
                currently_active: Some(false),
                displayname: None,
                last_active_ago: Some(uint!(2_478_593)),
                presence: PresenceState::Online,
                status_msg: Some("Making cupcakes".into()),
            },
            sender: UserId::try_from("@example:localhost").unwrap(),
        };

        let json = json!({
            "content": {
                "avatar_url": "mxc://localhost:wefuiwegh8742w",
                "currently_active": false,
                "last_active_ago": 2_478_593,
                "presence": "online",
                "status_msg": "Making cupcakes"
            },
            "sender": "@example:localhost",
            "type": "m.presence"
        });

        assert_eq!(to_json_value(&event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let json = json!({
            "content": {
                "avatar_url": "mxc://localhost:wefuiwegh8742w",
                "currently_active": false,
                "last_active_ago": 2_478_593,
                "presence": "online",
                "status_msg": "Making cupcakes"
            },
            "sender": "@example:localhost",
            "type": "m.presence"
        });

        assert_matches!(
            from_json_value::<PresenceEvent>(json).unwrap(),
            PresenceEvent {
                content: PresenceEventContent {
                    avatar_url: Some(avatar_url),
                    currently_active: Some(false),
                    displayname: None,
                    last_active_ago: Some(last_active_ago),
                    presence: PresenceState::Online,
                    status_msg: Some(status_msg),
                },
                sender,
            } if avatar_url == "mxc://localhost:wefuiwegh8742w"
                && status_msg == "Making cupcakes"
                && sender == "@example:localhost"
                && last_active_ago == uint!(2_478_593)
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;

use syn::{
    parse_quote, punctuated::Punctuated, GenericArgument, PathArguments, PathSegment, Type,
    TypePath, TypePtr, TypeReference,
};

use crate::{
    conversion::bridge_converter::ConvertError,
    known_types::{is_known_type, known_type_substitute_path, should_dereference_in_cpp},
    types::{Namespace, TypeName},
};

use super::typedef_analyzer::{analyze_typedef_target, TypedefTarget};

/// Results of some type conversion, annotated with a list of every type encountered.
pub(crate) struct Annotated<T> {
    pub(crate) ty: T,
    pub(crate) types_encountered: Vec<TypeName>,
}

impl<T> Annotated<T> {
    fn new(ty: T, types_encountered: Vec<TypeName>) -> Self {
        Self {
            ty,
            types_encountered,
        }
    }

    fn map<T2, F: FnOnce(T) -> T2>(self, fun: F) -> Annotated<T2> {
        Annotated {
            ty: fun(self.ty),
            types_encountered: self.types_encountered,
        }
    }
}

pub(crate) struct TypeConverter {
    types_found: Vec<TypeName>,
    typedefs: HashMap<TypeName, TypedefTarget>,
}

impl TypeConverter {
    pub(crate) fn new() -> Self {
        Self {
            types_found: Vec::new(),
            typedefs: HashMap::new(),
        }
    }

    pub(crate) fn push(&mut self, ty: TypeName) {
        self.types_found.push(ty);
    }

    pub(crate) fn insert_typedef(&mut self, id: TypeName, ty: &Type) {
        let target = analyze_typedef_target(ty);
        self.typedefs.insert(id, target);
    }

    pub(crate) fn convert_boxed_type(
        &self,
        ty: Box<Type>,
        ns: &Namespace,
    ) -> Result<Annotated<Box<Type>>, ConvertError> {
        Ok(self.convert_type(*ty, ns)?.map(Box::new))
    }

    fn convert_type(&self, ty: Type, ns: &Namespace) -> Result<Annotated<Type>, ConvertError> {
        let result = match ty {
            Type::Path(p) => {
                let newp = self.convert_type_path(p, ns)?;
                // Special handling because rust_Str (as emitted by bindgen)
                // doesn't simply get renamed to a different type _identifier_.
                // This plain type-by-value (as far as bindgen is concerned)
                // is actually a &str.
                if should_dereference_in_cpp(&newp.ty) {
                    Annotated::new(
                        Type::Reference(parse_quote! {
                            &str
                        }),
                        newp.types_encountered,
                    )
                } else {
                    newp.map(Type::Path)
                }
            }
            Type::Reference(mut r) => {
                let innerty = self.convert_boxed_type(r.elem, ns)?;
                r.elem = innerty.ty;
                Annotated::new(Type::Reference(r), innerty.types_encountered)
            }
            Type::Ptr(ptr) => self.convert_ptr_to_reference(ptr, ns)?.map(Type::Reference),
            _ => Annotated::new(ty, Vec::new()),
        };
        Ok(result)
    }

    fn convert_type_path(
        &self,
        mut typ: TypePath,
        ns: &Namespace,
    ) -> Result<Annotated<TypePath>, ConvertError> {
        let mut types_encountered = Vec::new();
        if typ.path.segments.iter().next().unwrap().ident == "root" {
            typ.path.segments = typ
                .path
                .segments
                .into_iter()
                .map(|s| -> Result<PathSegment, ConvertError> {
                    let ident = &s.ident;
                    let args = match s.arguments {
                        PathArguments::AngleBracketed(mut ab) => {
                            let mut innerty = self.convert_punctuated(ab.args, ns)?;
                            ab.args = innerty.ty;
                            types_encountered.append(&mut innerty.types_encountered);
                            PathArguments::AngleBracketed(ab)
                        }
                        _ => s.arguments,
                    };
                    Ok(parse_quote!( #ident #args ))
                })
                .collect::<Result<_, _>>()?;
        } else {
            let ty = TypeName::from_type_path(&typ);
            // If the type looks like it is unqualified, check we know it
            // already, and if not, qualify it according to the current
            // namespace. This is a bit of a shortcut compared to having a full
            // resolution pass which can search all known namespaces.
            if !self.types_found.contains(&ty) && !is_known_type(&ty) {
                typ.path.segments = std::iter::once(&"root".to_string())
                    .chain(ns.iter())
                    .map(|s| parse_quote! { #s })
                    .chain(typ.path.segments.into_iter())
                    .collect();
                types_encountered.push(TypeName::from_type_path(&typ));
            } else {
                types_encountered.push(ty);
            }
        }
        let mut last_seg_args = None;
        let mut seg_iter = typ.path.segments.iter().peekable();
        while let Some(seg) = seg_iter.next() {
            if !seg.arguments.is_empty() {
                if seg_iter.peek().is_some() {
                    panic!("Did not expect bindgen to create a type with path arguments on a non-final segment")
                } else {
                    last_seg_args = Some(seg.arguments.clone());
                }
            }
        }
        drop(seg_iter);
        let tn = TypeName::from_type_path(&typ);
        // Let's see if this is a typedef.
        let typ = self
            .resolve_typedef(&tn)?
            .map(|x| x.to_type_path())
            .unwrap_or(typ);

        // This will strip off any path arguments...
        let mut typ = known_type_substitute_path(&typ).unwrap_or(typ);
        // but then we'll put them back again as necessary.
        if let Some(last_seg_args) = last_seg_args {
            let last_seg = typ.path.segments.last_mut().unwrap();
            last_seg.arguments = last_seg_args;
        }
        Ok(Annotated::new(typ, types_encountered))
    }

    fn convert_punctuated<P>(
        &self,
        pun: Punctuated<GenericArgument, P>,
        ns: &Namespace,
    ) -> Result<Annotated<Punctuated<GenericArgument, P>>, ConvertError>
    where
        P: Default,
    {
        let mut new_pun = Punctuated::new();
        let mut types_encountered = Vec::new();
        for arg in pun.into_iter() {
            new_pun.push(match arg {
                GenericArgument::Type(t) => {
                    let mut innerty = self.convert_type(t, ns)?;
                    types_encountered.append(&mut innerty.types_encountered);
                    GenericArgument::Type(innerty.ty)
                }
                _ => arg,
            });
        }
        Ok(Annotated::new(new_pun, types_encountered))
    }

    fn resolve_typedef<'b>(
        &'b self,
        tn: &'b TypeName,
    ) -> Result<Option<&'b TypeName>, ConvertError> {
        match self.typedefs.get(&tn) {
            None => Ok(None),
            Some(TypedefTarget::NoArguments(original_tn)) => {
                match self.resolve_typedef(original_tn)? {
                    None => Ok(Some(original_tn)),
                    Some(further_resolution) => Ok(Some(further_resolution)),
                }
            }
            _ => Err(ConvertError::ComplexTypedefTarget(tn.to_cpp_name())),
        }
    }

    fn convert_ptr_to_reference(
        &self,
        ptr: TypePtr,
        ns: &Namespace,
    ) -> Result<Annotated<TypeReference>, ConvertError> {
        let mutability = ptr.mutability;
        let elem = self.convert_boxed_type(ptr.elem, ns)?;
        // TODO - in the future, we should check if this is a rust::Str and throw
        // a wobbler if not. rust::Str should only be seen _by value_ in C++
        // headers; it manifests as &str in Rust but on the C++ side it must
        // be a plain value. We should detect and abort.
        Ok(elem.map(|elem| {
            parse_quote! {
                & #mutability #elem
            }
        }))
    }
}
<commit_msg>Blocklisting fixes<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;

use syn::{
    parse_quote, punctuated::Punctuated, GenericArgument, PathArguments, PathSegment, Type,
    TypePath, TypePtr, TypeReference,
};

use crate::{
    conversion::bridge_converter::ConvertError,
    known_types::{is_known_type, known_type_substitute_path, should_dereference_in_cpp},
    types::{Namespace, TypeName},
};

use super::typedef_analyzer::{analyze_typedef_target, TypedefTarget};

/// Results of some type conversion, annotated with a list of every type encountered.
pub(crate) struct Annotated<T> {
    pub(crate) ty: T,
    pub(crate) types_encountered: Vec<TypeName>,
}

impl<T> Annotated<T> {
    fn new(ty: T, types_encountered: Vec<TypeName>) -> Self {
        Self {
            ty,
            types_encountered,
        }
    }

    fn map<T2, F: FnOnce(T) -> T2>(self, fun: F) -> Annotated<T2> {
        Annotated {
            ty: fun(self.ty),
            types_encountered: self.types_encountered,
        }
    }
}

pub(crate) struct TypeConverter {
    types_found: Vec<TypeName>,
    typedefs: HashMap<TypeName, TypedefTarget>,
}

impl TypeConverter {
    pub(crate) fn new() -> Self {
        Self {
            types_found: Vec::new(),
            typedefs: HashMap::new(),
        }
    }

    pub(crate) fn push(&mut self, ty: TypeName) {
        self.types_found.push(ty);
    }

    pub(crate) fn insert_typedef(&mut self, id: TypeName, ty: &Type) {
        let target = analyze_typedef_target(ty);
        self.typedefs.insert(id, target);
    }

    pub(crate) fn convert_boxed_type(
        &self,
        ty: Box<Type>,
        ns: &Namespace,
    ) -> Result<Annotated<Box<Type>>, ConvertError> {
        Ok(self.convert_type(*ty, ns)?.map(Box::new))
    }

    fn convert_type(&self, ty: Type, ns: &Namespace) -> Result<Annotated<Type>, ConvertError> {
        let result = match ty {
            Type::Path(p) => {
                let newp = self.convert_type_path(p, ns)?;
                // Special handling because rust_Str (as emitted by bindgen)
                // doesn't simply get renamed to a different type _identifier_.
                // This plain type-by-value (as far as bindgen is concerned)
                // is actually a &str.
                if should_dereference_in_cpp(&newp.ty) {
                    Annotated::new(
                        Type::Reference(parse_quote! {
                            &str
                        }),
                        newp.types_encountered,
                    )
                } else {
                    newp.map(Type::Path)
                }
            }
            Type::Reference(mut r) => {
                let innerty = self.convert_boxed_type(r.elem, ns)?;
                r.elem = innerty.ty;
                Annotated::new(Type::Reference(r), innerty.types_encountered)
            }
            Type::Ptr(ptr) => self.convert_ptr_to_reference(ptr, ns)?.map(Type::Reference),
            _ => Annotated::new(ty, Vec::new()),
        };
        Ok(result)
    }

    fn convert_type_path(
        &self,
        mut typ: TypePath,
        ns: &Namespace,
    ) -> Result<Annotated<TypePath>, ConvertError> {
        let mut types_encountered = Vec::new();
        if typ.path.segments.iter().next().unwrap().ident == "root" {
            typ.path.segments = typ
                .path
                .segments
                .into_iter()
                .map(|s| -> Result<PathSegment, ConvertError> {
                    let ident = &s.ident;
                    let args = match s.arguments {
                        PathArguments::AngleBracketed(mut ab) => {
                            let mut innerty = self.convert_punctuated(ab.args, ns)?;
                            ab.args = innerty.ty;
                            types_encountered.append(&mut innerty.types_encountered);
                            PathArguments::AngleBracketed(ab)
                        }
                        _ => s.arguments,
                    };
                    Ok(parse_quote!( #ident #args ))
                })
                .collect::<Result<_, _>>()?;
        } else {
            let ty = TypeName::from_type_path(&typ);
            // If the type looks like it is unqualified, check we know it
            // already, and if not, qualify it according to the current
            // namespace. This is a bit of a shortcut compared to having a full
            // resolution pass which can search all known namespaces.
            if !self.types_found.contains(&ty) && !is_known_type(&ty) {
                typ.path.segments = std::iter::once(&"root".to_string())
                    .chain(ns.iter())
                    .map(|s| parse_quote! { #s })
                    .chain(typ.path.segments.into_iter())
                    .collect();
            }
        }
        let mut last_seg_args = None;
        let mut seg_iter = typ.path.segments.iter().peekable();
        while let Some(seg) = seg_iter.next() {
            if !seg.arguments.is_empty() {
                if seg_iter.peek().is_some() {
                    panic!("Did not expect bindgen to create a type with path arguments on a non-final segment")
                } else {
                    last_seg_args = Some(seg.arguments.clone());
                }
            }
        }
        drop(seg_iter);
        let tn = TypeName::from_type_path(&typ);
        types_encountered.push(tn.clone());
        // Let's see if this is a typedef.
        let typ = self
            .resolve_typedef(&tn)?
            .map(|x| x.to_type_path())
            .unwrap_or(typ);

        // This will strip off any path arguments...
        let mut typ = known_type_substitute_path(&typ).unwrap_or(typ);
        // but then we'll put them back again as necessary.
        if let Some(last_seg_args) = last_seg_args {
            let last_seg = typ.path.segments.last_mut().unwrap();
            last_seg.arguments = last_seg_args;
        }
        Ok(Annotated::new(typ, types_encountered))
    }

    fn convert_punctuated<P>(
        &self,
        pun: Punctuated<GenericArgument, P>,
        ns: &Namespace,
    ) -> Result<Annotated<Punctuated<GenericArgument, P>>, ConvertError>
    where
        P: Default,
    {
        let mut new_pun = Punctuated::new();
        let mut types_encountered = Vec::new();
        for arg in pun.into_iter() {
            new_pun.push(match arg {
                GenericArgument::Type(t) => {
                    let mut innerty = self.convert_type(t, ns)?;
                    types_encountered.append(&mut innerty.types_encountered);
                    GenericArgument::Type(innerty.ty)
                }
                _ => arg,
            });
        }
        Ok(Annotated::new(new_pun, types_encountered))
    }

    fn resolve_typedef<'b>(
        &'b self,
        tn: &'b TypeName,
    ) -> Result<Option<&'b TypeName>, ConvertError> {
        match self.typedefs.get(&tn) {
            None => Ok(None),
            Some(TypedefTarget::NoArguments(original_tn)) => {
                match self.resolve_typedef(original_tn)? {
                    None => Ok(Some(original_tn)),
                    Some(further_resolution) => Ok(Some(further_resolution)),
                }
            }
            _ => Err(ConvertError::ComplexTypedefTarget(tn.to_cpp_name())),
        }
    }

    fn convert_ptr_to_reference(
        &self,
        ptr: TypePtr,
        ns: &Namespace,
    ) -> Result<Annotated<TypeReference>, ConvertError> {
        let mutability = ptr.mutability;
        let elem = self.convert_boxed_type(ptr.elem, ns)?;
        // TODO - in the future, we should check if this is a rust::Str and throw
        // a wobbler if not. rust::Str should only be seen _by value_ in C++
        // headers; it manifests as &str in Rust but on the C++ side it must
        // be a plain value. We should detect and abort.
        Ok(elem.map(|elem| {
            parse_quote! {
                & #mutability #elem
            }
        }))
    }
}
<|endoftext|>


<commit_before>use crate::methods::decode::date::decode_date_maybe;
use defaults::Defaults;
use eyre::Result;
use once_cell::sync::Lazy;
use regex::Regex;
use stencila_schema::{
    Article, BlockContent, CreativeWorkAuthors, CreativeWorkTitle, Date, InlineContent, Node,
    Paragraph, Person, ThingDescription,
};

use super::decode::person::decode_person;
use super::encode::txt::ToTxt;

/// Reshaping options
#[derive(Defaults)]
pub struct Options {
    /// Reshape articles
    #[def = "true"]
    article: bool,

    /// Detect the title of a `CreativeWork`
    #[def = "true"]
    detect_title: bool,

    /// Infer the title of a `CreativeWork`
    #[def = "true"]
    infer_title: bool,

    /// Detect the authors of a `CreativeWork`
    #[def = "true"]
    detect_authors: bool,

    /// Infer the authors of a `CreativeWork`
    #[def = "true"]
    infer_authors: bool,

    /// Detect the date modified of a `CreativeWork`
    #[def = "true"]
    detect_date: bool,

    /// Infer the date modified of a `CreativeWork`
    #[def = "true"]
    infer_date: bool,

    /// Detect the keywords of a `CreativeWork`
    #[def = "true"]
    detect_keywords: bool,

    /// Detect the abstract of a `CreativeWork`
    #[def = "true"]
    detect_abstract: bool,
}

/// Reshape a node by inferring its semantic structure
///
/// Most often used on a `CreativeWork` to do things like infer
/// `title`, `authors`, `references` etc from its `content`.
pub fn reshape(node: &mut Node, options: Options) -> Result<()> {
    if let (Node::Article(article), true) = (node, &options.article) {
        reshape_article(article, &options)
    }
    Ok(())
}

/// Reshape an `Article`
pub fn reshape_article(article: &mut Article, options: &Options) {
    if let Some(blocks) = &mut article.content {
        let mut index = 0;
        while index < blocks.len() {
            let mut delta = 1;

            if index == 0 {
                // Detections and inferences of meta-data that are only done at the top of the content.
                // Note that, because these functions will pop blocks off the content if they
                // match (i.e. effectively reset index to 0), there can be more than one of these,
                // and they can be in any order (although the code is optimized for the following
                // order).

                if article.title.is_none() && options.detect_title {
                    delta += detect_title(&mut article.title, blocks, index)
                }
                if !blocks.is_empty() && article.title.is_none() && options.infer_title {
                    delta += infer_title(&mut article.title, blocks, index)
                }

                if !blocks.is_empty() && article.authors.is_none() && options.detect_authors {
                    delta += detect_authors(&mut article.authors, blocks, index)
                }
                if !blocks.is_empty() && article.authors.is_none() && options.infer_authors {
                    delta += infer_authors(&mut article.authors, blocks, index)
                }

                if !blocks.is_empty() && article.date_modified.is_none() && options.detect_date {
                    delta += detect_date(&mut article.date_modified, blocks, index)
                }
                if !blocks.is_empty() && article.date_modified.is_none() && options.infer_date {
                    delta += infer_date(&mut article.date_modified, blocks, index)
                }

                if !blocks.is_empty() && article.keywords.is_none() && options.detect_keywords {
                    delta += detect_keywords(&mut article.keywords, blocks, index)
                }

                if !blocks.is_empty() && article.description.is_none() && options.detect_abstract {
                    delta += detect_abstract(&mut article.description, blocks, index)
                }
            }

            index = index.saturating_add(delta.max(0) as usize);
        }
    }
}

/// Does a paragraph begin with a `Strong` node?
fn first_is_strong(paragraph: &Paragraph) -> bool {
    matches!(paragraph.content.first(), Some(InlineContent::Strong(_)))
}

/// Does a paragraph begin with a `Emphasis` node?
fn first_is_emphasis(paragraph: &Paragraph) -> bool {
    matches!(paragraph.content.first(), Some(InlineContent::Emphasis(_)))
}

/// Does a paragraph have a `Superscript` in it?
fn has_superscript(paragraph: &Paragraph) -> bool {
    paragraph
        .content
        .iter()
        .any(|inline| matches!(inline, InlineContent::Superscript(_)))
}

/// Remove the first `Mark` node from the start of a paragraph.
fn remove_first_mark(paragraph: &Paragraph) -> Vec<InlineContent> {
    let mut content = match paragraph.content.first() {
        Some(InlineContent::Emphasis(emphasis)) => emphasis.content.clone(),
        Some(InlineContent::Strong(strong)) => strong.content.clone(),
        _ => Vec::new(),
    };
    let mut rest = paragraph.content.clone();
    rest.remove(0);
    content.append(&mut rest);
    content
}

/// Detect the title of a `CreativeWork` from a paragraph starting with "title"
fn detect_title(
    title: &mut Option<Box<CreativeWorkTitle>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:T|t)itle\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            *title = Some(Box::new(CreativeWorkTitle::VecInlineContent(vec![
                InlineContent::String(captures[1].to_string()),
            ])));
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Infer the title of a `CreativeWork` from a `BlockContent` node
fn infer_title(
    title: &mut Option<Box<CreativeWorkTitle>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let inferred = match &blocks[index] {
        BlockContent::Heading(heading) => {
            if heading.depth == Some(1) {
                Some(Box::new(CreativeWorkTitle::VecInlineContent(
                    heading.content.clone(),
                )))
            } else {
                None
            }
        }
        BlockContent::Paragraph(paragraph) => {
            if first_is_strong(paragraph) || first_is_emphasis(paragraph) {
                Some(Box::new(CreativeWorkTitle::VecInlineContent(
                    remove_first_mark(paragraph),
                )))
            } else {
                None
            }
        }
        _ => None,
    };

    if inferred.is_some() {
        *title = inferred;
        blocks.remove(index);
        -1
    } else {
        0
    }
}

/// Detect the authors of a `CreativeWork` from a paragraph starting with "authors"
fn detect_authors(
    authors: &mut Option<Vec<CreativeWorkAuthors>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:A|a)uthors?\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });
    static SPLIT_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("\\s*;|(and)\\s*").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            let authors_ = SPLIT_REGEX
                .split(&captures[1])
                .map(|str| CreativeWorkAuthors::Person(decode_person(str)))
                .collect();
            *authors = Some(authors_);
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Infer the authors of a `CreativeWork` from a paragraph with superscripts, and/or ORCIDs.
fn infer_authors(
    authors: &mut Option<Vec<CreativeWorkAuthors>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let inferred = match &blocks[index] {
        BlockContent::Paragraph(paragraph) => {
            //let txt = paragraph.to_txt();
            if has_superscript(paragraph) {
                Some(vec![CreativeWorkAuthors::Person(Person {
                    // TODO: Remove superscripts and record affiliations
                    name: Some(Box::new("superscripted".to_string())),
                    ..Default::default()
                })])
            } else {
                None
            }
        }
        _ => None,
    };

    if inferred.is_some() {
        *authors = inferred;
        blocks.remove(index);
        -1
    } else {
        0
    }
}

/// Detect the date of a `CreativeWork` from a paragraph starting with "date"
fn detect_date(date: &mut Option<Box<Date>>, blocks: &mut Vec<BlockContent>, index: usize) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("^(?:D|d)ate\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            if let Some(date_) = decode_date_maybe(&captures[1]) {
                *date = Some(Box::new(date_));
                blocks.remove(index);
                return -1;
            }
        }
    }

    0
}

/// Infer the date of a `CreativeWork` from a `Paragraph` containing a date string
fn infer_date(date: &mut Option<Box<Date>>, blocks: &mut Vec<BlockContent>, index: usize) -> i32 {
    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(date_) = decode_date_maybe(&txt) {
            *date = Some(Box::new(date_));
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Detect the keywords of a `CreativeWork` from a paragraph starting with "keywords"
fn detect_keywords(
    keywords: &mut Option<Vec<String>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:K|k)eywords?\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });
    static SPLIT_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("\\s*;|,\\s*").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            let keywords_ = SPLIT_REGEX
                .split(&captures[1])
                .map(|str| str.to_string())
                .collect();
            *keywords = Some(keywords_);
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Detect the abstract of a `CreativeWork` from a series of blocks
///
/// If the current block looks like an abstract heading, consumes all
/// the following paragraphs.
fn detect_abstract(
    abstract_: &mut Option<Box<ThingDescription>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let is_abstract = match &blocks[index] {
        BlockContent::Heading(heading) => {
            let txt = heading.to_txt();
            txt.trim() == "Abstract"
        }
        BlockContent::Paragraph(paragraph) => {
            let txt = paragraph.to_txt();
            txt.trim() == "Abstract"
        }
        _ => false,
    };
    if !is_abstract {
        return 0;
    }

    blocks.remove(index);
    let mut removed = 1;

    let mut content: Vec<BlockContent> = Vec::new();
    while index < blocks.len() {
        let next = &blocks[index];
        match next {
            BlockContent::Paragraph(_) => {
                content.push(next.clone());
                blocks.remove(index);
                removed += 1;
            }
            _ => break,
        }
    }

    *abstract_ = Some(Box::new(ThingDescription::VecBlockContent(content)));
    -removed
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::methods::decode::yaml;
    use crate::utils::tests::snapshot_content;
    use insta::assert_json_snapshot;

    #[test]
    fn reshape_yaml_articles() {
        snapshot_content("articles/reshape-*.yaml", |content| {
            let mut article = yaml::decode(&content).expect("Unable to decode YAML");
            reshape(&mut article, Options::default()).expect("Unable to reshape");
            assert_json_snapshot!(article);
        });
    }
}
<commit_msg>fix(Reshape): Add ampersand to separators<commit_after>use crate::methods::decode::date::decode_date_maybe;
use defaults::Defaults;
use eyre::Result;
use once_cell::sync::Lazy;
use regex::Regex;
use stencila_schema::{
    Article, BlockContent, CreativeWorkAuthors, CreativeWorkTitle, Date, InlineContent, Node,
    Paragraph, Person, ThingDescription,
};

use super::decode::person::decode_person;
use super::encode::txt::ToTxt;

/// Reshaping options
#[derive(Defaults)]
pub struct Options {
    /// Reshape articles
    #[def = "true"]
    article: bool,

    /// Detect the title of a `CreativeWork`
    #[def = "true"]
    detect_title: bool,

    /// Infer the title of a `CreativeWork`
    #[def = "true"]
    infer_title: bool,

    /// Detect the authors of a `CreativeWork`
    #[def = "true"]
    detect_authors: bool,

    /// Infer the authors of a `CreativeWork`
    #[def = "true"]
    infer_authors: bool,

    /// Detect the date modified of a `CreativeWork`
    #[def = "true"]
    detect_date: bool,

    /// Infer the date modified of a `CreativeWork`
    #[def = "true"]
    infer_date: bool,

    /// Detect the keywords of a `CreativeWork`
    #[def = "true"]
    detect_keywords: bool,

    /// Detect the abstract of a `CreativeWork`
    #[def = "true"]
    detect_abstract: bool,
}

/// Reshape a node by inferring its semantic structure
///
/// Most often used on a `CreativeWork` to do things like infer
/// `title`, `authors`, `references` etc from its `content`.
pub fn reshape(node: &mut Node, options: Options) -> Result<()> {
    if let (Node::Article(article), true) = (node, &options.article) {
        reshape_article(article, &options)
    }
    Ok(())
}

/// Reshape an `Article`
pub fn reshape_article(article: &mut Article, options: &Options) {
    if let Some(blocks) = &mut article.content {
        let mut index = 0;
        while index < blocks.len() {
            let mut delta = 1;

            if index == 0 {
                // Detections and inferences of meta-data that are only done at the top of the content.
                // Note that, because these functions will pop blocks off the content if they
                // match (i.e. effectively reset index to 0), there can be more than one of these,
                // and they can be in any order (although the code is optimized for the following
                // order).

                if article.title.is_none() && options.detect_title {
                    delta += detect_title(&mut article.title, blocks, index)
                }
                if !blocks.is_empty() && article.title.is_none() && options.infer_title {
                    delta += infer_title(&mut article.title, blocks, index)
                }

                if !blocks.is_empty() && article.authors.is_none() && options.detect_authors {
                    delta += detect_authors(&mut article.authors, blocks, index)
                }
                if !blocks.is_empty() && article.authors.is_none() && options.infer_authors {
                    delta += infer_authors(&mut article.authors, blocks, index)
                }

                if !blocks.is_empty() && article.date_modified.is_none() && options.detect_date {
                    delta += detect_date(&mut article.date_modified, blocks, index)
                }
                if !blocks.is_empty() && article.date_modified.is_none() && options.infer_date {
                    delta += infer_date(&mut article.date_modified, blocks, index)
                }

                if !blocks.is_empty() && article.keywords.is_none() && options.detect_keywords {
                    delta += detect_keywords(&mut article.keywords, blocks, index)
                }

                if !blocks.is_empty() && article.description.is_none() && options.detect_abstract {
                    delta += detect_abstract(&mut article.description, blocks, index)
                }
            }

            index = index.saturating_add(delta.max(0) as usize);
        }
    }
}

/// Does a paragraph begin with a `Strong` node?
fn first_is_strong(paragraph: &Paragraph) -> bool {
    matches!(paragraph.content.first(), Some(InlineContent::Strong(_)))
}

/// Does a paragraph begin with a `Emphasis` node?
fn first_is_emphasis(paragraph: &Paragraph) -> bool {
    matches!(paragraph.content.first(), Some(InlineContent::Emphasis(_)))
}

/// Does a paragraph have a `Superscript` in it?
fn has_superscript(paragraph: &Paragraph) -> bool {
    paragraph
        .content
        .iter()
        .any(|inline| matches!(inline, InlineContent::Superscript(_)))
}

/// Remove the first `Mark` node from the start of a paragraph.
fn remove_first_mark(paragraph: &Paragraph) -> Vec<InlineContent> {
    let mut content = match paragraph.content.first() {
        Some(InlineContent::Emphasis(emphasis)) => emphasis.content.clone(),
        Some(InlineContent::Strong(strong)) => strong.content.clone(),
        _ => Vec::new(),
    };
    let mut rest = paragraph.content.clone();
    rest.remove(0);
    content.append(&mut rest);
    content
}

/// Detect the title of a `CreativeWork` from a paragraph starting with "title"
fn detect_title(
    title: &mut Option<Box<CreativeWorkTitle>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:T|t)itle\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            *title = Some(Box::new(CreativeWorkTitle::VecInlineContent(vec![
                InlineContent::String(captures[1].to_string()),
            ])));
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Infer the title of a `CreativeWork` from a `BlockContent` node
fn infer_title(
    title: &mut Option<Box<CreativeWorkTitle>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let inferred = match &blocks[index] {
        BlockContent::Heading(heading) => {
            if heading.depth == Some(1) {
                Some(Box::new(CreativeWorkTitle::VecInlineContent(
                    heading.content.clone(),
                )))
            } else {
                None
            }
        }
        BlockContent::Paragraph(paragraph) => {
            if first_is_strong(paragraph) || first_is_emphasis(paragraph) {
                Some(Box::new(CreativeWorkTitle::VecInlineContent(
                    remove_first_mark(paragraph),
                )))
            } else {
                None
            }
        }
        _ => None,
    };

    if inferred.is_some() {
        *title = inferred;
        blocks.remove(index);
        -1
    } else {
        0
    }
}

/// Detect the authors of a `CreativeWork` from a paragraph starting with "authors"
fn detect_authors(
    authors: &mut Option<Vec<CreativeWorkAuthors>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:A|a)uthors?\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });
    static SPLIT_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("\\s*;|(and)|&\\s*").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            let authors_ = SPLIT_REGEX
                .split(&captures[1])
                .map(|str| CreativeWorkAuthors::Person(decode_person(str)))
                .collect();
            *authors = Some(authors_);
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Infer the authors of a `CreativeWork` from a paragraph with superscripts, and/or ORCIDs.
fn infer_authors(
    authors: &mut Option<Vec<CreativeWorkAuthors>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let inferred = match &blocks[index] {
        BlockContent::Paragraph(paragraph) => {
            //let txt = paragraph.to_txt();
            if has_superscript(paragraph) {
                Some(vec![CreativeWorkAuthors::Person(Person {
                    // TODO: Remove superscripts and record affiliations
                    name: Some(Box::new("superscripted".to_string())),
                    ..Default::default()
                })])
            } else {
                None
            }
        }
        _ => None,
    };

    if inferred.is_some() {
        *authors = inferred;
        blocks.remove(index);
        -1
    } else {
        0
    }
}

/// Detect the date of a `CreativeWork` from a paragraph starting with "date"
fn detect_date(date: &mut Option<Box<Date>>, blocks: &mut Vec<BlockContent>, index: usize) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("^(?:D|d)ate\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            if let Some(date_) = decode_date_maybe(&captures[1]) {
                *date = Some(Box::new(date_));
                blocks.remove(index);
                return -1;
            }
        }
    }

    0
}

/// Infer the date of a `CreativeWork` from a `Paragraph` containing a date string
fn infer_date(date: &mut Option<Box<Date>>, blocks: &mut Vec<BlockContent>, index: usize) -> i32 {
    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(date_) = decode_date_maybe(&txt) {
            *date = Some(Box::new(date_));
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Detect the keywords of a `CreativeWork` from a paragraph starting with "keywords"
fn detect_keywords(
    keywords: &mut Option<Vec<String>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    static BEGINS_REGEX: Lazy<Regex> = Lazy::new(|| {
        Regex::new("^(?:K|k)eywords?\\b(?:[^\\w]*)?(.*)").expect("Unable to create regex")
    });
    static SPLIT_REGEX: Lazy<Regex> =
        Lazy::new(|| Regex::new("\\s*;|,\\s*").expect("Unable to create regex"));

    if let BlockContent::Paragraph(paragraph) = &blocks[index] {
        let txt = paragraph.to_txt();
        if let Some(captures) = BEGINS_REGEX.captures(&txt) {
            let keywords_ = SPLIT_REGEX
                .split(&captures[1])
                .map(|str| str.to_string())
                .collect();
            *keywords = Some(keywords_);
            blocks.remove(index);
            return -1;
        }
    }

    0
}

/// Detect the abstract of a `CreativeWork` from a series of blocks
///
/// If the current block looks like an abstract heading, consumes all
/// the following paragraphs.
fn detect_abstract(
    abstract_: &mut Option<Box<ThingDescription>>,
    blocks: &mut Vec<BlockContent>,
    index: usize,
) -> i32 {
    let is_abstract = match &blocks[index] {
        BlockContent::Heading(heading) => {
            let txt = heading.to_txt();
            txt.trim() == "Abstract"
        }
        BlockContent::Paragraph(paragraph) => {
            let txt = paragraph.to_txt();
            txt.trim() == "Abstract"
        }
        _ => false,
    };
    if !is_abstract {
        return 0;
    }

    blocks.remove(index);
    let mut removed = 1;

    let mut content: Vec<BlockContent> = Vec::new();
    while index < blocks.len() {
        let next = &blocks[index];
        match next {
            BlockContent::Paragraph(_) => {
                content.push(next.clone());
                blocks.remove(index);
                removed += 1;
            }
            _ => break,
        }
    }

    *abstract_ = Some(Box::new(ThingDescription::VecBlockContent(content)));
    -removed
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::methods::decode::yaml;
    use crate::utils::tests::snapshot_content;
    use insta::assert_json_snapshot;

    #[test]
    fn reshape_yaml_articles() {
        snapshot_content("articles/reshape-*.yaml", |content| {
            let mut article = yaml::decode(&content).expect("Unable to decode YAML");
            reshape(&mut article, Options::default()).expect("Unable to reshape");
            assert_json_snapshot!(article);
        });
    }
}
<|endoftext|>


<commit_before>use std;

pub struct Pairwise<I, T> {
    iter: I,
    prev: Option<T>,
}

impl<I: Iterator> Iterator for Pairwise<I, I::Item>
where
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        if self.prev.is_none() {
            self.prev = self.iter.next();
            if self.prev.is_none() {
                return None;
            }
        }

        let next = self.iter.next();
        if next.is_none() {
            return None;
        }

        use std::mem::replace;
        let pair = (
            replace(&mut self.prev, next.clone()).unwrap(),
            next.unwrap(),
        );
        Some(pair)
    }
}

trait IteratorExt2: Iterator + Sized {
    fn pairwise(self) -> Pairwise<Self, Self::Item>
    where
        Self::Item: Clone,
    {
        Pairwise {
            iter: self,
            prev: None,
        }
    }

    fn join(self, separator: &str) -> String
    where
        Self::Item: std::fmt::Display,
    {
        self.map(|x| format!("{}", x))
            .collect::<Vec<_>>()
            .join(separator)
    }

    fn sort_by_key<K, F>(self, f: F) -> std::vec::IntoIter<Self::Item>
    where
        K: Ord,
        F: Fn(&Self::Item) -> K,
    {
        let mut v = self.collect::<Vec<_>>();
        v.sort_by_key(f);
        v.into_iter()
    }
}

impl<T: Iterator> IteratorExt2 for T {}

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

    #[test]
    fn test_join_empty() {
        assert_eq!("", Vec::<i64>::new().into_iter().join(" "));
    }

    #[test]
    fn test_join() {
        assert_eq!("0 1 2 3", (0..4).join(" "))
    }

    #[test]
    fn test_pairwise() {
        assert_eq!(
            vec![(0, 1), (1, 2), (2, 3)],
            (0..4).pairwise().collect::<Vec<_>>()
        )
    }

    #[test]
    fn test_pairwise_empty() {
        assert_eq!(0, (0..0).pairwise().count());
        assert_eq!(0, (0..1).pairwise().count());
    }
}
<commit_msg>Add Iterator::group_by<commit_after>use std;

pub struct Pairwise<I, T> {
    iter: I,
    prev: Option<T>,
}

impl<I: Iterator> Iterator for Pairwise<I, I::Item>
where
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        if self.prev.is_none() {
            self.prev = self.iter.next();
            if self.prev.is_none() {
                return None;
            }
        }

        let next = self.iter.next();
        if next.is_none() {
            return None;
        }

        use std::mem::replace;
        let pair = (
            replace(&mut self.prev, next.clone()).unwrap(),
            next.unwrap(),
        );
        Some(pair)
    }
}

trait IteratorExt2: Iterator + Sized {
    fn pairwise(self) -> Pairwise<Self, Self::Item>
    where
        Self::Item: Clone,
    {
        Pairwise {
            iter: self,
            prev: None,
        }
    }

    fn join(self, separator: &str) -> String
    where
        Self::Item: std::fmt::Display,
    {
        self.map(|x| format!("{}", x))
            .collect::<Vec<_>>()
            .join(separator)
    }

    fn sort_by_key<K, F>(self, f: F) -> std::vec::IntoIter<Self::Item>
    where
        K: Ord,
        F: Fn(&Self::Item) -> K,
    {
        let mut v = self.collect::<Vec<_>>();
        v.sort_by_key(f);
        v.into_iter()
    }

    fn group_by<K, V, KF, VF>(
        self,
        mut key_fn: KF,
        mut value_fn: VF,
    ) -> std::vec::IntoIter<(K, Vec<V>)>
    where
        K: Clone + Eq + std::hash::Hash,
        KF: FnMut(&Self::Item) -> K,
        VF: FnMut(Self::Item) -> V,
    {
        use std::collections::HashMap;

        let mut groups = Vec::<(K, Vec<V>)>::new();
        let mut group_indices = HashMap::<K, usize>::new();

        for item in self {
            let key = key_fn(&item);
            let value = value_fn(item);

            match group_indices.get(&key) {
                Some(&index) => {
                    let (_, ref mut items) = groups[index];
                    items.push(value);
                }
                None => {
                    let index = groups.len();
                    groups.push((key.clone(), vec![value]));
                    group_indices.insert(key, index);
                }
            }
        }

        groups.into_iter()
    }
}

impl<T: Iterator> IteratorExt2 for T {}

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

    #[test]
    fn test_join_empty() {
        assert_eq!("", Vec::<i64>::new().into_iter().join(" "));
    }

    #[test]
    fn test_join() {
        assert_eq!("0 1 2 3", (0..4).join(" "))
    }

    #[test]
    fn test_pairwise() {
        assert_eq!(
            vec![(0, 1), (1, 2), (2, 3)],
            (0..4).pairwise().collect::<Vec<_>>()
        )
    }

    #[test]
    fn test_pairwise_empty() {
        assert_eq!(0, (0..0).pairwise().count());
        assert_eq!(0, (0..1).pairwise().count());
    }

    #[test]
    fn test_group_by() {
        let kvs = vec![
            ("Japan", "Tokyo"),
            ("Japan", "Osaka"),
            ("USA", "New York"),
            ("China", "Shanghai"),
            ("USA", "Los Angeles"),
        ];
        let expected = vec![
            ("Japan", vec!["Tokyo", "Osaka"]),
            ("USA", vec!["New York", "Los Angeles"]),
            ("China", vec!["Shanghai"]),
        ];

        let actual = kvs
            .into_iter()
            .group_by(|&(country, _)| country, |(_, city)| city);

        for ((ak, av), (xk, xv)) in actual.into_iter().zip(expected) {
            assert_eq!(xk, ak);
            for (a, x) in av.into_iter().zip(xv) {
                assert_eq!(a, x);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::old_io::{self, ByRefWriter, IoError};
use std::num::{Float, FpCategory};
use std::string::FromUtf8Error;

use ser;
use ser::Serializer;

/// A structure for implementing serialization to JSON.
pub struct Writer<W> {
    writer: W,
}

impl<W: old_io::Writer> Writer<W> {
    /// Creates a new JSON visitr whose output will be written to the writer
    /// specified.
    #[inline]
    pub fn new(writer: W) -> Writer<W> {
        Writer {
            writer: writer,
        }
    }

    /// Unwrap the Writer from the Serializer.
    #[inline]
    pub fn into_inner(self) -> W {
        self.writer
    }
}

impl<W: old_io::Writer> ser::Serializer for Writer<W> {
    type Value = ();
    type Error = IoError;

    #[inline]
    fn visit<
        T: ser::Serialize,
    >(&mut self, value: &T) -> Result<(), IoError> {
        value.visit(&mut Visitor { writer: &mut self.writer })
    }
}

struct Visitor<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: old_io::Writer> ser::Visitor for Visitor<'a, W> {
    type Value = ();
    type Error = IoError;

    #[inline]
    fn visit_unit(&mut self) -> Result<(), IoError> {
        self.writer.write_str("null")
    }

    #[inline]
    fn visit_bool(&mut self, value: bool) -> Result<(), IoError> {
        if value {
            self.writer.write_str("true")
        } else {
            self.writer.write_str("false")
        }
    }

    #[inline]
    fn visit_isize(&mut self, value: isize) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i8(&mut self, value: i8) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i16(&mut self, value: i16) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i32(&mut self, value: i32) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i64(&mut self, value: i64) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_usize(&mut self, value: usize) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u8(&mut self, value: u8) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u16(&mut self, value: u16) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u32(&mut self, value: u32) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u64(&mut self, value: u64) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_f64(&mut self, value: f64) -> Result<(), IoError> {
        fmt_f64_or_null(self.writer, value)
    }

    #[inline]
    fn visit_char(&mut self, v: char) -> Result<(), IoError> {
        escape_char(self.writer, v)
    }

    #[inline]
    fn visit_str(&mut self, value: &str) -> Result<(), IoError> {
        escape_str(self.writer, value)
    }

    #[inline]
    fn visit_none(&mut self) -> Result<(), IoError> {
        self.visit_unit()
    }

    #[inline]
    fn visit_some<V>(&mut self, value: V) -> Result<(), IoError>
        where V: ser::Serialize
    {
        value.visit(self)
    }

    #[inline]
    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), IoError>
        where V: ser::SeqVisitor,
    {
        try!(self.writer.write_str("["));

        while let Some(()) = try!(visitor.visit(self)) { }

        self.writer.write_str("]")
    }

    #[inline]
    fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> Result<(), IoError>
        where T: ser::Serialize,
    {
        if !first {
            try!(self.writer.write_str(","));
        }

        value.visit(self)
    }

    #[inline]
    fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), IoError>
        where V: ser::MapVisitor,
    {
        try!(self.writer.write_str("{{"));

        while let Some(()) = try!(visitor.visit(self)) { }

        self.writer.write_str("}}")
    }

    #[inline]
    fn visit_map_elt<K, V>(&mut self, first: bool, key: K, value: V) -> Result<(), IoError>
        where K: ser::Serialize,
              V: ser::Serialize,
    {
        if !first {
            try!(self.writer.write_str(","));
        }

        try!(key.visit(self));
        try!(self.writer.write_str(":"));
        value.visit(self)
    }
}

#[inline]
pub fn escape_bytes<W: old_io::Writer>(wr: &mut W, bytes: &[u8]) -> Result<(), IoError> {
    try!(wr.write_str("\""));

    let mut start = 0;

    for (i, byte) in bytes.iter().enumerate() {
        let escaped = match *byte {
            b'"' => "\\\"",
            b'\\' => "\\\\",
            b'\x08' => "\\b",
            b'\x0c' => "\\f",
            b'\n' => "\\n",
            b'\r' => "\\r",
            b'\t' => "\\t",
            _ => { continue; }
        };

        if start < i {
            try!(wr.write_all(&bytes[start..i]));
        }

        try!(wr.write_str(escaped));

        start = i + 1;
    }

    if start != bytes.len() {
        try!(wr.write_all(&bytes[start..]));
    }

    wr.write_str("\"")
}

#[inline]
pub fn escape_str<W: old_io::Writer>(wr: &mut W, value: &str) -> Result<(), IoError> {
    escape_bytes(wr, value.as_bytes())
}

#[inline]
pub fn escape_char<W: old_io::Writer>(wr: &mut W, value: char) -> Result<(), IoError> {
    let mut buf = &mut [0; 4];
    value.encode_utf8(buf);
    escape_bytes(wr, buf)
}

fn fmt_f64_or_null<W: old_io::Writer>(wr: &mut W, value: f64) -> Result<(), IoError> {
    match value.classify() {
        FpCategory::Nan | FpCategory::Infinite => wr.write_str("null"),
        _ => wr.write_str(&f64::to_str_digits(value, 6)),
    }
}

#[inline]
pub fn to_writer<W, T>(wr: &mut W, value: &T) -> Result<(), IoError>
    where W: old_io::Writer,
          T: ser::Serialize,
{
    let mut wr = Writer::new(wr.by_ref());
    try!(wr.visit(value));
    Ok(())
}

#[inline]
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, IoError>
    where T: ser::Serialize,
{
    let mut wr = Vec::with_capacity(128);
    to_writer(&mut wr, value).unwrap();
    Ok(wr)
}

#[inline]
pub fn to_string<T>(value: &T) -> Result<Result<String, FromUtf8Error>, IoError>
    where T: ser::Serialize,
{
    let vec = try!(to_vec(value));
    Ok(String::from_utf8(vec))
}
<commit_msg>Fix the json object delimiters<commit_after>use std::f64;
use std::old_io::{self, ByRefWriter, IoError};
use std::num::{Float, FpCategory};
use std::string::FromUtf8Error;

use ser;
use ser::Serializer;

/// A structure for implementing serialization to JSON.
pub struct Writer<W> {
    writer: W,
}

impl<W: old_io::Writer> Writer<W> {
    /// Creates a new JSON visitr whose output will be written to the writer
    /// specified.
    #[inline]
    pub fn new(writer: W) -> Writer<W> {
        Writer {
            writer: writer,
        }
    }

    /// Unwrap the Writer from the Serializer.
    #[inline]
    pub fn into_inner(self) -> W {
        self.writer
    }
}

impl<W: old_io::Writer> ser::Serializer for Writer<W> {
    type Value = ();
    type Error = IoError;

    #[inline]
    fn visit<
        T: ser::Serialize,
    >(&mut self, value: &T) -> Result<(), IoError> {
        value.visit(&mut Visitor { writer: &mut self.writer })
    }
}

struct Visitor<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: old_io::Writer> ser::Visitor for Visitor<'a, W> {
    type Value = ();
    type Error = IoError;

    #[inline]
    fn visit_unit(&mut self) -> Result<(), IoError> {
        self.writer.write_str("null")
    }

    #[inline]
    fn visit_bool(&mut self, value: bool) -> Result<(), IoError> {
        if value {
            self.writer.write_str("true")
        } else {
            self.writer.write_str("false")
        }
    }

    #[inline]
    fn visit_isize(&mut self, value: isize) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i8(&mut self, value: i8) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i16(&mut self, value: i16) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i32(&mut self, value: i32) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_i64(&mut self, value: i64) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_usize(&mut self, value: usize) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u8(&mut self, value: u8) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u16(&mut self, value: u16) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u32(&mut self, value: u32) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_u64(&mut self, value: u64) -> Result<(), IoError> {
        write!(self.writer, "{}", value)
    }

    #[inline]
    fn visit_f64(&mut self, value: f64) -> Result<(), IoError> {
        fmt_f64_or_null(self.writer, value)
    }

    #[inline]
    fn visit_char(&mut self, v: char) -> Result<(), IoError> {
        escape_char(self.writer, v)
    }

    #[inline]
    fn visit_str(&mut self, value: &str) -> Result<(), IoError> {
        escape_str(self.writer, value)
    }

    #[inline]
    fn visit_none(&mut self) -> Result<(), IoError> {
        self.visit_unit()
    }

    #[inline]
    fn visit_some<V>(&mut self, value: V) -> Result<(), IoError>
        where V: ser::Serialize
    {
        value.visit(self)
    }

    #[inline]
    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), IoError>
        where V: ser::SeqVisitor,
    {
        try!(self.writer.write_str("["));

        while let Some(()) = try!(visitor.visit(self)) { }

        self.writer.write_str("]")
    }

    #[inline]
    fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> Result<(), IoError>
        where T: ser::Serialize,
    {
        if !first {
            try!(self.writer.write_str(","));
        }

        value.visit(self)
    }

    #[inline]
    fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), IoError>
        where V: ser::MapVisitor,
    {
        try!(self.writer.write_str("{"));

        while let Some(()) = try!(visitor.visit(self)) { }

        self.writer.write_str("}")
    }

    #[inline]
    fn visit_map_elt<K, V>(&mut self, first: bool, key: K, value: V) -> Result<(), IoError>
        where K: ser::Serialize,
              V: ser::Serialize,
    {
        if !first {
            try!(self.writer.write_str(","));
        }

        try!(key.visit(self));
        try!(self.writer.write_str(":"));
        value.visit(self)
    }
}

#[inline]
pub fn escape_bytes<W: old_io::Writer>(wr: &mut W, bytes: &[u8]) -> Result<(), IoError> {
    try!(wr.write_str("\""));

    let mut start = 0;

    for (i, byte) in bytes.iter().enumerate() {
        let escaped = match *byte {
            b'"' => "\\\"",
            b'\\' => "\\\\",
            b'\x08' => "\\b",
            b'\x0c' => "\\f",
            b'\n' => "\\n",
            b'\r' => "\\r",
            b'\t' => "\\t",
            _ => { continue; }
        };

        if start < i {
            try!(wr.write_all(&bytes[start..i]));
        }

        try!(wr.write_str(escaped));

        start = i + 1;
    }

    if start != bytes.len() {
        try!(wr.write_all(&bytes[start..]));
    }

    wr.write_str("\"")
}

#[inline]
pub fn escape_str<W: old_io::Writer>(wr: &mut W, value: &str) -> Result<(), IoError> {
    escape_bytes(wr, value.as_bytes())
}

#[inline]
pub fn escape_char<W: old_io::Writer>(wr: &mut W, value: char) -> Result<(), IoError> {
    let mut buf = &mut [0; 4];
    value.encode_utf8(buf);
    escape_bytes(wr, buf)
}

fn fmt_f64_or_null<W: old_io::Writer>(wr: &mut W, value: f64) -> Result<(), IoError> {
    match value.classify() {
        FpCategory::Nan | FpCategory::Infinite => wr.write_str("null"),
        _ => wr.write_str(&f64::to_str_digits(value, 6)),
    }
}

#[inline]
pub fn to_writer<W, T>(wr: &mut W, value: &T) -> Result<(), IoError>
    where W: old_io::Writer,
          T: ser::Serialize,
{
    let mut wr = Writer::new(wr.by_ref());
    try!(wr.visit(value));
    Ok(())
}

#[inline]
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, IoError>
    where T: ser::Serialize,
{
    let mut wr = Vec::with_capacity(128);
    to_writer(&mut wr, value).unwrap();
    Ok(wr)
}

#[inline]
pub fn to_string<T>(value: &T) -> Result<Result<String, FromUtf8Error>, IoError>
    where T: ser::Serialize,
{
    let vec = try!(to_vec(value));
    Ok(String::from_utf8(vec))
}
<|endoftext|>