<commit_before>#![crate_name = "yaml"]
#![crate_type = "lib"]
#![feature(plugin)]
#![feature(box_syntax)]

#![feature(core)]
#![feature(libc)]
#![feature(io)]

#![plugin(regex_macros)]

extern crate libc;

extern crate regex;

use std::str;
use std::ffi::CStr;
use std::io::Read;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use error::YamlError;

pub mod ffi;
pub mod error;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    unsafe {
        str::from_utf8(CStr::from_ptr(ffi::yaml_get_version_string()).to_bytes()).unwrap().to_string()
    }
}

pub fn version() -> (isize, isize, isize) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as isize, c_minor as isize, c_patch as isize)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_bytes(bytes, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

pub fn parse_io_utf8(reader: &mut Read) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_io(reader, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Read, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io::BufReader;
    use constructor::YamlStandardData::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::YAML_EVENT_T_SIZE, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::YAML_PARSER_T_SIZE, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::YAML_EMITTER_T_SIZE, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::YAML_DOCUMENT_T_SIZE, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::YAML_NODE_T_SIZE, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<commit_msg>Remove unused feature flag<commit_after>#![crate_name = "yaml"]
#![crate_type = "lib"]
#![feature(plugin)]
#![feature(box_syntax)]

#![feature(core)]
#![feature(libc)]

#![plugin(regex_macros)]

extern crate libc;

extern crate regex;

use std::str;
use std::ffi::CStr;
use std::io::Read;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use error::YamlError;

pub mod ffi;
pub mod error;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    unsafe {
        str::from_utf8(CStr::from_ptr(ffi::yaml_get_version_string()).to_bytes()).unwrap().to_string()
    }
}

pub fn version() -> (isize, isize, isize) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as isize, c_minor as isize, c_patch as isize)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_bytes(bytes, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

pub fn parse_io_utf8(reader: &mut Read) -> Result<Vec<YamlStandardData>, YamlError> {
    parse_io(reader, ffi::YamlEncoding::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Read, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, YamlError> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    parser.load().map(|doc_res|
        doc_res.and_then(|doc| ctor.construct(doc.root().unwrap()))
    ).collect()
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io::BufReader;
    use constructor::YamlStandardData::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::YAML_EVENT_T_SIZE, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::YAML_PARSER_T_SIZE, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::YAML_EMITTER_T_SIZE, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::YAML_DOCUMENT_T_SIZE, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::YAML_NODE_T_SIZE, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Hewlett Packard Development Company L.P.
 *
 * 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
 *
 *     http://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.
 */
#![feature(mpsc_select)]
#![feature(scoped)]
#![feature(ip_addr)]
extern crate byteorder;
extern crate hash_ring;
extern crate uuid;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::option::Option;
use std::io;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::sync::Arc;
use std::thread;

use hash_ring::HashRing;

pub mod packet;
use packet::Packet;
pub mod connection;
use connection::Connection;
pub mod constants;
use constants::*;
pub mod base;
use base::BaseClientServer;
pub mod util;
use util::LoggingRwLock as RwLock;

fn run_test_server() -> (Arc<RwLock<Box<BaseClientServer>>>, u16) {
    match env_logger::init() {
        Ok(_) => { },
        Err(e) => {
            info!("{}", e);
        }
    }
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0 , 1), 0));
    let (mut bcs, threads) = BaseClientServer::run("runserver".to_string().into_bytes(), Some(vec![addr]));
    println!("Waiting 100ms for server");
    let mut port: u16;
    thread::sleep_ms(100);
    {
        let binds;
        {
            let bcs2 = bcs.clone();
            let bcs2 = bcs2.read(line!()).unwrap();
            binds = bcs2.binds.clone();
        }
        println!("Checking binds for actual port");
        match binds {
            None => unreachable!(),
            Some(binds) => {
                loop {
                    port = binds.lock().unwrap()[0].port();
                    if port != 0 {
                        println!("First bind port is {}", port);
                        break;
                    }
                    // condvar or channel is probably a better idea
                    thread::sleep_ms(100);
                }
            }
        }
    }
    (bcs, port)
}

#[test]
fn send_packet() {
    let (bcs, port) = run_test_server();
    let mut conn = Connection::new("127.0.0.1", port);
    conn.connect().unwrap();
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    match conn.send_packet(p) {
        Ok(_) => {},
        Err(_) => panic!("Error in send_packet."),
    }
    let bcs = bcs.read(line!()).unwrap();
    bcs.stop();
}

#[test]
#[should_panic]  // Still no echo implementation in server
fn echo() {
    let (bcs, port) = run_test_server();
    let mut test: Vec<u8> = Vec::new();
    test.extend("abc123".to_string().bytes());
    let mut conn = Connection::new("127.0.0.1", port);
    conn.connect().unwrap();
    let result = String::from_utf8(conn.echo(test, 0)).unwrap();
    assert_eq!("abc123", result);
    let mut test2: Vec<u8> = Vec::new();
    let mut output = String::from_utf8(conn.echo(test2, 0)).unwrap();
    println!("UUID = {}", output);
    let bcs = bcs.read(line!()).unwrap();
    bcs.stop();
}

#[test]
fn bcs_constructor() {
    let bcs = BaseClientServer::new("clientid".to_string().into_bytes());
}

#[test]
fn run_server_client_can_reach() {
    let (bcs, port) = run_test_server();
    // Is it working?
    let (mut bcs_client, client_threads) = BaseClientServer::run("servers_client".to_string().into_bytes(), None);
    {
        let bcs_client = bcs_client.write(line!()).unwrap();
        bcs_client.add_server("127.0.0.1".to_string(), port);
    }
    {
        //let bcs_client = bcs_client.read(line!()).unwrap();
        BaseClientServer::wait_for_connection(bcs_client.clone(), Some(5000)).unwrap();
    }
    {
        let bcs_client = bcs_client.write(line!()).unwrap();
        bcs_client.stop();
    }
    // Now shut server down
    let mut bcs = bcs.read(line!()).unwrap();
    println!("Stopping bcs...");
    bcs.stop();
}

#[test]
#[should_panic]
fn bcs_select_connection() {
    let (mut bcs, threads) = BaseClientServer::run("selconn".to_string().into_bytes(), None);
    println!("Waiting 100ms for connections");
    BaseClientServer::wait_for_connection(bcs.clone(), Some(100)).unwrap();
    let mut bcs = bcs.write(line!()).unwrap();
    bcs.select_connection("some string".to_string());
    bcs.stop();
    for thread in threads {
        thread.join();
    }
}

#[test]
fn bcs_run() {
    println!("Begin");
    let (mut bcs, threads) = BaseClientServer::run("clientid".to_string().into_bytes(), None);
    println!("Started");
    let mut bcs0 = bcs.clone();
    let mut bcs1 = bcs.clone();
    println!("Waiting 100ms");
    thread::sleep_ms(100);
    {
        let bcs = &bcs.read(line!()).unwrap();
        bcs.stop();
    }
    for thread in threads {
        thread.join();
    }
}
<commit_msg>Fix a bunch of warnings<commit_after>/*
 * Copyright (c) 2015, Hewlett Packard Development Company L.P.
 *
 * 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
 *
 *     http://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.
 */
#![feature(mpsc_select)]
#![feature(scoped)]
#![feature(ip_addr)]
extern crate byteorder;
extern crate hash_ring;
extern crate uuid;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::sync::Arc;
use std::thread;
use std::thread::JoinHandle;

pub mod packet;
use packet::Packet;
pub mod connection;
use connection::Connection;
pub mod constants;
use constants::*;
pub mod base;
use base::BaseClientServer;
pub mod util;
use util::LoggingRwLock as RwLock;

