<commit_before>// Copyright (c) 2015-2016 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate clock_ticks;

use std::thread;
use std::net::SocketAddr;
use super::super::{Client, Connection, Config, Handler, MessageKind, Stats};

struct MockClientHandler {
    pub last_tick_time: u32,
    pub tick_count: u32,
    pub accumulated: u32
}

impl Handler<Client> for MockClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.last_tick_time = precise_time_ms();
    }

    fn tick_connection(
        &mut self, client: &mut Client,
        _: &mut Connection
    ) {

        // Accumulate time so we can check that the artificial delay
        // was correct for by the servers tick loop
        if self.tick_count > 1 {
            self.accumulated += precise_time_ms() - self.last_tick_time;
        }

        self.last_tick_time = precise_time_ms();
        self.tick_count += 1;

        if self.tick_count == 5 {
            client.close().unwrap();
        }

        // Fake some load inside of the tick handler
        thread::sleep_ms(75);

    }

}

struct MockSyncClientHandler {
    pub connect_count: u32,
    pub tick_count: u32,
    pub close_count: u32
}

impl Handler<Client> for MockSyncClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.connect_count += 1;
    }

    fn tick_connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.tick_count += 1;
    }

    fn close(&mut self, _: &mut Client) {
        self.close_count += 1;
    }

}

struct MockClientStatsHandler {
    pub tick_count: u32,
}

impl Handler<Client> for MockClientStatsHandler {

    fn connect(&mut self, _: &mut Client) {
    }

    fn tick_connection(
        &mut self, client: &mut Client,
        conn: &mut Connection
    ) {

        conn.send(MessageKind::Instant, b"Hello World".to_vec());
        self.tick_count += 1;

        if self.tick_count == 20 {
            client.close().unwrap();
        }

    }

}

fn precise_time_ms() -> u32 {
    (clock_ticks::precise_time_ns() / 1000000) as u32
}

#[test]
fn test_client_tick_delay() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockClientHandler {
        last_tick_time: 0,
        tick_count: 0,
        accumulated: 0
    };

    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12345").unwrap();

    assert!(handler.accumulated <= 350);

}

#[test]
fn test_client_sync() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockSyncClientHandler {
        connect_count: 0,
        tick_count: 0,
        close_count: 0
    };

    // TODO improve sync client tests
    let mut client = Client::new(config);
    let mut state = client.connect_sync(&mut handler, "127.0.0.1:12345").unwrap();
    assert_eq!(handler.tick_count, 0);
    assert_eq!(handler.connect_count, 1);

    assert_eq!(state.rtt(), 0);
    assert_eq!(state.packet_loss(), 0.0);

    let peer_addr: SocketAddr = "127.0.0.1:12345".parse().unwrap();
    assert_eq!(state.peer_addr(), peer_addr);

    client.receive_sync(&mut handler, &mut state, 0);
    client.tick_sync(&mut handler, &mut state);
    assert_eq!(handler.tick_count, 1);
    client.send_sync(&mut handler, &mut state);

    client.receive_sync(&mut handler, &mut state, 0);
    client.tick_sync(&mut handler, &mut state);
    assert_eq!(handler.tick_count, 2);
    client.send_sync(&mut handler, &mut state);

    client.close_sync(&mut handler, &mut state).unwrap();
    assert_eq!(handler.close_count, 1);

}

#[test]
fn test_client_sync_set_config() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockSyncClientHandler {
        connect_count: 0,
        tick_count: 0,
        close_count: 0
    };

    // TODO improve sync client tests
    let mut client = Client::new(config);
    let mut state = client.connect_sync(&mut handler, "127.0.0.1:12345").unwrap();

    client.set_config(Config {
        send_rate: 30,
        .. Config::default()

    }, &mut state);

}

#[test]
fn test_client_stats() {

    let config = Config {
        send_rate: 20,
        connection_init_threshold: 1500,
        connection_drop_threshold: 2500,
        .. Config::default()
    };

    let mut handler = MockClientStatsHandler {
        tick_count: 0
    };

    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12346").unwrap();

    assert_eq!(client.stats(), Stats {
        bytes_sent: 300,
        bytes_received: 0
    });

}

<commit_msg>Reduce timing related test issues.<commit_after>// Copyright (c) 2015-2016 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate clock_ticks;

use std::thread;
use std::net::SocketAddr;
use super::super::{Client, Connection, Config, Handler, MessageKind, Stats};

struct MockClientHandler {
    pub last_tick_time: u32,
    pub tick_count: u32,
    pub accumulated: u32
}

impl Handler<Client> for MockClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.last_tick_time = precise_time_ms();
    }

    fn tick_connection(&mut self, client: &mut Client, _: &mut Connection) {

        // Accumulate time so we can check that the artificial delay
        // was correct for by the servers tick loop
        if self.tick_count > 1 {
            self.accumulated += precise_time_ms() - self.last_tick_time;
        }

        self.last_tick_time = precise_time_ms();
        self.tick_count += 1;

        if self.tick_count == 5 {
            client.close().unwrap();
        }

        // Fake some load inside of the tick handler
        thread::sleep_ms(75);

    }

}

struct MockSyncClientHandler {
    pub connect_count: u32,
    pub tick_count: u32,
    pub close_count: u32
}

impl Handler<Client> for MockSyncClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.connect_count += 1;
    }

    fn tick_connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.tick_count += 1;
    }

    fn close(&mut self, _: &mut Client) {
        self.close_count += 1;
    }

}

struct MockClientStatsHandler {
    pub tick_count: u32,
}

impl Handler<Client> for MockClientStatsHandler {

    fn connect(&mut self, _: &mut Client) {
    }

    fn tick_connection(
        &mut self, client: &mut Client,
        conn: &mut Connection
    ) {

        conn.send(MessageKind::Instant, b"Hello World".to_vec());
        self.tick_count += 1;

        if self.tick_count == 20 {
            client.close().unwrap();
        }

    }

}

fn precise_time_ms() -> u32 {
    (clock_ticks::precise_time_ns() / 1000000) as u32
}

#[test]
fn test_client_tick_delay() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockClientHandler {
        last_tick_time: 0,
        tick_count: 0,
        accumulated: 0
    };

    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12345").unwrap();

    assert!(handler.accumulated <= 350);

}

#[test]
fn test_client_sync() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockSyncClientHandler {
        connect_count: 0,
        tick_count: 0,
        close_count: 0
    };

    // TODO improve sync client tests
    let mut client = Client::new(config);
    let mut state = client.connect_sync(&mut handler, "127.0.0.1:12345").unwrap();
    assert_eq!(handler.tick_count, 0);
    assert_eq!(handler.connect_count, 1);

    assert_eq!(state.rtt(), 0);
    assert_eq!(state.packet_loss(), 0.0);

    let peer_addr: SocketAddr = "127.0.0.1:12345".parse().unwrap();
    assert_eq!(state.peer_addr(), peer_addr);

    client.receive_sync(&mut handler, &mut state, 0);
    client.tick_sync(&mut handler, &mut state);
    assert_eq!(handler.tick_count, 1);
    client.send_sync(&mut handler, &mut state);

    client.receive_sync(&mut handler, &mut state, 0);
    client.tick_sync(&mut handler, &mut state);
    assert_eq!(handler.tick_count, 2);
    client.send_sync(&mut handler, &mut state);

    client.close_sync(&mut handler, &mut state).unwrap();
    assert_eq!(handler.close_count, 1);

}

#[test]
fn test_client_sync_set_config() {

    let config = Config {
        send_rate: 10,
        .. Config::default()
    };

    let mut handler = MockSyncClientHandler {
        connect_count: 0,
        tick_count: 0,
        close_count: 0
    };

    // TODO improve sync client tests
    let mut client = Client::new(config);
    let mut state = client.connect_sync(&mut handler, "127.0.0.1:12345").unwrap();

    client.set_config(Config {
        send_rate: 30,
        .. Config::default()

    }, &mut state);

}

#[test]
fn test_client_stats() {

    let config = Config {
        send_rate: 20,
        connection_init_threshold: 500000,
        connection_drop_threshold: 500000,
        .. Config::default()
    };

    let mut handler = MockClientStatsHandler {
        tick_count: 0
    };

    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12346").unwrap();

    assert_eq!(client.stats(), Stats {
        bytes_sent: 300,
        bytes_received: 0
    });

}

<|endoftext|>


<commit_before>#![allow(non_camel_case_types, non_upper_case_globals)]

pub extern crate libc;
pub extern crate wayland_commons;
pub extern crate wayland_server;
#[macro_use]
pub extern crate wayland_sys;

pub use wayland_sys::{
    gid_t, pid_t,
    server::{self, WAYLAND_SERVER_HANDLE},
    uid_t, *
};

#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
mod generated {
    use libc;
    include!("gen.rs");

    // XXX: If you add another protocols, take a look at wayland_protocol! macro
    // from `wayland-rs/wayland-protocols/src/protocol_macro.rs`.
    pub mod protocols {
        pub mod server_decoration {
            #![allow(unused_imports)]
            #![allow(unused_variables)]
            mod c_interfaces {
                use wayland_server::sys::protocol_interfaces::wl_surface_interface;
                include!(concat!(env!("OUT_DIR"), "/server_decoration_interfaces.rs"));
            }

            pub mod server {
                pub(crate) use wayland_commons::{
                    map::{Object, ObjectMetadata},
                    wire::{Argument, ArgumentType, Message, MessageDesc},
                    AnonymousObject, Interface, MessageGroup
                };
                use wayland_server::{protocol::wl_surface, *};
                pub(crate) use wayland_server::{NewResource, Resource};
                pub(crate) use wayland_sys as sys;
                use wayland_sys::common::{wl_argument, wl_interface};
                include!(concat!(env!("OUT_DIR"), "/server_decoration_server_api.rs"));
            }
        }
        pub mod idle {
            #![allow(unused_imports)]
            #![allow(unused_variables)]
            mod c_interfaces {
                use wayland_server::sys::protocol_interfaces::wl_seat_interface;
                include!(concat!(env!("OUT_DIR"), "/idle_interfaces.rs"));
            }

            pub mod server {
                pub(crate) use wayland_commons::{
                    map::{Object, ObjectMetadata},
                    wire::{Argument, ArgumentType, Message, MessageDesc},
                    AnonymousObject, Interface, MessageGroup
                };
                use wayland_server::{protocol::wl_seat, *};
                pub(crate) use wayland_server::{NewResource, Resource};
                pub(crate) use wayland_sys as sys;
                use wayland_sys::common::{wl_argument, wl_interface};
                include!(concat!(env!("OUT_DIR"), "/idle_server_api.rs"));
            }
        }

    }
}
pub use self::generated::*;

#[cfg(feature = "unstable")]
pub type wlr_output_events = self::generated::wlr_output__bindgen_ty_1;
#[cfg(feature = "unstable")]
pub type wlr_input_device_pointer = self::generated::wlr_input_device__bindgen_ty_1;

#[cfg(feature = "unstable")]
impl wl_output_transform {
    /// Returns the transform that, when composed with `self`, gives
    /// `WL_OUTPUT_TRANSFORM_NORMAL`.
    pub fn invert(self) -> Self {
        unsafe { wlr_output_transform_invert(self) }
    }

    /// Returns a transform that, when applied, has the same effect as applying
    /// sequentially `self` and `other`.
    pub fn compose(self, other: Self) -> Self {
        unsafe { wlr_output_transform_compose(self, other) }
    }
}
<commit_msg>Disable clippy for wlroots-sys<commit_after>#![allow(non_camel_case_types, non_upper_case_globals)]
#![allow(clippy::all)]

pub extern crate libc;
pub extern crate wayland_commons;
pub extern crate wayland_server;
#[macro_use]
pub extern crate wayland_sys;

pub use wayland_sys::{
    gid_t, pid_t,
    server::{self, WAYLAND_SERVER_HANDLE},
    uid_t, *
};

#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
mod generated {
    use libc;
    include!("gen.rs");

    // XXX: If you add another protocols, take a look at wayland_protocol! macro
    // from `wayland-rs/wayland-protocols/src/protocol_macro.rs`.
    pub mod protocols {
        pub mod server_decoration {
            #![allow(unused_imports)]
            #![allow(unused_variables)]
            mod c_interfaces {
                use wayland_server::sys::protocol_interfaces::wl_surface_interface;
                include!(concat!(env!("OUT_DIR"), "/server_decoration_interfaces.rs"));
            }

            pub mod server {
                pub(crate) use wayland_commons::{
                    map::{Object, ObjectMetadata},
                    wire::{Argument, ArgumentType, Message, MessageDesc},
                    AnonymousObject, Interface, MessageGroup
                };
                use wayland_server::{protocol::wl_surface, *};
                pub(crate) use wayland_server::{NewResource, Resource};
                pub(crate) use wayland_sys as sys;
                use wayland_sys::common::{wl_argument, wl_interface};
                include!(concat!(env!("OUT_DIR"), "/server_decoration_server_api.rs"));
            }
        }
        pub mod idle {
            #![allow(unused_imports)]
            #![allow(unused_variables)]
            mod c_interfaces {
                use wayland_server::sys::protocol_interfaces::wl_seat_interface;
                include!(concat!(env!("OUT_DIR"), "/idle_interfaces.rs"));
            }