fn run_test_server() -> (Arc<RwLock<Box<BaseClientServer>>>, Vec<JoinHandle<()>>, u16) {
    match env_logger::init() {
        Ok(_) => { },
        Err(e) => {
            info!("{}", e);
        }
    }
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0 , 1), 0));
    let (bcs, threads) = BaseClientServer::run("runserver".to_string().into_bytes(), Some(vec![addr]));
    println!("Waiting 100ms for server");
    let mut port: u16;
    thread::sleep_ms(100);
    {
        let binds;
        {
            let bcs2 = bcs.clone();
            let bcs2 = bcs2.read(line!()).unwrap();
            binds = bcs2.binds.clone();
        }
        println!("Checking binds for actual port");
        match binds {
            None => unreachable!(),
            Some(binds) => {
                loop {
                    port = binds.lock().unwrap()[0].port();
                    if port != 0 {
                        println!("First bind port is {}", port);
                        break;
                    }
                    // condvar or channel is probably a better idea
                    thread::sleep_ms(100);
                }
            }
        }
    }
    (bcs, threads, port)
}

#[test]
fn send_packet() {
    let (bcs, _, port) = run_test_server();
    let mut conn = Connection::new("127.0.0.1", port);
    conn.connect().unwrap();
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    match conn.send_packet(p) {
        Ok(_) => {},
        Err(_) => panic!("Error in send_packet."),
    }
    let bcs = bcs.read(line!()).unwrap();
    bcs.stop();
}

#[test]
#[should_panic]  // Still no echo implementation in server
fn echo() {
    let (bcs, _, port) = run_test_server();
    let mut test: Vec<u8> = Vec::new();
    test.extend("abc123".to_string().bytes());
    let mut conn = Connection::new("127.0.0.1", port);
    conn.connect().unwrap();
    let result = String::from_utf8(conn.echo(test, 0)).unwrap();
    assert_eq!("abc123", result);
    let test2: Vec<u8> = Vec::new();
    let output = String::from_utf8(conn.echo(test2, 0)).unwrap();
    println!("UUID = {}", output);
    let bcs = bcs.read(line!()).unwrap();
    bcs.stop();
}

#[test]
fn bcs_constructor() {
    let bcs = BaseClientServer::new("clientid".to_string().into_bytes());
}

#[test]
fn run_server_client_can_reach() {
    let (bcs, _, port) = run_test_server();
    // Is it working?
    let (bcs_client, _) = BaseClientServer::run("servers_client".to_string().into_bytes(), None);
    {
        let bcs_client = bcs_client.write(line!()).unwrap();
        bcs_client.add_server("127.0.0.1".to_string(), port);
    }
    {
        //let bcs_client = bcs_client.read(line!()).unwrap();
        BaseClientServer::wait_for_connection(bcs_client.clone(), Some(5000)).unwrap();
    }
    {
        let bcs_client = bcs_client.write(line!()).unwrap();
        bcs_client.stop();
    }
    // Now shut server down
    let bcs = bcs.read(line!()).unwrap();
    println!("Stopping bcs...");
    bcs.stop();
}

#[test]
#[should_panic]
fn bcs_select_connection() {
    let (bcs, threads) = BaseClientServer::run("selconn".to_string().into_bytes(), None);
    println!("Waiting 100ms for connections");
    BaseClientServer::wait_for_connection(bcs.clone(), Some(100)).unwrap();
    let mut bcs = bcs.write(line!()).unwrap();
    bcs.select_connection("some string".to_string());
    bcs.stop();
    for thread in threads {
        thread.join();
    }
}

#[test]
fn bcs_run() {
    println!("Begin");
    let (bcs, threads) = BaseClientServer::run("clientid".to_string().into_bytes(), None);
    println!("Waiting 100ms");
    thread::sleep_ms(100);
    {
        let bcs = &bcs.read(line!()).unwrap();
        bcs.stop();
    }
    for thread in threads {
        thread.join();
    }
}
<|endoftext|>


<commit_before>//! # Feature flags
//!
//! This crate exposes a number of features. These can be enabled or disabled as shown
//! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features
//! are _disabled_ by default unless otherwise noted.
//!
//! Reliance on a given feature is always indicated alongside the item definition.
//!
//! - `std` (_enabled by default, implicitly enables `alloc`_)
//!
//!   This enables a number of features that depend on the standard library.
//!
//! - `alloc` (_enabled by default via `std`_)
//!
//!   Enables a number of features that require the ability to dynamically allocate memory.
//!
//! - `macros`
//!
//!   Enables macros that provide compile-time verification of values and intuitive syntax.
//!
//! - `formatting` (_implicitly enables `std`_)
//!
//!   Enables formatting of most structs.
//!
//! - `parsing`
//!
//!   Enables parsing of most structs.
//!
//! - `local-offset` (_implicitly enables `std`_)
//!
//!   This feature enables a number of methods that allow obtaining the system's UTC offset.
//!
//! - `large-dates`
//!
//!   By default, only years within the ±9999 range (inclusive) are supported. If you need support
//!   for years outside this range, consider enabling this feature; the supported range will be
//!   increased to ±999,999.
//!
//!   Note that enabling this feature has some costs, as it means forgoing some optimizations.
//!   Ambiguities may be introduced when parsing that would not otherwise exist.
//!
//!   If you are using this feature, **please leave a comment**
//!   [on this discussion](https://github.com/time-rs/time/discussions/306) with your use case. If
//!   there is not sufficient demand for this feature, it will be dropped in a future release.
//!
//! - `serde`
//!
//!   Enables [serde](https://docs.rs/serde) support for all types.
//!
//! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_)
//!
//!   Allows serde representations to use a human-readable format. This is determined by the
//!   serializer, not the user. If this feature is not enabled or if the serializer requests a
//!   non-human-readable format, a format optimized for binary representation will be used.
//!
//! - `rand`
//!
//!   Enables [rand](https://docs.rs/rand) support for all types.
//!
//! - `quickcheck` (_implicitly enables `alloc`_)
//!
//!   Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`].
//!
//! One pseudo-feature flag that is only available to end users is the `unsound_local_offset` cfg.
//! As the name indicates, using the feature is unsound, and [may cause unexpected segmentation
//! faults](https://github.com/time-rs/time/issues/293). Unlike other flags, this is deliberately
//! only available to end users; this is to ensure that a user doesn't have unsound behavior without
//! knowing it. To enable this behavior, you must use `RUSTFLAGS="--cfg unsound_local_offset" cargo
//! build` or similar. Note: This flag is _not tested anywhere_, including in the regular test of
//! the powerset of all feature flags. Use at your own risk. Without this flag, any method that
//! requires the local offset will return the `Err` variant.

#![doc(html_playground_url = "https://play.rust-lang.org")]
#![cfg_attr(__time_03_docs, feature(doc_cfg, doc_auto_cfg, doc_notable_trait))]
#![cfg_attr(
    __time_03_docs,
    deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
    anonymous_parameters,
    clippy::all,
    const_err,
    illegal_floating_point_literal_pattern,
    late_bound_lifetime_arguments,
    path_statements,
    patterns_in_fns_without_body,
    rust_2018_idioms,
    trivial_casts,
    trivial_numeric_casts,
    unreachable_pub,
    unsafe_code,
    unused_extern_crates
)]
#![warn(
    clippy::dbg_macro,
    clippy::decimal_literal_representation,
    clippy::get_unwrap,
    clippy::missing_docs_in_private_items,
    clippy::nursery,
    clippy::print_stdout,
    clippy::todo,
    clippy::unimplemented,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    deprecated_in_future,
    missing_copy_implementations,
    missing_debug_implementations,
    unused_qualifications,
    variant_size_differences
)]
#![allow(clippy::redundant_pub_crate)]
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(test(attr(deny(warnings))))]

#[allow(unused_extern_crates)]
#[cfg(feature = "alloc")]
extern crate alloc;

// region: macros
/// Helper macro for easily implementing `OpAssign`.
macro_rules! __impl_assign {
    ($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$(
        #[allow(unused_qualifications)]
        $(#[$attr])*
        impl core::ops::$op<$t> for $target {
            fn $fn(&mut self, rhs: $t) {
                *self = *self $sym rhs;
            }
        }
    )+};
}

/// Implement `AddAssign` for the provided types.
macro_rules! impl_add_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `SubAssign` for the provided types.
macro_rules! impl_sub_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `MulAssign` for the provided types.
macro_rules! impl_mul_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `DivAssign` for the provided types.
macro_rules! impl_div_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;

        let (_quotient, _remainder) = (_a / _b, _a % _b);

        if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
            _quotient - 1
        } else {
            _quotient
        }
    }};
}

/// Euclidean remainder. Useful for `const` contexts.
macro_rules! rem_euclid {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;
        let r = _a % _b;
        if r < 0 {
            if _b < 0 {
                r - _b
            } else {
                r + _b
            }
        } else {
            r
        }
    }};
}

/// Cascade an out-of-bounds value.
macro_rules! cascade {
    (@ordinal ordinal) => {};
    (@year year) => {};

    // Cascade an out-of-bounds value from "from" to "to".
    ($from:ident in $min:literal.. $max:literal => $to:tt) => {
        #[allow(unused_comparisons, unused_assignments)]
        if $from >= $max {
            $from -= $max - $min;
            $to += 1;
        } else if $from < $min {
            $from += $max - $min;
            $to -= 1;
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($ordinal:ident => $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@ordinal $ordinal);
        cascade!(@year $year);
        #[allow(unused_assignments)]
        if $ordinal > crate::util::days_in_year($year) {
            $year += 1;
            $ordinal = 1;
        } else if $ordinal == 0 {
            $year -= 1;
            $ordinal = crate::util::days_in_year($year);
        }
    };
}

/// Returns `Err(error::ComponentRange)` if the value is not in range.
macro_rules! ensure_value_in_range {
    ($value:ident in $start:expr => $end:expr) => {{
        let _start = $start;
        let _end = $end;
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < _start || $value > _end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: _start as _,
                maximum: _end as _,
                value: $value as _,
                conditional_range: false,
            });
        }
    }};

    ($value:ident conditionally in $start:expr => $end:expr) => {{
        let _start = $start;
        let _end = $end;
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < _start || $value > _end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: _start as _,
                maximum: _end as _,
                value: $value as _,
                conditional_range: true,
            });
        }
    }};
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
/// usable in `const` contexts.
macro_rules! const_try {
    ($e:expr) => {
        match $e {
            Ok(value) => value,
            Err(error) => return Err(error),
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
    ($e:expr) => {
        match $e {
            Some(value) => value,
            None => return None,
        }
    };
}
// endregion macros

mod date;
mod duration;
pub mod error;
pub mod ext;
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod format_description;
#[cfg(feature = "formatting")]
pub mod formatting;
#[cfg(feature = "std")]
mod instant;
#[cfg(feature = "macros")]
pub mod macros;
mod month;
mod offset_date_time;
#[cfg(feature = "parsing")]
pub mod parsing;
mod primitive_date_time;
#[cfg(feature = "quickcheck")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "quickcheck")))]
mod quickcheck;
#[cfg(feature = "rand")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
mod rand;
#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
#[cfg(test)]
mod tests;
mod time;
mod utc_offset;
pub mod util;
mod weekday;

pub use crate::date::Date;
pub use crate::duration::Duration;
pub use crate::error::Error;
#[cfg(feature = "std")]
pub use crate::instant::Instant;
pub use crate::month::Month;
pub use crate::offset_date_time::OffsetDateTime;
pub use crate::primitive_date_time::PrimitiveDateTime;
pub use crate::time::Time;
pub use crate::utc_offset::UtcOffset;
pub use crate::weekday::Weekday;

/// An alias for [`std::result::Result`] with a generic error from the time crate.
pub type Result<T> = core::result::Result<T, Error>;
<commit_msg>Formatting<commit_after>//! # Feature flags
//!
//! This crate exposes a number of features. These can be enabled or disabled as shown
//! [in Cargo's documentation](https://doc.rust-lang.org/cargo/reference/features.html). Features
//! are _disabled_ by default unless otherwise noted.
//!
//! Reliance on a given feature is always indicated alongside the item definition.
//!
//! - `std` (_enabled by default, implicitly enables `alloc`_)
//!
//!   This enables a number of features that depend on the standard library.
//!
//! - `alloc` (_enabled by default via `std`_)
//!
//!   Enables a number of features that require the ability to dynamically allocate memory.
//!
//! - `macros`
//!
//!   Enables macros that provide compile-time verification of values and intuitive syntax.
//!
//! - `formatting` (_implicitly enables `std`_)
//!
//!   Enables formatting of most structs.
//!
//! - `parsing`
//!
//!   Enables parsing of most structs.
//!
//! - `local-offset` (_implicitly enables `std`_)
//!
//!   This feature enables a number of methods that allow obtaining the system's UTC offset.
//!
//! - `large-dates`
//!
//!   By default, only years within the ±9999 range (inclusive) are supported. If you need support
//!   for years outside this range, consider enabling this feature; the supported range will be
//!   increased to ±999,999.
//!
//!   Note that enabling this feature has some costs, as it means forgoing some optimizations.
//!   Ambiguities may be introduced when parsing that would not otherwise exist.
//!
//!   If you are using this feature, **please leave a comment**
//!   [on this discussion](https://github.com/time-rs/time/discussions/306) with your use case. If
//!   there is not sufficient demand for this feature, it will be dropped in a future release.
//!
//! - `serde`
//!
//!   Enables [serde](https://docs.rs/serde) support for all types.
//!
//! - `serde-human-readable` (_implicitly enables `serde`, `formatting`, and `parsing`_)
//!
//!   Allows serde representations to use a human-readable format. This is determined by the
//!   serializer, not the user. If this feature is not enabled or if the serializer requests a
//!   non-human-readable format, a format optimized for binary representation will be used.
//!
//! - `rand`
//!
//!   Enables [rand](https://docs.rs/rand) support for all types.
//!
//! - `quickcheck` (_implicitly enables `alloc`_)
//!
//!   Enables [quickcheck](https://docs.rs/quickcheck) support for all types except [`Instant`].
//!
//! One pseudo-feature flag that is only available to end users is the `unsound_local_offset` cfg.
//! As the name indicates, using the feature is unsound, and [may cause unexpected segmentation
//! faults](https://github.com/time-rs/time/issues/293). Unlike other flags, this is deliberately
//! only available to end users; this is to ensure that a user doesn't have unsound behavior without
//! knowing it. To enable this behavior, you must use `RUSTFLAGS="--cfg unsound_local_offset" cargo
//! build` or similar. Note: This flag is _not tested anywhere_, including in the regular test of
//! the powerset of all feature flags. Use at your own risk. Without this flag, any method that
//! requires the local offset will return the `Err` variant.

#![doc(html_playground_url = "https://play.rust-lang.org")]
#![cfg_attr(__time_03_docs, feature(doc_cfg, doc_auto_cfg, doc_notable_trait))]
#![cfg_attr(
    __time_03_docs,
    deny(rustdoc::broken_intra_doc_links, rustdoc::private_intra_doc_links)
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(
    anonymous_parameters,
    clippy::all,
    const_err,
    illegal_floating_point_literal_pattern,
    late_bound_lifetime_arguments,
    path_statements,
    patterns_in_fns_without_body,
    rust_2018_idioms,
    trivial_casts,
    trivial_numeric_casts,
    unreachable_pub,
    unsafe_code,
    unused_extern_crates
)]
#![warn(
    clippy::dbg_macro,
    clippy::decimal_literal_representation,
    clippy::get_unwrap,
    clippy::missing_docs_in_private_items,
    clippy::nursery,
    clippy::print_stdout,
    clippy::todo,
    clippy::unimplemented,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    deprecated_in_future,
    missing_copy_implementations,
    missing_debug_implementations,
    unused_qualifications,
    variant_size_differences
)]
#![allow(clippy::redundant_pub_crate)]
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
#![doc(test(attr(deny(warnings))))]