            pub mod server {
                pub(crate) use wayland_commons::{
                    map::{Object, ObjectMetadata},
                    wire::{Argument, ArgumentType, Message, MessageDesc},
                    AnonymousObject, Interface, MessageGroup
                };
                use wayland_server::{protocol::wl_seat, *};
                pub(crate) use wayland_server::{NewResource, Resource};
                pub(crate) use wayland_sys as sys;
                use wayland_sys::common::{wl_argument, wl_interface};
                include!(concat!(env!("OUT_DIR"), "/idle_server_api.rs"));
            }
        }

    }
}
pub use self::generated::*;

#[cfg(feature = "unstable")]
pub type wlr_output_events = self::generated::wlr_output__bindgen_ty_1;
#[cfg(feature = "unstable")]
pub type wlr_input_device_pointer = self::generated::wlr_input_device__bindgen_ty_1;

#[cfg(feature = "unstable")]
impl wl_output_transform {
    /// Returns the transform that, when composed with `self`, gives
    /// `WL_OUTPUT_TRANSFORM_NORMAL`.
    pub fn invert(self) -> Self {
        unsafe { wlr_output_transform_invert(self) }
    }

    /// Returns a transform that, when applied, has the same effect as applying
    /// sequentially `self` and `other`.
    pub fn compose(self, other: Self) -> Self {
        unsafe { wlr_output_transform_compose(self, other) }
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Self::List) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::List) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    // ** Want/need to express a negative product here among Nil, Cons and Name!
    // fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `cons` and `nil` above:
    fn singleton (st:&mut A, hd:Hd) -> Self::List {
        let nil = Self::nil(st);
        Self::cons(st, hd, nil)
    }

    fn elim2<Res,Nil,Cons,Name> (&mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `elim` above:
    fn is_empty (st:&mut A, list:&Self::List) -> bool {
        Self::elim2(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

#[allow(dead_code)]
fn list_merge<A:Adapton,X:Ord+Clone,L:ListT<A,X>>
    (st:&mut A, l:&L,
     xo:Option<&X>, // xo is useful for merging binary trees.
     n1:Option<&A::Name>, l1:&L::List,
     n2:Option<&A::Name>, l2:&L::List  ) -> L::List
{
    L::elim2(st, l1,
            |_| l2.clone(),
            |st,h1,t1|
            L::elim2(st, l2,
                    |st| L::nil(st),
                    |st, h2, t2|
                    if match xo {
                        None => false,
                        Some(x) => ( x <= h1 && x <= h2 ) }
                    {
                        let rest = list_merge(st, l, None, n1, l1, n2, l2);
                        L::cons(st, xo.unwrap().clone(), rest)
                    }
                    else if h1 <= h2 {
                        //TODO: Nominal memoization with n1:
                        let rest = list_merge(st, l, xo, None, t1, n2, l2);
                        L::cons(st, (*h1).clone(), rest)
                    }
                    else {
                        //TODO: Nominal memoization with n2:
                        let rest = list_merge(st, l, xo, n1, l1, None, t2);
                        L::cons(st, (*h2).clone(), rest)
                    },
                    |st, m2, t2| list_merge(st, l, xo, n1, l1, Some(m2), t2)
                    ),
            |st,n1,t1| list_merge(st, l, xo, Some(n1), t1, n2, l2)
            )
}

fn list_merge_sort<A:Adapton,X:Ord+Hash+Clone,L:ListT<A,X>,T:TreeT<A,X,X>>
    (st:&mut A, l:&L, list:&L::List) -> L::List
{
    let tree = tree_of_list::<A,X,T,L>(st, list);
    T::fold_up (st, tree,
                |st, x|
                L::singleton(st, x),

                |st, x, left, right|
                list_merge(st, l, Some(&x), None, &left, None, &right)
                )
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                             -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Self::List)       -> Self::List { List::Cons(hd,Box::new(tl)) }
    fn name (_:&mut A, nm:A::Name, tl:Self::List)  -> Self::List { List::Name(nm, Box::new(tl)) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)          -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>) -> Self::List { List::Art(art) }

    // fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    // {
    //     match *list {
    //         List::Nil => nilf(st),
    //         List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
    //         List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
    //         List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
    //         List::Art(ref art) => {
    //             let list = st.force(art);
    //             self.elim(st, &list, nilf, consf, namef)
    //         }
    //     }
    // }

    fn elim2<Res,Nil,Cons,Name> (st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
            List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
            List::Rc(ref rc) => Self::elim2(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                Self::elim2(st, &list, nilf, consf, namef)
            }
        }
    }

}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    L::elim2 (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( L::is_empty( st, &rest ) );
    tree
}
<commit_msg>dropping xo param; its ugly<commit_after>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Self::List) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::List) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    // ** Want/need to express a negative product here among Nil, Cons and Name!
    // fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `cons` and `nil` above:
    fn singleton (st:&mut A, hd:Hd) -> Self::List {
        let nil = Self::nil(st);
        Self::cons(st, hd, nil)
    }

    fn elim2<Res,Nil,Cons,Name> (&mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `elim` above:
    fn is_empty (st:&mut A, list:&Self::List) -> bool {
        Self::elim2(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

#[allow(dead_code)]
pub fn list_merge<A:Adapton,X:Ord+Clone,L:ListT<A,X>>
    (st:&mut A,
     xo:Option<&X>, // xo is useful for merging binary trees.
     n1:Option<&A::Name>, l1:&L::List,
     n2:Option<&A::Name>, l2:&L::List  ) -> L::List
{
    L::elim2(st, l1,
             |_| l2.clone(),
             |st,h1,t1|
             L::elim2(st, l2,
                      |st| L::nil(st),
                      |st, h2, t2|
                      if match xo {
                          None => false,
                          Some(x) => ( x <= h1 && x <= h2 ) }
                      {
                          let rest = list_merge::<A,X,L>(st, None, n1, l1, n2, l2);
                          L::cons(st, xo.unwrap().clone(), rest)
                      }
                      else if h1 <= h2 {
                          //TODO: Nominal memoization with n1:
                          let rest = list_merge::<A,X,L>(st, xo, None, t1, n2, l2);
                          L::cons(st, (*h1).clone(), rest)
                      }
                      else {
                          //TODO: Nominal memoization with n2:
                          let rest = list_merge::<A,X,L>(st, xo, n1, l1, None, t2);
                          L::cons(st, (*h2).clone(), rest)
                      },
                      |st, m2, t2| list_merge::<A,X,L>(st, xo, n1, l1, Some(m2), t2)
                      ),
             |st,n1,t1| list_merge::<A,X,L>(st, xo, Some(n1), t1, n2, l2)
             )
}

pub fn list_merge_sort<A:Adapton,X:Ord+Hash+Clone,L:ListT<A,X>,T:TreeT<A,X,X>>
    (st:&mut A, list:&L::List) -> L::List
{
    let tree = tree_of_list::<A,X,T,L>(st, list);
    T::fold_up (st, tree,
                |st, x| // Nil:
                L::singleton(st, x),
                |st, x, left, right| {
                    let left = L::cons(st, x,left);
                    list_merge::<A,X,L>(st, None, None, &left, None, &right)
                }
                )
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                             -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Self::List)       -> Self::List { List::Cons(hd,Box::new(tl)) }
    fn name (_:&mut A, nm:A::Name, tl:Self::List)  -> Self::List { List::Name(nm, Box::new(tl)) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)          -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>) -> Self::List { List::Art(art) }

    // fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    // {
    //     match *list {
    //         List::Nil => nilf(st),
    //         List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
    //         List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
    //         List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
    //         List::Art(ref art) => {
    //             let list = st.force(art);
    //             self.elim(st, &list, nilf, consf, namef)
    //         }
    //     }
    // }

    fn elim2<Res,Nil,Cons,Name> (st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
            List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
            List::Rc(ref rc) => Self::elim2(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                Self::elim2(st, &list, nilf, consf, namef)
            }
        }
    }

}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    L::elim2 (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( L::is_empty( st, &rest ) );
    tree
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from `elim` above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let $( $arg ),* = args ;
//                 f(st, l, list, left_tree, left_tree_lev, parent_lev)
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree, right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree, rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                // Done: Memoized the recursive calls to tree_of_list_rec.
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree, right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree, rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<commit_msg>stuck, due to rustc not understanding that elim is a pattern-match; its arms are mutually-exclusive<commit_after>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    // ** Want/need to express a negative product here among Nil, Cons and Name!
    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from `elim` above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let $( $arg ),* = args ;
//                 f(st, l, list, left_tree, left_tree_lev, parent_lev)
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree, right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree, rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                // Done: Memoized the recursive calls to tree_of_list_rec.
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree, right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree, rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Boden Garman <bpgarman@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) fpath