#[allow(unused_extern_crates)]
#[cfg(feature = "alloc")]
extern crate alloc;

// region: macros
/// Helper macro for easily implementing `OpAssign`.
macro_rules! __impl_assign {
    ($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$(
        #[allow(unused_qualifications)]
        $(#[$attr])*
        impl core::ops::$op<$t> for $target {
            fn $fn(&mut self, rhs: $t) {
                *self = *self $sym rhs;
            }
        }
    )+};
}

/// Implement `AddAssign` for the provided types.
macro_rules! impl_add_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(+ AddAssign add_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `SubAssign` for the provided types.
macro_rules! impl_sub_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(- SubAssign sub_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `MulAssign` for the provided types.
macro_rules! impl_mul_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(* MulAssign mul_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Implement `DivAssign` for the provided types.
macro_rules! impl_div_assign {
    ($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
        __impl_assign!(/ DivAssign div_assign $target : $($(#[$attr])* $t),+);
    };
}

/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;

        let (_quotient, _remainder) = (_a / _b, _a % _b);

        if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
            _quotient - 1
        } else {
            _quotient
        }
    }};
}

/// Euclidean remainder. Useful for `const` contexts.
macro_rules! rem_euclid {
    ($a:expr, $b:expr) => {{
        let _a = $a;
        let _b = $b;
        let r = _a % _b;
        if r < 0 {
            if _b < 0 { r - _b } else { r + _b }
        } else {
            r
        }
    }};
}

/// Cascade an out-of-bounds value.
macro_rules! cascade {
    (@ordinal ordinal) => {};
    (@year year) => {};

    // Cascade an out-of-bounds value from "from" to "to".
    ($from:ident in $min:literal.. $max:literal => $to:tt) => {
        #[allow(unused_comparisons, unused_assignments)]
        if $from >= $max {
            $from -= $max - $min;
            $to += 1;
        } else if $from < $min {
            $from += $max - $min;
            $to -= 1;
        }
    };

    // Special case the ordinal-to-year cascade, as it has different behavior.
    ($ordinal:ident => $year:ident) => {
        // We need to actually capture the idents. Without this, macro hygiene causes errors.
        cascade!(@ordinal $ordinal);
        cascade!(@year $year);
        #[allow(unused_assignments)]
        if $ordinal > crate::util::days_in_year($year) {
            $year += 1;
            $ordinal = 1;
        } else if $ordinal == 0 {
            $year -= 1;
            $ordinal = crate::util::days_in_year($year);
        }
    };
}

/// Returns `Err(error::ComponentRange)` if the value is not in range.
macro_rules! ensure_value_in_range {
    ($value:ident in $start:expr => $end:expr) => {{
        let _start = $start;
        let _end = $end;
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < _start || $value > _end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: _start as _,
                maximum: _end as _,
                value: $value as _,
                conditional_range: false,
            });
        }
    }};

    ($value:ident conditionally in $start:expr => $end:expr) => {{
        let _start = $start;
        let _end = $end;
        #[allow(trivial_numeric_casts, unused_comparisons)]
        if $value < _start || $value > _end {
            return Err(crate::error::ComponentRange {
                name: stringify!($value),
                minimum: _start as _,
                maximum: _end as _,
                value: $value as _,
                conditional_range: true,
            });
        }
    }};
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
/// usable in `const` contexts.
macro_rules! const_try {
    ($e:expr) => {
        match $e {
            Ok(value) => value,
            Err(error) => return Err(error),
        }
    };
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
    ($e:expr) => {
        match $e {
            Some(value) => value,
            None => return None,
        }
    };
}
// endregion macros

mod date;
mod duration;
pub mod error;
pub mod ext;
#[cfg(any(feature = "formatting", feature = "parsing"))]
pub mod format_description;
#[cfg(feature = "formatting")]
pub mod formatting;
#[cfg(feature = "std")]
mod instant;
#[cfg(feature = "macros")]
pub mod macros;
mod month;
mod offset_date_time;
#[cfg(feature = "parsing")]
pub mod parsing;
mod primitive_date_time;
#[cfg(feature = "quickcheck")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "quickcheck")))]
mod quickcheck;
#[cfg(feature = "rand")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
mod rand;
#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
#[allow(missing_copy_implementations, missing_debug_implementations)]
pub mod serde;
#[cfg(test)]
mod tests;
mod time;
mod utc_offset;
pub mod util;
mod weekday;

pub use crate::date::Date;
pub use crate::duration::Duration;
pub use crate::error::Error;
#[cfg(feature = "std")]
pub use crate::instant::Instant;
pub use crate::month::Month;
pub use crate::offset_date_time::OffsetDateTime;
pub use crate::primitive_date_time::PrimitiveDateTime;
pub use crate::time::Time;
pub use crate::utc_offset::UtcOffset;
pub use crate::weekday::Weekday;

/// An alias for [`std::result::Result`] with a generic error from the time crate.
pub type Result<T> = core::result::Result<T, Error>;
<|endoftext|>


<commit_before>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40
#![allow(clippy::mem_replace_with_default, clippy::manual_non_exhaustive)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
        WhereClause,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    fn parse_signature(input: ParseStream<'_>) -> Result<Signature> {
        let constness: Option<Token![const]> = input.parse()?;
        let asyncness: Option<Token![async]> = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let abi: Option<Abi> = input.parse()?;
        let fn_token: Token![fn] = input.parse()?;
        let ident: Ident = input.parse()?;
        let generics: Generics = input.parse()?;

        let content;
        let paren_token = parenthesized!(content in input);
        let inputs = content.parse_terminated(FnArg::parse)?;
        let variadic = inputs.last().as_ref().and_then(get_variadic);

        fn get_variadic(input: &&FnArg) -> Option<Variadic> {
            if let FnArg::Typed(PatType { ty, .. }) = input {
                if let Type::Verbatim(tokens) = &**ty {
                    if let Ok(dots) = parse2(tokens.clone()) {
                        return Some(Variadic { attrs: Vec::new(), dots });
                    }
                }
            }
            None
        }

        let output: ReturnType = input.parse()?;
        let where_clause: Option<WhereClause> = input.parse()?;

        Ok(Signature {
            constness,
            asyncness,
            unsafety,
            abi,
            fn_token,
            ident,
            paren_token,
            inputs,
            output,
            variadic,
            generics: Generics { where_clause, ..generics },
        })
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = parse_signature(input)?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<commit_msg>Ignore clippy::match_like_matches_macro lint<commit_after>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
#![allow(
    clippy::mem_replace_with_default,
    clippy::manual_non_exhaustive,
    clippy::match_like_matches_macro
)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
        WhereClause,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    fn parse_signature(input: ParseStream<'_>) -> Result<Signature> {
        let constness: Option<Token![const]> = input.parse()?;
        let asyncness: Option<Token![async]> = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let abi: Option<Abi> = input.parse()?;
        let fn_token: Token![fn] = input.parse()?;
        let ident: Ident = input.parse()?;
        let generics: Generics = input.parse()?;

        let content;
        let paren_token = parenthesized!(content in input);
        let inputs = content.parse_terminated(FnArg::parse)?;
        let variadic = inputs.last().as_ref().and_then(get_variadic);

        fn get_variadic(input: &&FnArg) -> Option<Variadic> {
            if let FnArg::Typed(PatType { ty, .. }) = input {
                if let Type::Verbatim(tokens) = &**ty {
                    if let Ok(dots) = parse2(tokens.clone()) {
                        return Some(Variadic { attrs: Vec::new(), dots });
                    }
                }
            }
            None
        }

        let output: ReturnType = input.parse()?;
        let where_clause: Option<WhereClause> = input.parse()?;

        Ok(Signature {
            constness,
            asyncness,
            unsafety,
            abi,
            fn_token,
            ident,
            paren_token,
            inputs,
            output,
            variadic,
            generics: Generics { where_clause, ..generics },
        })
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = parse_signature(input)?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<|endoftext|>


<commit_before>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: ItemFn
//! [`syn_mid::Block`]: Block
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
#![allow(
    clippy::mem_replace_with_default,
    clippy::manual_non_exhaustive,
    clippy::match_like_matches_macro
)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    fn parse_signature(input: ParseStream<'_>) -> Result<Signature> {
        let constness: Option<Token![const]> = input.parse()?;
        let asyncness: Option<Token![async]> = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let abi: Option<Abi> = input.parse()?;
        let fn_token: Token![fn] = input.parse()?;
        let ident: Ident = input.parse()?;
        let mut generics: Generics = input.parse()?;

        let content;
        let paren_token = parenthesized!(content in input);
        let inputs = content.parse_terminated(FnArg::parse)?;
        let variadic = inputs.last().as_ref().and_then(get_variadic);

        fn get_variadic(input: &&FnArg) -> Option<Variadic> {
            if let FnArg::Typed(PatType { ty, .. }) = input {
                if let Type::Verbatim(tokens) = &**ty {
                    if let Ok(dots) = parse2(tokens.clone()) {
                        return Some(Variadic { attrs: Vec::new(), dots });
                    }
                }
            }
            None
        }

        let output: ReturnType = input.parse()?;
        generics.where_clause = input.parse()?;

        Ok(Signature {
            constness,
            asyncness,
            unsafety,
            abi,
            fn_token,
            ident,
            paren_token,
            inputs,
            output,
            variadic,
            generics,
        })
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = parse_signature(input)?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<commit_msg>impl Parse for Signature<commit_after>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! # Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** — Clone impls for all syntax tree types.
//!
//! [`syn_mid::ItemFn`]: ItemFn
//! [`syn_mid::Block`]: Block
//! [syn]: https://github.com/dtolnay/syn

#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
#![doc(test(
    no_crate_inject,
    attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![forbid(unsafe_code)]
#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
#![allow(
    clippy::mem_replace_with_default,
    clippy::manual_non_exhaustive,
    clippy::match_like_matches_macro
)]
#![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use crate::{
    arg::{FnArg, Receiver},
    pat::{
        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
        PatType, PatWild,
    },
};

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
    Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub sig: Signature,
        pub block: Box<Block>,
    }
}