#[macro_use]
extern crate uucore;

mod count_bytes;
mod countable;
mod wordcount;
use count_bytes::count_bytes_fast;
use countable::WordCountable;
use wordcount::{TitledWordCount, WordCount};

use clap::{App, Arg, ArgMatches};
use thiserror::Error;

use std::fs::{self, File};
use std::io::{self, ErrorKind, Write};
use std::path::Path;

/// The minimum character width for formatting counts when reading from stdin.
const MINIMUM_WIDTH: usize = 7;

#[derive(Error, Debug)]
pub enum WcError {
    #[error("{0}")]
    Io(#[from] io::Error),
    #[error("Expected a file, found directory {0}")]
    IsDirectory(String),
}

type WcResult<T> = Result<T, WcError>;

struct Settings {
    show_bytes: bool,
    show_chars: bool,
    show_lines: bool,
    show_words: bool,
    show_max_line_length: bool,
}

impl Settings {
    fn new(matches: &ArgMatches) -> Settings {
        let settings = Settings {
            show_bytes: matches.is_present(options::BYTES),
            show_chars: matches.is_present(options::CHAR),
            show_lines: matches.is_present(options::LINES),
            show_words: matches.is_present(options::WORDS),
            show_max_line_length: matches.is_present(options::MAX_LINE_LENGTH),
        };

        if settings.show_bytes
            || settings.show_chars
            || settings.show_lines
            || settings.show_words
            || settings.show_max_line_length
        {
            return settings;
        }

        Settings {
            show_bytes: true,
            show_chars: false,
            show_lines: true,
            show_words: true,
            show_max_line_length: false,
        }
    }

    fn number_enabled(&self) -> u32 {
        let mut result = 0;
        result += self.show_bytes as u32;
        result += self.show_chars as u32;
        result += self.show_lines as u32;
        result += self.show_max_line_length as u32;
        result += self.show_words as u32;
        result
    }
}

static ABOUT: &str = "Display newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified.";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub mod options {
    pub static BYTES: &str = "bytes";
    pub static CHAR: &str = "chars";
    pub static LINES: &str = "lines";
    pub static MAX_LINE_LENGTH: &str = "max-line-length";
    pub static WORDS: &str = "words";
}

static ARG_FILES: &str = "files";

fn get_usage() -> String {
    format!(
        "{0} [OPTION]... [FILE]...
 With no FILE, or when FILE is -, read standard input.",
        executable!()
    )
}

enum StdinKind {
    /// Stdin specified on command-line with "-".
    Explicit,

    /// Stdin implicitly specified on command-line by not passing any positional argument.
    Implicit,
}

/// Supported inputs.
enum Input {
    /// A regular file.
    Path(String),

    /// Standard input.
    Stdin(StdinKind),
}

impl Input {
    /// Converts input to title that appears in stats.
    fn to_title(&self) -> Option<&str> {
        match self {
            Input::Path(path) => Some(path),
            Input::Stdin(StdinKind::Explicit) => Some("-"),
            Input::Stdin(StdinKind::Implicit) => None,
        }
    }
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(options::BYTES)
                .short("c")
                .long(options::BYTES)
                .help("print the byte counts"),
        )
        .arg(
            Arg::with_name(options::CHAR)
                .short("m")
                .long(options::CHAR)
                .help("print the character counts"),
        )
        .arg(
            Arg::with_name(options::LINES)
                .short("l")
                .long(options::LINES)
                .help("print the newline counts"),
        )
        .arg(
            Arg::with_name(options::MAX_LINE_LENGTH)
                .short("L")
                .long(options::MAX_LINE_LENGTH)
                .help("print the length of the longest line"),
        )
        .arg(
            Arg::with_name(options::WORDS)
                .short("w")
                .long(options::WORDS)
                .help("print the word counts"),
        )
        .arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
        .get_matches_from(args);

    let mut inputs: Vec<Input> = matches
        .values_of(ARG_FILES)
        .map(|v| {
            v.map(|i| {
                if i == "-" {
                    Input::Stdin(StdinKind::Explicit)
                } else {
                    Input::Path(ToString::to_string(i))
                }
            })
            .collect()
        })
        .unwrap_or_default();

    if inputs.is_empty() {
        inputs.push(Input::Stdin(StdinKind::Implicit));
    }

    let settings = Settings::new(&matches);

    if wc(inputs, &settings).is_ok() {
        0
    } else {
        1
    }
}

fn word_count_from_reader<T: WordCountable>(
    mut reader: T,
    settings: &Settings,
    path: &str,
) -> WcResult<WordCount> {
    let only_count_bytes = settings.show_bytes
        && (!(settings.show_chars
            || settings.show_lines
            || settings.show_max_line_length
            || settings.show_words));
    if only_count_bytes {
        return Ok(WordCount {
            bytes: count_bytes_fast(&mut reader)?,
            ..WordCount::default()
        });
    }

    // we do not need to decode the byte stream if we're only counting bytes/newlines
    let decode_chars = settings.show_chars || settings.show_words || settings.show_max_line_length;

    // Sum the WordCount for each line. Show a warning for each line
    // that results in an IO error when trying to read it.
    let total = reader
        .lines()
        .filter_map(|res| match res {
            Ok(line) => Some(line),
            Err(e) => {
                show_warning!("Error while reading {}: {}", path, e);
                None
            }
        })
        .map(|line| WordCount::from_line(&line, decode_chars))
        .sum();
    Ok(total)
}

fn word_count_from_input(input: &Input, settings: &Settings) -> WcResult<WordCount> {
    match input {
        Input::Stdin(_) => {
            let stdin = io::stdin();
            let stdin_lock = stdin.lock();
            word_count_from_reader(stdin_lock, settings, "-")
        }
        Input::Path(path) => {
            let path_obj = Path::new(path);
            if path_obj.is_dir() {
                Err(WcError::IsDirectory(path.to_owned()))
            } else {
                let file = File::open(path)?;
                word_count_from_reader(file, settings, path)
            }
        }
    }
}

/// Print a message appropriate for the particular error to `stderr`.
///
/// # Examples
///
/// This will print `wc: /tmp: Is a directory` to `stderr`.
///
/// ```rust,ignore
/// show_error(Input::Path("/tmp"), WcError::IsDirectory("/tmp"))
/// ```
fn show_error(input: &Input, err: WcError) {
    match (input, err) {
        (_, WcError::IsDirectory(path)) => {
            show_error_custom_description!(path, "Is a directory");
        }
        (Input::Path(path), WcError::Io(e)) if e.kind() == ErrorKind::NotFound => {
            show_error_custom_description!(path, "No such file or directory");
        }
        (_, e) => {
            show_error!("{}", e);
        }
    };
}

/// Compute the number of digits needed to represent any count for this input.
///
/// If `input` is [`Input::Stdin`], then this function returns
/// [`MINIMUM_WIDTH`]. Otherwise, if metadata could not be read from
/// `input` then this function returns 1.
///
/// # Errors
///
/// This function will return an error if `input` is a [`Input::Path`]
/// and there is a problem accessing the metadata of the given `input`.
///
/// # Examples
///
/// A [`Input::Stdin`] gets a default minimum width:
///
/// ```rust,ignore
/// let input = Input::Stdin(StdinKind::Explicit);
/// assert_eq!(7, digit_width(input));
/// ```
fn digit_width(input: &Input) -> WcResult<Option<usize>> {
    match input {
        Input::Stdin(_) => Ok(Some(MINIMUM_WIDTH)),
        Input::Path(filename) => {
            let path = Path::new(filename);
            let metadata = fs::metadata(path)?;
            if metadata.is_file() {
                // TODO We are now computing the number of bytes in a file
                // twice: once here and once in `WordCount::from_line()` (or
                // in `count_bytes_fast()` if that function is called
                // instead). See GitHub issue #2201.
                let num_bytes = metadata.len();
                let num_digits = num_bytes.to_string().len();
                Ok(Some(num_digits))
            } else {
                Ok(None)
            }
        }
    }
}

/// Compute the number of digits needed to represent all counts in all inputs.
///
/// `inputs` may include zero or more [`Input::Stdin`] entries, each of
/// which represents reading from `stdin`. The presence of any such
/// entry causes this function to return a width that is at least
/// [`MINIMUM_WIDTH`].
///
/// If `input` is empty, then this function returns 1. If file metadata
/// could not be read from any of the [`Input::Path`] inputs and there
/// are no [`Input::Stdin`] inputs, then this function returns 1.
///
/// If there is a problem accessing the metadata, this function will
/// silently ignore the error and assume that the number of digits
/// needed to display the counts for that file is 1.
///
/// # Examples
///
/// An empty slice implies a width of 1:
///
/// ```rust,ignore
/// assert_eq!(1, max_width(&vec![]));
/// ```
///
/// The presence of [`Input::Stdin`] implies a minimum width:
///
/// ```rust,ignore
/// let inputs = vec![Input::Stdin(StdinKind::Explicit)];
/// assert_eq!(7, max_width(&inputs));
/// ```
fn max_width(inputs: &[Input]) -> usize {
    let mut result = 1;
    for input in inputs {
        match digit_width(input) {
            Ok(maybe_n) => {
                if let Some(n) = maybe_n {
                    result = result.max(n);
                }
            }
            Err(_) => continue,
        }
    }
    result
}

fn wc(inputs: Vec<Input>, settings: &Settings) -> Result<(), u32> {
    // Compute the width, in digits, to use when formatting counts.
    //
    // The width is the number of digits needed to print the number of
    // bytes in the largest file. This is true regardless of whether
    // the `settings` indicate that the bytes will be displayed.
    let mut error_count = 0;
    let max_width = max_width(&inputs);

    let mut total_word_count = WordCount::default();
    let mut results = vec![];

    let num_inputs = inputs.len();

    for input in &inputs {
        let word_count = word_count_from_input(&input, settings).unwrap_or_else(|err| {
            show_error(&input, err);
            error_count += 1;
            WordCount::default()
        });
        total_word_count += word_count;
        results.push(word_count.with_title(input.to_title()));
    }

    for result in &results {
        if let Err(err) = print_stats(settings, &result, max_width) {
            show_warning!(
                "failed to print result for {}: {}",
                result.title.unwrap_or("<stdin>"),
                err
            );
            error_count += 1;
        }
    }

    if num_inputs > 1 {
        let total_result = total_word_count.with_title(Some("total"));
        if let Err(err) = print_stats(settings, &total_result, max_width) {
            show_warning!("failed to print total: {}", err);
            error_count += 1;
        }
    }

    if error_count == 0 {
        Ok(())
    } else {
        Err(error_count)
    }
}

fn print_stats(
    settings: &Settings,
    result: &TitledWordCount,
    mut min_width: usize,
) -> WcResult<()> {
    let stdout = io::stdout();
    let mut stdout_lock = stdout.lock();

    if settings.number_enabled() <= 1 {
        // Prevent a leading space in case we only need to display a single
        // number.
        min_width = 0;
    }

    let mut is_first: bool = true;

    if settings.show_lines {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.lines, min_width)?;
        is_first = false;
    }
    if settings.show_words {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.words, min_width)?;
        is_first = false;
    }
    if settings.show_bytes {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.bytes, min_width)?;
        is_first = false;
    }
    if settings.show_chars {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.chars, min_width)?;
        is_first = false;
    }
    if settings.show_max_line_length {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(
            stdout_lock,
            "{:1$}",
            result.count.max_line_length, min_width
        )?;
    }

    if let Some(title) = result.title {
        writeln!(stdout_lock, " {}", title)?;
    } else {
        writeln!(stdout_lock)?;
    }

    Ok(())
}
<commit_msg>wc: print counts for each file as soon as computed<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Boden Garman <bpgarman@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) fpath