ast_struct! {
    /// A function signature in a trait or implementation: `unsafe fn
    /// initialize(&self)`.
    pub struct Signature {
        pub constness: Option<Token![const]>,
        pub asyncness: Option<Token![async]>,
        pub unsafety: Option<Token![unsafe]>,
        pub abi: Option<Abi>,
        pub fn_token: Token![fn],
        pub ident: Ident,
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Variadic>,
        pub output: ReturnType,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
    };

    use super::{Block, FnArg, ItemFn, PatType, Signature};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
        }
    }

    impl Parse for Signature {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let constness: Option<Token![const]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse()?;
            let ident: Ident = input.parse()?;
            let mut generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let inputs = content.parse_terminated(FnArg::parse)?;
            let variadic = inputs.last().as_ref().and_then(get_variadic);

            fn get_variadic(input: &&FnArg) -> Option<Variadic> {
                if let FnArg::Typed(PatType { ty, .. }) = input {
                    if let Type::Verbatim(tokens) = &**ty {
                        if let Ok(dots) = parse2(tokens.clone()) {
                            return Some(Variadic { attrs: Vec::new(), dots });
                        }
                    }
                }
                None
            }

            let output: ReturnType = input.parse()?;
            generics.where_clause = input.parse()?;

            Ok(Self {
                constness,
                asyncness,
                unsafety,
                abi,
                fn_token,
                ident,
                paren_token,
                inputs,
                output,
                variadic,
                generics,
            })
        }
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let sig = input.parse()?;
            let block = input.parse()?;
            Ok(Self { attrs, vis, sig, block: Box::new(block) })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};
    use syn::{punctuated::Punctuated, Token, Type};

    use super::{Block, FnArg, ItemFn, Signature};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
        let last = match inputs.last() {
            Some(last) => last,
            None => return false,
        };

        let pat = match last {
            FnArg::Typed(pat) => pat,
            FnArg::Receiver(_) => return false,
        };

        let tokens = match pat.ty.as_ref() {
            Type::Verbatim(tokens) => tokens,
            _ => return false,
        };

        tokens.to_string() == "..."
    }

    impl ToTokens for Signature {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.constness.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !has_variadic(&self.inputs) {
                    if !self.inputs.empty_or_trailing() {
                        <Token![,]>::default().to_tokens(tokens);
                    }
                    self.variadic.to_tokens(tokens);
                }
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.sig.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Index;
use std::fmt::{self, Write};
use std::io::{self, Read};

#[derive(Clone)]
pub struct StrStack {
    data: String,
    ends: Vec<usize>,
}

impl Index<usize> for StrStack {
    type Output = str;
    #[inline]
    fn index(&self, index: usize) -> &str {
        let start = if index == 0 {
            0
        } else {
            self.ends[index-1]
        };
        let end = self.ends[index];
        &self.data[start..end]
    }
}

#[derive(Clone, Copy)]
pub struct Iter<'a> {
    stack: &'a StrStack,
    start: usize,
    end: usize,
}

impl fmt::Debug for StrStack {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a str;
    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        if self.start == self.end {
            None
        } else {
            let s = &self.stack[self.start];
            self.start += 1;
            Some(s)
        }
    }

    fn count(self) -> usize {
        self.end - self.start
    }

    fn nth(&mut self, n: usize) -> Option<&'a str> {
        match self.start.checked_add(n) {
            Some(n) if n < self.end => {
                self.start = n;
                self.next()
            },
            _ => {
                self.start = self.end;
                None
            }
        }
    }

    fn last(mut self) -> Option<&'a str> {
        self.next_back()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.end - self.start;
        (len, Some(len))
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

impl<'a> DoubleEndedIterator for Iter<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<&'a str> {
        if self.start == self.end {
            None
        } else {
            self.end -= 1;
            Some(&self.stack[self.end])
        }
    }
}

impl<'a> IntoIterator for &'a StrStack {
    type IntoIter = Iter<'a>;
    type Item = &'a str;
    #[inline]
    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

impl StrStack {
    /// Create a new StrStack.
    #[inline]
    pub fn new() -> StrStack {
        StrStack {
            data: String::new(),
            ends: Vec::new(),
        }
    }

    /// Create a new StrStack with the given capacity.
    ///
    /// You will be able to push `bytes` bytes and create `strings` strings before reallocating.
    #[inline]
    pub fn with_capacity(bytes: usize, strings: usize) -> StrStack {
        StrStack {
            data: String::with_capacity(bytes),
            ends: Vec::with_capacity(strings)
        }
    }

    /// Push a string onto the string stack.
    ///
    /// This returns the index of the string on the stack.
    #[inline]
    pub fn push(&mut self, s: &str) -> usize {
        self.data.push_str(s);
        self.ends.push(self.data.len());
        self.len() - 1
    }

    /// Iterate over the strings on the stack.
    #[inline]
    pub fn iter(&self) -> Iter {
        Iter {
            stack: self,
            start: 0,
            end: self.len(),
        }
    }

    /// Remove the top string from the stack.
    ///
    /// Returns true iff a string was removed.
    #[inline]
    pub fn pop(&mut self) -> bool {
        let popped = self.ends.pop().is_some();
        if let Some(&offset) = self.ends.last() {
            self.data.truncate(offset);
        }
        popped
    }