#[macro_use]
extern crate uucore;

mod count_bytes;
mod countable;
mod wordcount;
use count_bytes::count_bytes_fast;
use countable::WordCountable;
use wordcount::{TitledWordCount, WordCount};

use clap::{App, Arg, ArgMatches};
use thiserror::Error;

use std::fs::{self, File};
use std::io::{self, ErrorKind, Write};
use std::path::Path;

/// The minimum character width for formatting counts when reading from stdin.
const MINIMUM_WIDTH: usize = 7;

#[derive(Error, Debug)]
pub enum WcError {
    #[error("{0}")]
    Io(#[from] io::Error),
    #[error("Expected a file, found directory {0}")]
    IsDirectory(String),
}

type WcResult<T> = Result<T, WcError>;

struct Settings {
    show_bytes: bool,
    show_chars: bool,
    show_lines: bool,
    show_words: bool,
    show_max_line_length: bool,
}

impl Settings {
    fn new(matches: &ArgMatches) -> Settings {
        let settings = Settings {
            show_bytes: matches.is_present(options::BYTES),
            show_chars: matches.is_present(options::CHAR),
            show_lines: matches.is_present(options::LINES),
            show_words: matches.is_present(options::WORDS),
            show_max_line_length: matches.is_present(options::MAX_LINE_LENGTH),
        };

        if settings.show_bytes
            || settings.show_chars
            || settings.show_lines
            || settings.show_words
            || settings.show_max_line_length
        {
            return settings;
        }

        Settings {
            show_bytes: true,
            show_chars: false,
            show_lines: true,
            show_words: true,
            show_max_line_length: false,
        }
    }

    fn number_enabled(&self) -> u32 {
        let mut result = 0;
        result += self.show_bytes as u32;
        result += self.show_chars as u32;
        result += self.show_lines as u32;
        result += self.show_max_line_length as u32;
        result += self.show_words as u32;
        result
    }
}

static ABOUT: &str = "Display newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified.";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub mod options {
    pub static BYTES: &str = "bytes";
    pub static CHAR: &str = "chars";
    pub static LINES: &str = "lines";
    pub static MAX_LINE_LENGTH: &str = "max-line-length";
    pub static WORDS: &str = "words";
}

static ARG_FILES: &str = "files";

fn get_usage() -> String {
    format!(
        "{0} [OPTION]... [FILE]...
 With no FILE, or when FILE is -, read standard input.",
        executable!()
    )
}

enum StdinKind {
    /// Stdin specified on command-line with "-".
    Explicit,

    /// Stdin implicitly specified on command-line by not passing any positional argument.
    Implicit,
}

/// Supported inputs.
enum Input {
    /// A regular file.
    Path(String),

    /// Standard input.
    Stdin(StdinKind),
}

impl Input {
    /// Converts input to title that appears in stats.
    fn to_title(&self) -> Option<&str> {
        match self {
            Input::Path(path) => Some(path),
            Input::Stdin(StdinKind::Explicit) => Some("-"),
            Input::Stdin(StdinKind::Implicit) => None,
        }
    }
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(options::BYTES)
                .short("c")
                .long(options::BYTES)
                .help("print the byte counts"),
        )
        .arg(
            Arg::with_name(options::CHAR)
                .short("m")
                .long(options::CHAR)
                .help("print the character counts"),
        )
        .arg(
            Arg::with_name(options::LINES)
                .short("l")
                .long(options::LINES)
                .help("print the newline counts"),
        )
        .arg(
            Arg::with_name(options::MAX_LINE_LENGTH)
                .short("L")
                .long(options::MAX_LINE_LENGTH)
                .help("print the length of the longest line"),
        )
        .arg(
            Arg::with_name(options::WORDS)
                .short("w")
                .long(options::WORDS)
                .help("print the word counts"),
        )
        .arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
        .get_matches_from(args);

    let mut inputs: Vec<Input> = matches
        .values_of(ARG_FILES)
        .map(|v| {
            v.map(|i| {
                if i == "-" {
                    Input::Stdin(StdinKind::Explicit)
                } else {
                    Input::Path(ToString::to_string(i))
                }
            })
            .collect()
        })
        .unwrap_or_default();

    if inputs.is_empty() {
        inputs.push(Input::Stdin(StdinKind::Implicit));
    }

    let settings = Settings::new(&matches);

    if wc(inputs, &settings).is_ok() {
        0
    } else {
        1
    }
}

fn word_count_from_reader<T: WordCountable>(
    mut reader: T,
    settings: &Settings,
    path: &str,
) -> WcResult<WordCount> {
    let only_count_bytes = settings.show_bytes
        && (!(settings.show_chars
            || settings.show_lines
            || settings.show_max_line_length
            || settings.show_words));
    if only_count_bytes {
        return Ok(WordCount {
            bytes: count_bytes_fast(&mut reader)?,
            ..WordCount::default()
        });
    }

    // we do not need to decode the byte stream if we're only counting bytes/newlines
    let decode_chars = settings.show_chars || settings.show_words || settings.show_max_line_length;

    // Sum the WordCount for each line. Show a warning for each line
    // that results in an IO error when trying to read it.
    let total = reader
        .lines()
        .filter_map(|res| match res {
            Ok(line) => Some(line),
            Err(e) => {
                show_warning!("Error while reading {}: {}", path, e);
                None
            }
        })
        .map(|line| WordCount::from_line(&line, decode_chars))
        .sum();
    Ok(total)
}

fn word_count_from_input(input: &Input, settings: &Settings) -> WcResult<WordCount> {
    match input {
        Input::Stdin(_) => {
            let stdin = io::stdin();
            let stdin_lock = stdin.lock();
            word_count_from_reader(stdin_lock, settings, "-")
        }
        Input::Path(path) => {
            let path_obj = Path::new(path);
            if path_obj.is_dir() {
                Err(WcError::IsDirectory(path.to_owned()))
            } else {
                let file = File::open(path)?;
                word_count_from_reader(file, settings, path)
            }
        }
    }
}

/// Print a message appropriate for the particular error to `stderr`.
///
/// # Examples
///
/// This will print `wc: /tmp: Is a directory` to `stderr`.
///
/// ```rust,ignore
/// show_error(Input::Path("/tmp"), WcError::IsDirectory("/tmp"))
/// ```
fn show_error(input: &Input, err: WcError) {
    match (input, err) {
        (_, WcError::IsDirectory(path)) => {
            show_error_custom_description!(path, "Is a directory");
        }
        (Input::Path(path), WcError::Io(e)) if e.kind() == ErrorKind::NotFound => {
            show_error_custom_description!(path, "No such file or directory");
        }
        (_, e) => {
            show_error!("{}", e);
        }
    };
}