    /// Clear the stack.
    #[inline]
    pub fn clear(&mut self) {
        self.ends.clear();
        self.data.clear();
    }

    /// Returns the number of strings on the stack.
    #[inline]
    pub fn len(&self) -> usize {
        self.ends.len()
    }

    /// Truncate the stack to `len` strings.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        self.ends.truncate(len);
        self.data.truncate(*self.ends.last().unwrap_or(&0));
    }

    /// Read from `source` into the string stack.
    ///
    /// Returns the index of the new string or an IO Error.
    pub fn consume<R: io::Read>(&mut self, mut source: R) -> io::Result<usize> {
        match source.read_to_string(&mut self.data) {
            Ok(_) => {
                let idx = self.len();
                self.ends.push(self.data.len());
                Ok(idx)
            },
            Err(e) => Err(e),
        }
    }

    /// Returns a writer helper for this string stack.
    ///
    /// This is useful for building a string in-place on the string-stack.
    ///
    /// Example:
    ///
    /// ```
    /// use std::fmt::Write;
    /// use str_stack::StrStack;
    ///
    /// let mut s = StrStack::new();
    /// let index = {
    ///     let mut writer = s.writer();
    ///     writer.write_str("Hello");
    ///     writer.write_char(' ');
    ///     writer.write_str("World");
    ///     writer.write_char('!');
    ///     writer.finish()
    /// };
    /// assert_eq!(&s[index], "Hello World!");
    /// ```
    #[inline]
    pub fn writer(&mut self) -> Writer {
        Writer(self)
    }

    /// Allows calling the write! macro directly on the string stack:
    ///
    /// Example:
    ///
    /// ```
    /// use std::fmt::Write;
    /// use str_stack::StrStack;
    ///
    /// let mut s = StrStack::new();
    /// let index = write!(&mut s, "Hello {}!", "World");
    /// assert_eq!(&s[index], "Hello World!");
    /// ```
    #[inline]
    pub fn write_fmt(&mut self, args: fmt::Arguments) -> usize {
        let mut writer = self.writer();
        let _ = writer.write_fmt(args);
        writer.finish()
    }
}

pub struct Writer<'a>(&'a mut StrStack);

impl<'a> Writer<'a> {
    /// Finish pushing the string onto the stack and return its index.
    #[inline]
    pub fn finish(self) -> usize {
        // We push on drop.
        self.0.len()
    }
}
impl<'a> fmt::Write for Writer<'a> {
    #[inline]
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.0.data.push_str(s);
        Ok(())
    }
    #[inline]
    fn write_char(&mut self, c: char) -> fmt::Result {
        self.0.data.push(c);
        Ok(())
    }
}

impl<'a> Drop for Writer<'a> {
    fn drop(&mut self) {
        self.0.ends.push(self.0.data.len());
    }
}

#[test]
fn test_basic() {
    let mut stack = StrStack::new();
    let first = stack.push("one");
    let second = stack.push("two");
    let third = stack.push("three");

    assert_eq!(&stack[first], "one");
    assert_eq!(&stack[second], "two");
    assert_eq!(&stack[third], "three");

    assert_eq!(stack.len(), 3);

    assert!(stack.pop());

    assert_eq!(stack.len(), 2);

    assert_eq!(&stack[first], "one");
    assert_eq!(&stack[second], "two");

    assert!(stack.pop());
    assert!(stack.pop());

    assert_eq!(stack.len(), 0);
    assert!(!stack.pop());
}

#[test]
fn test_consume() {
    let mut stack = StrStack::new();
    let idx = stack.consume("testing".as_bytes()).unwrap();
    assert_eq!(&stack[idx], "testing");
}

#[test]
fn test_writer() {
    let mut stack = StrStack::new();
    let first = {
        let mut w = stack.writer();
        write!(w, "{}", "first ").unwrap();
        write!(w, "{}", "second").unwrap();
        w.finish()
    };

    let second = {
        let mut w = stack.writer();
        write!(w, "{}", "third ").unwrap();
        write!(w, "{}", "fourth").unwrap();
        w.finish()
    };
    assert_eq!(&stack[first], "first second");
    assert_eq!(&stack[second], "third fourth");
}
<commit_msg>Add extend/fromiterator<commit_after>use std::ops::Index;
use std::fmt::{self, Write};
use std::io::{self, Read};
use std::iter::FromIterator;

#[derive(Clone)]
pub struct StrStack {
    data: String,
    ends: Vec<usize>,
}

impl Index<usize> for StrStack {
    type Output = str;
    #[inline]
    fn index(&self, index: usize) -> &str {
        let start = if index == 0 {
            0
        } else {
            self.ends[index-1]
        };
        let end = self.ends[index];
        &self.data[start..end]
    }
}

#[derive(Clone, Copy)]
pub struct Iter<'a> {
    stack: &'a StrStack,
    start: usize,
    end: usize,
}

impl fmt::Debug for StrStack {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a str;
    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        if self.start == self.end {
            None
        } else {
            let s = &self.stack[self.start];
            self.start += 1;
            Some(s)
        }
    }

    fn count(self) -> usize {
        self.end - self.start
    }

    fn nth(&mut self, n: usize) -> Option<&'a str> {
        match self.start.checked_add(n) {
            Some(n) if n < self.end => {
                self.start = n;
                self.next()
            },
            _ => {
                self.start = self.end;
                None
            }
        }
    }

    fn last(mut self) -> Option<&'a str> {
        self.next_back()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.end - self.start;
        (len, Some(len))
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

impl<'a> DoubleEndedIterator for Iter<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<&'a str> {
        if self.start == self.end {
            None
        } else {
            self.end -= 1;
            Some(&self.stack[self.end])
        }
    }
}

impl<'a> IntoIterator for &'a StrStack {
    type IntoIter = Iter<'a>;
    type Item = &'a str;
    #[inline]
    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

impl StrStack {
    /// Create a new StrStack.
    #[inline]
    pub fn new() -> StrStack {
        StrStack {
            data: String::new(),
            ends: Vec::new(),
        }
    }

    /// Create a new StrStack with the given capacity.
    ///
    /// You will be able to push `bytes` bytes and create `strings` strings before reallocating.
    #[inline]
    pub fn with_capacity(bytes: usize, strings: usize) -> StrStack {
        StrStack {
            data: String::with_capacity(bytes),
            ends: Vec::with_capacity(strings)
        }
    }

    /// Push a string onto the string stack.
    ///
    /// This returns the index of the string on the stack.
    #[inline]
    pub fn push(&mut self, s: &str) -> usize {
        self.data.push_str(s);
        self.ends.push(self.data.len());
        self.len() - 1
    }

    /// Iterate over the strings on the stack.
    #[inline]
    pub fn iter(&self) -> Iter {
        Iter {
            stack: self,
            start: 0,
            end: self.len(),
        }
    }

    /// Remove the top string from the stack.
    ///
    /// Returns true iff a string was removed.
    #[inline]
    pub fn pop(&mut self) -> bool {
        let popped = self.ends.pop().is_some();
        if let Some(&offset) = self.ends.last() {
            self.data.truncate(offset);
        }
        popped
    }

    /// Clear the stack.
    #[inline]
    pub fn clear(&mut self) {
        self.ends.clear();
        self.data.clear();
    }

    /// Returns the number of strings on the stack.
    #[inline]
    pub fn len(&self) -> usize {
        self.ends.len()
    }

    /// Truncate the stack to `len` strings.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        self.ends.truncate(len);
        self.data.truncate(*self.ends.last().unwrap_or(&0));
    }