/// Compute the number of digits needed to represent any count for this input.
///
/// If `input` is [`Input::Stdin`], then this function returns
/// [`MINIMUM_WIDTH`]. Otherwise, if metadata could not be read from
/// `input` then this function returns 1.
///
/// # Errors
///
/// This function will return an error if `input` is a [`Input::Path`]
/// and there is a problem accessing the metadata of the given `input`.
///
/// # Examples
///
/// A [`Input::Stdin`] gets a default minimum width:
///
/// ```rust,ignore
/// let input = Input::Stdin(StdinKind::Explicit);
/// assert_eq!(7, digit_width(input));
/// ```
fn digit_width(input: &Input) -> WcResult<Option<usize>> {
    match input {
        Input::Stdin(_) => Ok(Some(MINIMUM_WIDTH)),
        Input::Path(filename) => {
            let path = Path::new(filename);
            let metadata = fs::metadata(path)?;
            if metadata.is_file() {
                // TODO We are now computing the number of bytes in a file
                // twice: once here and once in `WordCount::from_line()` (or
                // in `count_bytes_fast()` if that function is called
                // instead). See GitHub issue #2201.
                let num_bytes = metadata.len();
                let num_digits = num_bytes.to_string().len();
                Ok(Some(num_digits))
            } else {
                Ok(None)
            }
        }
    }
}

/// Compute the number of digits needed to represent all counts in all inputs.
///
/// `inputs` may include zero or more [`Input::Stdin`] entries, each of
/// which represents reading from `stdin`. The presence of any such
/// entry causes this function to return a width that is at least
/// [`MINIMUM_WIDTH`].
///
/// If `input` is empty, then this function returns 1. If file metadata
/// could not be read from any of the [`Input::Path`] inputs and there
/// are no [`Input::Stdin`] inputs, then this function returns 1.
///
/// If there is a problem accessing the metadata, this function will
/// silently ignore the error and assume that the number of digits
/// needed to display the counts for that file is 1.
///
/// # Examples
///
/// An empty slice implies a width of 1:
///
/// ```rust,ignore
/// assert_eq!(1, max_width(&vec![]));
/// ```
///
/// The presence of [`Input::Stdin`] implies a minimum width:
///
/// ```rust,ignore
/// let inputs = vec![Input::Stdin(StdinKind::Explicit)];
/// assert_eq!(7, max_width(&inputs));
/// ```
fn max_width(inputs: &[Input]) -> usize {
    let mut result = 1;
    for input in inputs {
        match digit_width(input) {
            Ok(maybe_n) => {
                if let Some(n) = maybe_n {
                    result = result.max(n);
                }
            }
            Err(_) => continue,
        }
    }
    result
}

fn wc(inputs: Vec<Input>, settings: &Settings) -> Result<(), u32> {
    // Compute the width, in digits, to use when formatting counts.
    //
    // The width is the number of digits needed to print the number of
    // bytes in the largest file. This is true regardless of whether
    // the `settings` indicate that the bytes will be displayed.
    let mut error_count = 0;
    let max_width = max_width(&inputs);

    let mut total_word_count = WordCount::default();

    let num_inputs = inputs.len();

    for input in &inputs {
        let word_count = word_count_from_input(&input, settings).unwrap_or_else(|err| {
            show_error(&input, err);
            error_count += 1;
            WordCount::default()
        });
        total_word_count += word_count;
        let result = word_count.with_title(input.to_title());
        if let Err(err) = print_stats(settings, &result, max_width) {
            show_warning!(
                "failed to print result for {}: {}",
                result.title.unwrap_or("<stdin>"),
                err
            );
            error_count += 1;
        }
    }

    if num_inputs > 1 {
        let total_result = total_word_count.with_title(Some("total"));
        if let Err(err) = print_stats(settings, &total_result, max_width) {
            show_warning!("failed to print total: {}", err);
            error_count += 1;
        }
    }

    if error_count == 0 {
        Ok(())
    } else {
        Err(error_count)
    }
}

fn print_stats(
    settings: &Settings,
    result: &TitledWordCount,
    mut min_width: usize,
) -> WcResult<()> {
    let stdout = io::stdout();
    let mut stdout_lock = stdout.lock();

    if settings.number_enabled() <= 1 {
        // Prevent a leading space in case we only need to display a single
        // number.
        min_width = 0;
    }

    let mut is_first: bool = true;

    if settings.show_lines {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.lines, min_width)?;
        is_first = false;
    }
    if settings.show_words {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.words, min_width)?;
        is_first = false;
    }
    if settings.show_bytes {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.bytes, min_width)?;
        is_first = false;
    }
    if settings.show_chars {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(stdout_lock, "{:1$}", result.count.chars, min_width)?;
        is_first = false;
    }
    if settings.show_max_line_length {
        if !is_first {
            write!(stdout_lock, " ")?;
        }
        write!(
            stdout_lock,
            "{:1$}",
            result.count.max_line_length, min_width
        )?;
    }

    if let Some(title) = result.title {
        writeln!(stdout_lock, " {}", title)?;
    } else {
        writeln!(stdout_lock)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult};
use vec::Vec2;
use view::View;

/// A blank view that forwards calls to closures.
///
/// You can use this view to easily draw your own interface.
pub struct Canvas<T> {
    state: T,

    draw: Box<Fn(&Printer, &T)>,
    on_event: Box<FnMut(Event, &mut T) -> EventResult>,
    get_min_size: Box<FnMut(Vec2, &mut T) -> Vec2>,
    layout: Box<FnMut(Vec2, &mut T)>,
    take_focus: Box<FnMut(Direction, &mut T) -> bool>,
}

impl<T> Canvas<T> {
    /// Creates a new, empty Canvas.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let canvas = Canvas::new(())
    ///                     .with_draw(|printer, _| {
    ///                         // Print the view
    ///                     });
    /// ```
    pub fn new(state: T) -> Self {
        Canvas {
            state: state,
            draw: Box::new(|_, _| ()),
            on_event: Box::new(|_, _| EventResult::Ignored),
            get_min_size: Box::new(|_, _| Vec2::new(1, 1)),
            layout: Box::new(|_, _| ()),
            take_focus: Box::new(|_, _| false),
        }
    }

    /// Sets the closure for `draw(&Printer)`
    pub fn set_draw<F>(&mut self, f: F)
        where F: 'static + Fn(&Printer, &T)
    {
        self.draw = Box::new(f);
    }

    /// Sets the closure for `draw(&Printer)`
    ///
    /// Chainable variant.
    pub fn with_draw<F>(self, f: F) -> Self
        where F: 'static + Fn(&Printer, &T)
    {
        self.with(|s| s.set_draw(f))
    }