    /// Read from `source` into the string stack.
    ///
    /// Returns the index of the new string or an IO Error.
    pub fn consume<R: io::Read>(&mut self, mut source: R) -> io::Result<usize> {
        match source.read_to_string(&mut self.data) {
            Ok(_) => {
                let idx = self.len();
                self.ends.push(self.data.len());
                Ok(idx)
            },
            Err(e) => Err(e),
        }
    }

    /// Returns a writer helper for this string stack.
    ///
    /// This is useful for building a string in-place on the string-stack.
    ///
    /// Example:
    ///
    /// ```
    /// use std::fmt::Write;
    /// use str_stack::StrStack;
    ///
    /// let mut s = StrStack::new();
    /// let index = {
    ///     let mut writer = s.writer();
    ///     writer.write_str("Hello");
    ///     writer.write_char(' ');
    ///     writer.write_str("World");
    ///     writer.write_char('!');
    ///     writer.finish()
    /// };
    /// assert_eq!(&s[index], "Hello World!");
    /// ```
    #[inline]
    pub fn writer(&mut self) -> Writer {
        Writer(self)
    }

    /// Allows calling the write! macro directly on the string stack:
    ///
    /// Example:
    ///
    /// ```
    /// use std::fmt::Write;
    /// use str_stack::StrStack;
    ///
    /// let mut s = StrStack::new();
    /// let index = write!(&mut s, "Hello {}!", "World");
    /// assert_eq!(&s[index], "Hello World!");
    /// ```
    #[inline]
    pub fn write_fmt(&mut self, args: fmt::Arguments) -> usize {
        let mut writer = self.writer();
        let _ = writer.write_fmt(args);
        writer.finish()
    }
}

impl<S> Extend<S> for StrStack where S: AsRef<str> {
    fn extend<T>(&mut self, iterator: T) where T: IntoIterator<Item=S> {
        let iterator = iterator.into_iter();
        let (min, _) = iterator.size_hint();
        self.ends.reserve(min);
        for v in iterator {
            self.push(v.as_ref());
        }
    }
}

impl<S> FromIterator<S> for StrStack where S: AsRef<str> {
    fn from_iter<T>(iterator: T) -> Self where T: IntoIterator<Item=S> {
        let mut stack = StrStack::new();
        stack.extend(iterator);
        stack
    }
}

pub struct Writer<'a>(&'a mut StrStack);

impl<'a> Writer<'a> {
    /// Finish pushing the string onto the stack and return its index.
    #[inline]
    pub fn finish(self) -> usize {
        // We push on drop.
        self.0.len()
    }
}

impl<'a> fmt::Write for Writer<'a> {
    #[inline]
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.0.data.push_str(s);
        Ok(())
    }
    #[inline]
    fn write_char(&mut self, c: char) -> fmt::Result {
        self.0.data.push(c);
        Ok(())
    }
}

impl<'a> Drop for Writer<'a> {
    fn drop(&mut self) {
        self.0.ends.push(self.0.data.len());
    }
}

#[test]
fn test_basic() {
    let mut stack = StrStack::new();
    let first = stack.push("one");
    let second = stack.push("two");
    let third = stack.push("three");

    assert_eq!(&stack[first], "one");
    assert_eq!(&stack[second], "two");
    assert_eq!(&stack[third], "three");

    assert_eq!(stack.len(), 3);

    assert!(stack.pop());

    assert_eq!(stack.len(), 2);

    assert_eq!(&stack[first], "one");
    assert_eq!(&stack[second], "two");

    assert!(stack.pop());
    assert!(stack.pop());

    assert_eq!(stack.len(), 0);
    assert!(!stack.pop());
}

#[test]
fn test_consume() {
    let mut stack = StrStack::new();
    let idx = stack.consume("testing".as_bytes()).unwrap();
    assert_eq!(&stack[idx], "testing");
}

#[test]
fn test_writer() {
    let mut stack = StrStack::new();
    let first = {
        let mut w = stack.writer();
        write!(w, "{}", "first ").unwrap();
        write!(w, "{}", "second").unwrap();
        w.finish()
    };

    let second = {
        let mut w = stack.writer();
        write!(w, "{}", "third ").unwrap();
        write!(w, "{}", "fourth").unwrap();
        w.finish()
    };
    assert_eq!(&stack[first], "first second");
    assert_eq!(&stack[second], "third fourth");
}
<|endoftext|>


<commit_before>///! The Paeth decomposition of a N-dimensional rotation is an equivalent
///! composition of N one-dimensional shear operations.  Paeth decompositions
///! come from the paper "A Fast Algorithm for General Raster Rotation" by
///! Alan W. Paeth in 1986 (DOI 10.1016/B978-0-08-050753-8.50046-2)
///!
///! This crate implements Paeth decompositions for the 2d and 3d rotation
///! objects in the `nalgebra` package.

extern crate nalgebra as na;
use na::{BaseFloat, Rotation2, Matrix2};

/// Two-dimensional Paeth rotation
///
/// Decomposes a given rotation into an Y-shear followed by and X-shear:
/// `R = X*Y`.  The parameters of the shears are stored in a compact
/// form in the `PaethRotation2` struct:
///
/// ```ignore
/// X = [ gamma eta
///         0    1   ]
///
/// Y = [ 0      1
///       alpha beta ]
/// ```
///
/// The individual shear matrices can be computed with `shear_x()` and
/// `shear_y().
pub struct PaethRotation2<N>
where N: BaseFloat + Clone {
    pub alpha: N,
    pub beta: N,
    pub gamma: N,
    pub eta: N,
}

impl<N> PaethRotation2<N>
where N: BaseFloat + Clone {
    pub fn new(rot2: &Rotation2<N>) -> Self {
        let m = rot2.submatrix();
        PaethRotation2{
            alpha: m.m21,
            beta: m.m22,
            gamma: m.m11 - m.m12*m.m21/m.m22,
            eta: m.m12 / m.m22
        }
    }

    pub fn shear_y(self: &Self) -> Matrix2<N> {
        Matrix2{
            m11: N::one(),
            m12: N::zero(),
            m21: self.alpha,
            m22: self.beta,
        }
    }

    pub fn shear_x(self: &Self) -> Matrix2<N> {
        Matrix2{
            m11: self.gamma,
            m12: self.eta,
            m21: N::zero(),
            m22: N::one(),
        }
    }
}

/// Three-dimensional Paeth rotation
///
/// Decomposes a given rotation into a compositon of three one-dimensional
/// shears: `R = X*Y*Z`.  The parameters for the shears are stored in a
/// compact form in the `PathRotation3` struct:
///
/// ```ignore
///
/// X = [  xx   xy   xz
///         0    1    0
///         0    0    1]
///
/// Y = [   1    0    0
///        yx   yy   yz
///         0    0    1 ]
///
/// Z = [   1    0    0
///         0    1    0
///        zx   zy   zz ]
///
/// ```
///
/// The individual shear matrices can be computed with `shear_x()`, `shear_y()`
/// and `shear_z()`.
pub struct PaethRotation3<N>
where N: BaseFloat + Clone {
    pub xx: N,
    pub xy: N,
    pub xz: N,
    pub yx: N,
    pub yy: N,
    pub yz: N,
    pub zx: N,
    pub zy: N,
    pub zz: N,
}

impl<N> PaethRotation3<N>
where N: BaseFloat + Clone {
    pub fn new(rot3: &Rotation3<N>) -> Self {
        let m = rot3.submatrix();
    }

    pub fn shear_x(self: &Self) -> Matrix3<N> {
    }

    pub fn shear_y(self: &Self) -> Matrix3<N> {
    }

    pub fn shear_z(self: &Self) -> Matrix3<N> {
    }
}

#[test]
fn test_rot2() {
    use na::Vector1;

    let r = Rotation2::new(Vector1::new(32f32));
    let rm = r.submatrix();
    let p = PaethRotation2::new(&r);
    let px = p.shear_x();
    let py = p.shear_y();
    let rr = px * py;

    assert_eq!(rr.m11, rm.m11);
    assert_eq!(rr.m12, rm.m12);
    assert_eq!(rr.m21, rm.m21);
    assert_eq!(rr.m22, rm.m22);
}

<commit_msg>adds PaethRotation3 and test<commit_after>///! The Paeth decomposition of a N-dimensional rotation is an equivalent
///! composition of N one-dimensional shear operations.  Paeth decompositions
///! come from the paper "A Fast Algorithm for General Raster Rotation" by
///! Alan W. Paeth in 1986 (DOI 10.1016/B978-0-08-050753-8.50046-2)
///!
///! This crate implements Paeth decompositions for the 2d and 3d rotation
///! objects in the `nalgebra` package.

#[macro_use]
extern crate nalgebra as na;
use na::{BaseFloat, Rotation2, Matrix2, Rotation3, Matrix3, inverse, ApproxEq};

/// Two-dimensional Paeth rotation
///
/// Decomposes a given rotation into an Y-shear followed by and X-shear:
/// `R = X*Y`.  The parameters of the shears are stored in a compact
/// form in the `PaethRotation2` struct:
///
/// ```ignore
/// X = [ gamma eta
///         0    1   ]
///
/// Y = [ 0      1
///       alpha beta ]
/// ```
///
/// The individual shear matrices can be computed with `shear_x()` and
/// `shear_y().
pub struct PaethRotation2<N>
where N: BaseFloat + Clone {
    pub alpha: N,
    pub beta: N,
    pub gamma: N,
    pub eta: N,
}

impl<N> PaethRotation2<N>
where N: BaseFloat + Clone {
    pub fn new(rot2: &Rotation2<N>) -> Self {
        Self::new_from_matrix(rot2.submatrix())
    }

    pub fn new_from_matrix(m: &Matrix2<N>) -> Self {
        PaethRotation2{
            alpha: m.m21,
            beta: m.m22,
            gamma: m.m11 - m.m12*m.m21/m.m22,
            eta: m.m12 / m.m22
        }
    }

    pub fn shear_y(self: &Self) -> Matrix2<N> {
        Matrix2{
            m11: N::one(),
            m12: N::zero(),
            m21: self.alpha,
            m22: self.beta,
        }
    }

    pub fn shear_x(self: &Self) -> Matrix2<N> {
        Matrix2{
            m11: self.gamma,
            m12: self.eta,
            m21: N::zero(),
            m22: N::one(),
        }
    }
}

/// Three-dimensional Paeth rotation
///
/// Decomposes a given rotation into a compositon of three one-dimensional
/// shears: `R = X*Y*Z`.  The parameters for the shears are stored in a
/// compact form in the `PathRotation3` struct:
///
/// ```ignore
///
/// X = [  xx   xy   xz
///         0    1    0
///         0    0    1]
///
/// Y = [   1    0    0
///        yx   yy   yz
///         0    0    1 ]
///
/// Z = [   1    0    0
///         0    1    0
///        zx   zy   zz ]
///
/// ```
///
/// The individual shear matrices can be computed with `shear_x()`, `shear_y()`
/// and `shear_z()`.
pub struct PaethRotation3<N>
where N: BaseFloat + Clone {
    pub xx: N,
    pub xy: N,
    pub xz: N,
    pub yx: N,
    pub yy: N,
    pub yz: N,
    pub zx: N,
    pub zy: N,
    pub zz: N,
}

fn shear_x_from_entries<N: BaseFloat + Clone>(xx: N, xy: N, xz: N) -> Matrix3<N> {
    Matrix3{
        m11: xx,
        m12: xy,
        m13: xz,

        m21: N::zero(),
        m22: N::one(),
        m23: N::zero(),

        m31: N::zero(),
        m32: N::zero(),
        m33: N::one(),
    }
}

fn shear_y_from_entries<N: BaseFloat + Clone>(yx: N, yy: N, yz: N) -> Matrix3<N> {
    Matrix3{
        m11: N::one(),
        m12: N::zero(),
        m13: N::zero(),

        m21: yx,
        m22: yy,
        m23: yz,

        m31: N::zero(),
        m32: N::zero(),
        m33: N::one(),
    }
}

fn shear_z_from_entries<N: BaseFloat + Clone>(zx: N, zy: N, zz: N) -> Matrix3<N> {
    Matrix3{
        m11: N::one(),
        m12: N::zero(),
        m13: N::zero(),

        m21: N::zero(),
        m22: N::one(),
        m23: N::zero(),

        m31: zx,
        m32: zy,
        m33: zz,
    }
}

impl<N> PaethRotation3<N>
where N: BaseFloat + Clone + ApproxEq<N> {
    pub fn new(rot3: &Rotation3<N>) -> Self {
        Self::new_from_matrix(rot3.submatrix())
    }

    pub fn new_from_matrix(m: &Matrix3<N>) -> Self {
        // one could write explicit expressions for the factorization,
        // but for the sake of simplicity here, we successively
        // "peel off" dimensions of the rotation

        let zx = m.m31;
        let zy = m.m32;
        let zz = m.m33;

        let shear_z = shear_z_from_entries(zx.clone(), zy.clone(), zz.clone());
        let m_less_z = *m * inverse(&shear_z).expect("shear_z was not invertible?");

        let yx = m_less_z.m21;
        let yy = m_less_z.m22;
        let yz = m_less_z.m23;

        let shear_y = shear_y_from_entries(yx.clone(), yy.clone(), yz.clone());
        let m_less_yz = m_less_z * inverse(&shear_y).expect("shear_y not invertible?");

        let xx = m_less_yz.m11;
        let xy = m_less_yz.m12;
        let xz = m_less_yz.m13;

        PaethRotation3{
            xx: xx,
            xy: xy,
            xz: xz,

            yx: yx,
            yy: yy,
            yz: yz,

            zx: zx,
            zy: zy,
            zz: zz,
        }
    }

    pub fn shear_x(self: &Self) -> Matrix3<N> {
        shear_x_from_entries(self.xx.clone(), self.xy.clone(), self.xz.clone())
    }

    pub fn shear_y(self: &Self) -> Matrix3<N> {
        shear_y_from_entries(self.yx.clone(), self.yy.clone(), self.yz.clone())
    }

    pub fn shear_z(self: &Self) -> Matrix3<N> {
        shear_z_from_entries(self.zx.clone(), self.zy.clone(), self.zz.clone())
    }
}

#[test]
fn test_rot2() {
    use na::Vector1;

    let r = Rotation2::new(Vector1::new(32f32));
    let rm = r.submatrix();
    let p = PaethRotation2::new(&r);
    let px = p.shear_x();
    let py = p.shear_y();
    let rr = px * py;

    assert_approx_eq!(rr.m11, rm.m11);
    assert_approx_eq!(rr.m12, rm.m12);
    assert_approx_eq!(rr.m21, rm.m21);
    assert_approx_eq!(rr.m22, rm.m22);
}

#[test]
fn test_rot3() {
    use na::Vector3;

    let r = Rotation3::new(Vector3::new(2f32, 5f32, -3f32));
    let rm = r.submatrix();
    let p = PaethRotation3::new(&r);
    let px = p.shear_x();
    let py = p.shear_y();
    let pz = p.shear_z();
    let rr = px * py * pz;

    assert_approx_eq!(rr.m11, rm.m11);
    assert_approx_eq!(rr.m12, rm.m12);
    assert_approx_eq!(rr.m13, rm.m13);

    assert_approx_eq!(rr.m21, rm.m21);
    assert_approx_eq!(rr.m22, rm.m22);
    assert_approx_eq!(rr.m23, rm.m23);

    assert_approx_eq!(rr.m31, rm.m31);
    assert_approx_eq!(rr.m32, rm.m32);
    assert_approx_eq!(rr.m33, rm.m33);
}

<|endoftext|>