    /// Sets the closure for `on_event(Event)`
    pub fn set_on_event<F>(&mut self, f: F)
        where F: 'static + FnMut(Event, &mut T) -> EventResult
    {
        self.on_event = Box::new(f);
    }

    /// Sets the closure for `on_event(Event)`
    ///
    /// Chainable variant.
    pub fn with_on_event<F>(self, f: F) -> Self
        where F: 'static + FnMut(Event, &mut T) -> EventResult
    {
        self.with(|s| s.set_on_event(f))
    }

    /// Sets the closure for `get_min_size(Vec2)`
    pub fn set_get_min_size<F>(&mut self, f: F)
        where F: 'static + FnMut(Vec2, &mut T) -> Vec2
    {
        self.get_min_size = Box::new(f);
    }

    /// Sets the closure for `get_min_size(Vec2)`
    ///
    /// Chainable variant.
    pub fn with_get_min_size<F>(self, f: F) -> Self
        where F: 'static + FnMut(Vec2, &mut T) -> Vec2
    {
        self.with(|s| s.set_get_min_size(f))
    }

    /// Sets the closure for `layout(Vec2)`
    pub fn set_layout<F>(&mut self, f: F)
        where F: 'static + FnMut(Vec2, &mut T)
    {
        self.layout = Box::new(f);
    }

    /// Sets the closure for `layout(Vec2)`
    ///
    /// Chainable variant.
    pub fn with_layout<F>(self, f: F) -> Self
        where F: 'static + FnMut(Vec2, &mut T)
    {
        self.with(|s| s.set_layout(f))
    }

    /// Sets the closure for `take_focus(Direction)`
    pub fn set_take_focus<F>(&mut self, f: F)
        where F: 'static + FnMut(Direction, &mut T) -> bool
    {
        self.take_focus = Box::new(f);
    }

    /// Sets the closure for `take_focus(Direction)`
    ///
    /// Chainable variant.
    pub fn with_take_focus<F>(self, f: F) -> Self
        where F: 'static + FnMut(Direction, &mut T) -> bool
    {
        self.with(|s| s.set_take_focus(f))
    }
}

impl <T> View for Canvas<T> {
    fn draw(&self, printer: &Printer) {
        (self.draw)(printer, &self.state);
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        (self.on_event)(event, &mut self.state)
    }

    fn get_min_size(&mut self, constraint: Vec2) -> Vec2 {
        (self.get_min_size)(constraint, &mut self.state)
    }

    fn layout(&mut self, size: Vec2) {
        (self.layout)(size, &mut self.state);
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        (self.take_focus)(source, &mut self.state)
    }
}
<commit_msg>Fix Canvas doc comment<commit_after>use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult};
use vec::Vec2;
use view::View;

/// A blank view that forwards calls to closures.
///
/// You can use this view to easily draw your own interface.
pub struct Canvas<T> {
    state: T,

    draw: Box<Fn(&Printer, &T)>,
    on_event: Box<FnMut(Event, &mut T) -> EventResult>,
    get_min_size: Box<FnMut(Vec2, &mut T) -> Vec2>,
    layout: Box<FnMut(Vec2, &mut T)>,
    take_focus: Box<FnMut(Direction, &mut T) -> bool>,
}

impl<T> Canvas<T> {
    /// Creates a new, empty Canvas.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cursive::views::Canvas;
    /// let canvas = Canvas::new(())
    ///                     .with_draw(|printer, _| {
    ///                         // Print the view
    ///                     });
    /// ```
    pub fn new(state: T) -> Self {
        Canvas {
            state: state,
            draw: Box::new(|_, _| ()),
            on_event: Box::new(|_, _| EventResult::Ignored),
            get_min_size: Box::new(|_, _| Vec2::new(1, 1)),
            layout: Box::new(|_, _| ()),
            take_focus: Box::new(|_, _| false),
        }
    }

    /// Sets the closure for `draw(&Printer)`
    pub fn set_draw<F>(&mut self, f: F)
        where F: 'static + Fn(&Printer, &T)
    {
        self.draw = Box::new(f);
    }

    /// Sets the closure for `draw(&Printer)`
    ///
    /// Chainable variant.
    pub fn with_draw<F>(self, f: F) -> Self
        where F: 'static + Fn(&Printer, &T)
    {
        self.with(|s| s.set_draw(f))
    }

    /// Sets the closure for `on_event(Event)`
    pub fn set_on_event<F>(&mut self, f: F)
        where F: 'static + FnMut(Event, &mut T) -> EventResult
    {
        self.on_event = Box::new(f);
    }

    /// Sets the closure for `on_event(Event)`
    ///
    /// Chainable variant.
    pub fn with_on_event<F>(self, f: F) -> Self
        where F: 'static + FnMut(Event, &mut T) -> EventResult
    {
        self.with(|s| s.set_on_event(f))
    }

    /// Sets the closure for `get_min_size(Vec2)`
    pub fn set_get_min_size<F>(&mut self, f: F)
        where F: 'static + FnMut(Vec2, &mut T) -> Vec2
    {
        self.get_min_size = Box::new(f);
    }

    /// Sets the closure for `get_min_size(Vec2)`
    ///
    /// Chainable variant.
    pub fn with_get_min_size<F>(self, f: F) -> Self
        where F: 'static + FnMut(Vec2, &mut T) -> Vec2
    {
        self.with(|s| s.set_get_min_size(f))
    }

    /// Sets the closure for `layout(Vec2)`
    pub fn set_layout<F>(&mut self, f: F)
        where F: 'static + FnMut(Vec2, &mut T)
    {
        self.layout = Box::new(f);
    }

    /// Sets the closure for `layout(Vec2)`
    ///
    /// Chainable variant.
    pub fn with_layout<F>(self, f: F) -> Self
        where F: 'static + FnMut(Vec2, &mut T)
    {
        self.with(|s| s.set_layout(f))
    }

    /// Sets the closure for `take_focus(Direction)`
    pub fn set_take_focus<F>(&mut self, f: F)
        where F: 'static + FnMut(Direction, &mut T) -> bool
    {
        self.take_focus = Box::new(f);
    }

    /// Sets the closure for `take_focus(Direction)`
    ///
    /// Chainable variant.
    pub fn with_take_focus<F>(self, f: F) -> Self
        where F: 'static + FnMut(Direction, &mut T) -> bool
    {
        self.with(|s| s.set_take_focus(f))
    }
}

impl <T> View for Canvas<T> {
    fn draw(&self, printer: &Printer) {
        (self.draw)(printer, &self.state);
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        (self.on_event)(event, &mut self.state)
    }

    fn get_min_size(&mut self, constraint: Vec2) -> Vec2 {
        (self.get_min_size)(constraint, &mut self.state)
    }

    fn layout(&mut self, size: Vec2) {
        (self.layout)(size, &mut self.state);
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        (self.take_focus)(source, &mut self.state)
    }
}
<|endoftext|>