<commit_before>// Copyright (c) 2013-2104 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;
use std::num::Zero;
use std::num::from_int;
use std::char::from_u32;
use regex::Regex;
use num::bigint::BigInt;

const A: uint = 'A' as uint;
const J: uint = 'J' as uint;
const Q: uint = 'Q' as uint;
const K: uint = 'K' as uint;
const D: uint = '♦' as uint;
const H: uint = '♥' as uint;
const S: uint = '♠' as uint;
const C: uint = '♣' as uint;

struct Card {
    rank: uint,
    suit: uint
}

struct Ante {
    pc:     uint,                   // Program counter (index within ante.code)
    line:   uint,                   // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<uint, BigInt>,  // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
}

impl Ante {
    fn new(filename: &str) -> Ante {
        let mut vars: HashMap<uint, BigInt> = HashMap::new();
        vars.insert(D, Ante::big(0));
        vars.insert(H, Ante::big(0));
        vars.insert(S, Ante::big(0));
        vars.insert(C, Ante::big(0));

        let code = Ante::parse(filename);
        let labels = Ante::resolve(&code);

        Ante {
            pc:     0,
            line:   0,
            code:   code,
            vars:   vars,
            labels: labels
        }
    }

    fn run(&mut self) -> &Ante {
        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            self.pc += 1;
            match card.rank {
                0u  => self.newline(card),
                K   => self.jump(card),
                Q   => continue,
                J   => self.dump(card, true),
                10u => self.dump(card, false),
                _   => self.assign(card)
            };
        }
        self
    }

    // Turn source file into array of cards.
    fn parse(filename: &str) -> Vec<Card> {
        let mut file = File::open(&Path::new(filename));
        let program = file.read_to_string().unwrap();

        // Split program blob into lines getting rid of comments and whitespaces.
        let comments = Regex::new(r"#.*$").unwrap();
        let lines: Vec<String> = program.as_slice().lines().map( |line|
            comments.replace_all(line, "").as_slice().trim().to_string()
        ).collect();

        // Turn source file into array of cards. Each card a struct of rank and suit.
        let mut code: Vec<Card> = vec![];
        let card = Regex::new(r"(10|[2-9JQKA])([♦♥♠♣])").unwrap();
        for (i, line) in lines.iter().enumerate() {
            // Line number cards have zero rank.
            code.push(Card { rank: 0, suit: i + 1 });

            // Parse cards using regural expression.
            for caps in card.captures_iter(line.as_slice()) {
                let rank = caps.at(1).char_at(0);
                let suit = caps.at(2).char_at(0);
                let card = match rank {
                   '1'       => Card { rank: 10, suit: suit as uint },
                   '2'...'9' => Card { rank: rank as uint - 48, suit: suit as uint },
                   _         => Card { rank: rank as uint, suit: suit as uint }
                };
                code.push(card);
            }
        }
        code
    }

    // Extra pass to set up jump labels.
    fn resolve(code: &Vec<Card>) -> HashMap<uint, uint> {
        let mut pc = 0u;
        let mut labels: HashMap<uint, uint> = HashMap::new();

        while pc < code.len() - 1 {
            let card = code[pc];
            pc += 1;
            if card.rank == Q {
                let mut queen = card.suit as uint;
                while pc < code.len() && code[pc].rank == Q && code[pc].suit == card.suit {
                    queen += card.suit as uint;
                    pc += 1;
                }
                labels.insert(queen, pc);
            }
        }
        labels
    }

    fn newline(&mut self, card: Card) -> &Ante {
        self.line = card.suit as uint;
        self
    }

    fn jump(&mut self, card: Card) -> &Ante {
        let mut suit = card.suit as uint;
        while self.pc < self.code.len() && self.code[self.pc].rank == K && self.code[self.pc].suit == card.suit {
            suit += card.suit as uint;
            self.pc += 1;
        }

        if !self.vars[card.suit].is_zero() {
            let label: uint = suit as uint;
            if self.labels.contains_key(&label) {
                self.pc = self.labels[label];
            } else {
                self.exception("can't find the label...");
            }
        }
        self
    }

    fn assign(&mut self, card: Card) -> &Ante {
        let operands = self.remaining(card);
        self.expression(operands)
    }

    fn dump(&self, card: Card, as_character: bool) -> &Ante {
        let value = self.vars[card.suit].clone();
        if as_character {
            if value < Ante::big(0) || value > Ante::big(255) {
                self.exception(format!("character code {} is out of 0..255 range", value).as_slice());
            } else {
                print!("{:1c}", from_u32(value.to_u32().unwrap()).unwrap());
            }
        } else {
            print!("{}", value);
        }
        self
    }

    fn remaining(&mut self, card: Card) -> Vec<Card> {
        let mut operands: Vec<Card> = vec![card];

        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            if card.rank == 0 || card.rank == K || card.rank == Q || card.rank == J {
                break;
            }
            operands.push(card);
            self.pc += 1;
        }
        operands
    }

    fn expression(&mut self, operands: Vec<Card>) -> &Ante {
        let mut initial: BigInt = Ante::big(operands[0].rank as int);
        let target = operands[0].suit;

        if initial.to_uint().unwrap() == A {
            initial = self.vars[target].clone();
        }

        for i in range(1, operands.len()) {
            let mut rank = Ante::big(operands[i].rank as int);
            let suit = operands[i].suit;

            if rank.to_uint().unwrap() == A {
                rank = self.vars[suit].clone();
            }

            match suit {
                D => { initial = initial.add(&rank) },
                H => { initial = initial.mul(&rank) },
                S => { initial = initial.sub(&rank) },
                C => if !rank.is_zero() {
                        initial = initial.div(&rank);
                     } else {
                        self.exception("division by zero");
                     },
                _ => continue
            }
        }

        *self.vars.get_mut(&target) = initial;
        self
    }

    fn big(n: int) -> BigInt {
        from_int::<BigInt>(n).unwrap()
    }

    // NOTE: fail! got renamed to panic!
    fn exception(&self, message: &str) {
        fail!("Ante exception: {} on line {} (pc:{})\n", message, self.line, self.pc)
    }
}

fn main() {
    println!("usage: ante filename.ante");
    Ante::new("fizzbuzz.ante".as_slice()).run();
}
<commit_msg>Maintain output buffer to display UTF-8 characters<commit_after>// Copyright (c) 2013-2104 Michael Dvorkin
// Ante is an esoteric programming language where all you've got is a deck of cards.
//
// This is Ante implementation in Rust.

extern crate regex;
extern crate num;

use std::io::File;
use std::collections::HashMap;
use std::num::Zero;
use std::num::from_int;
use std::str::{is_utf8, from_utf8};
use regex::Regex;
use num::bigint::BigInt;

const A: uint = 'A' as uint;
const J: uint = 'J' as uint;
const Q: uint = 'Q' as uint;
const K: uint = 'K' as uint;
const D: uint = '♦' as uint;
const H: uint = '♥' as uint;
const S: uint = '♠' as uint;
const C: uint = '♣' as uint;

struct Card {
    rank: uint,
    suit: uint
}

struct Ante {
    pc:     uint,                   // Program counter (index within ante.code)
    line:   uint,                   // Current line number.
    code:   Vec<Card>,              // Array of cards.
    vars:   HashMap<uint, BigInt>,  // Four registers hashed by suit.
    labels: HashMap<uint, uint>,    // Labels for ante.pc to jump to.
    buffer: Vec<u8>                 // Buffer to collect UTF-8 character bytes.
}

impl Ante {
    fn new(filename: &str) -> Ante {
        let mut vars: HashMap<uint, BigInt> = HashMap::new();
        vars.insert(D, Ante::big(0));
        vars.insert(H, Ante::big(0));
        vars.insert(S, Ante::big(0));
        vars.insert(C, Ante::big(0));

        let code = Ante::parse(filename);
        let labels = Ante::resolve(&code);

        Ante {
            pc:     0,
            line:   0,
            code:   code,
            vars:   vars,
            labels: labels,
            buffer: vec![]
        }
    }

    fn run(&mut self) -> &Ante {
        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            self.pc += 1;
            match card.rank {
                0u  => self.newline(card),
                K   => self.jump(card),
                Q   => continue,
                J   => self.dump(card, true),
                10u => self.dump(card, false),
                _   => self.assign(card)
            };
        }
        self
    }

    // Turn source file into array of cards.
    fn parse(filename: &str) -> Vec<Card> {
        let mut file = File::open(&Path::new(filename));
        let program = file.read_to_string().unwrap();

        // Split program blob into lines getting rid of comments and whitespaces.
        let comments = Regex::new(r"#.*$").unwrap();
        let lines: Vec<String> = program.as_slice().lines().map( |line|
            comments.replace_all(line, "").as_slice().trim().to_string()
        ).collect();

        // Turn source file into array of cards. Each card a struct of rank and suit.
        let mut code: Vec<Card> = vec![];
        let card = Regex::new(r"(10|[2-9JQKA])([♦♥♠♣])").unwrap();
        for (i, line) in lines.iter().enumerate() {
            // Line number cards have zero rank.
            code.push(Card { rank: 0, suit: i + 1 });

            // Parse cards using regural expression.
            for caps in card.captures_iter(line.as_slice()) {
                let rank = caps.at(1).char_at(0);
                let suit = caps.at(2).char_at(0);
                let card = match rank {
                   '1'       => Card { rank: 10, suit: suit as uint },
                   '2'...'9' => Card { rank: rank as uint - 48, suit: suit as uint },
                   _         => Card { rank: rank as uint, suit: suit as uint }
                };
                code.push(card);
            }
        }
        code
    }

    // Extra pass to set up jump labels.
    fn resolve(code: &Vec<Card>) -> HashMap<uint, uint> {
        let mut pc = 0u;
        let mut labels: HashMap<uint, uint> = HashMap::new();

        while pc < code.len() - 1 {
            let card = code[pc];
            pc += 1;
            if card.rank == Q {
                let mut queen = card.suit as uint;
                while pc < code.len() && code[pc].rank == Q && code[pc].suit == card.suit {
                    queen += card.suit as uint;
                    pc += 1;
                }
                labels.insert(queen, pc);
            }
        }
        labels
    }

    fn newline(&mut self, card: Card) -> &Ante {
        self.line = card.suit as uint;
        self
    }

    fn jump(&mut self, card: Card) -> &Ante {
        let mut suit = card.suit as uint;
        while self.pc < self.code.len() && self.code[self.pc].rank == K && self.code[self.pc].suit == card.suit {
            suit += card.suit as uint;
            self.pc += 1;
        }

        if !self.vars[card.suit].is_zero() {
            let label: uint = suit as uint;
            if self.labels.contains_key(&label) {
                self.pc = self.labels[label];
            } else {
                self.exception("can't find the label...");
            }
        }
        self
    }

    fn assign(&mut self, card: Card) -> &Ante {
        let operands = self.remaining(card);
        self.expression(operands)
    }

    fn dump(&mut self, card: Card, as_character: bool) -> &Ante {
        let value = self.vars[card.suit].clone();
        if as_character {
            if value < Ante::big(0) || value > Ante::big(255) {
                self.exception(format!("character code {} is not in 0..255 range", value).as_slice());
            } else {
                // Collect the bytes till we have full UTF-8 character.
                // Once the character is built dump it and reset the buffer.
                self.buffer.push(value.to_u8().unwrap());
                if is_utf8(self.buffer.as_slice()) {
                    print!("{}", from_utf8(self.buffer.as_slice()).unwrap());
                    self.buffer = vec![];
                }
            }
        } else {
            print!("{}", value);
        }
        self
    }

    fn remaining(&mut self, card: Card) -> Vec<Card> {
        let mut operands: Vec<Card> = vec![card];

        while self.pc < self.code.len() {
            let card = self.code[self.pc];
            if card.rank == 0 || card.rank == K || card.rank == Q || card.rank == J {
                break;
            }
            operands.push(card);
            self.pc += 1;
        }
        operands
    }

    fn expression(&mut self, operands: Vec<Card>) -> &Ante {
        let mut initial: BigInt = Ante::big(operands[0].rank as int);
        let target = operands[0].suit;

        if initial.to_uint().unwrap() == A {
            initial = self.vars[target].clone();
        }

        for i in range(1, operands.len()) {
            let mut rank = Ante::big(operands[i].rank as int);
            let suit = operands[i].suit;

            if rank.to_uint().unwrap() == A {
                rank = self.vars[suit].clone();
            }

            match suit {
                D => { initial = initial.add(&rank) },
                H => { initial = initial.mul(&rank) },
                S => { initial = initial.sub(&rank) },
                C => if !rank.is_zero() {
                        initial = initial.div(&rank);
                     } else {
                        self.exception("division by zero");
                     },
                _ => continue
            }
        }

        *self.vars.get_mut(&target) = initial;
        self
    }

    fn big(n: int) -> BigInt {
        from_int::<BigInt>(n).unwrap()
    }

    // NOTE: fail! got renamed to panic!
    fn exception(&self, message: &str) {
        fail!("Ante exception: {} on line {} (pc:{})\n", message, self.line, self.pc)
    }
}

fn main() {
    println!("usage: ante filename.ante");
    Ante::new("quine.ante".as_slice()).run();
}
<|endoftext|>


<commit_before>use libc::c_long;

// a raw Core Foundation reference. It may or may not have been
// CFRetain'ed, depending on whether it was obtained via ownership or
// borrow semantics.
pub trait AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef;
    static pure fn type_id() -> CFTypeID;
}

pub type Boolean = u8;

pub type CFIndex = c_long;
pub type CFOptionFlags = u32;
pub struct CFRange {
    location: CFIndex,
    length: CFIndex
}

pub fn CFRangeMake(off: CFIndex, len: CFIndex) -> CFRange {
    CFRange { location: off, length: len }
}

struct __CFAllocator { private: () }
pub type CFAllocatorRef = *__CFAllocator;

struct __CFNull { private: () }
pub type CFNullRef = *__CFNull;

pub type CFHashCode = libc::c_ulong;
pub type CFTypeID = libc::c_ulong;

struct __CFType { private: () }
pub type CFTypeRef = *__CFType;

pub impl CFTypeRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self }
    // this can't be used, because CFType is the supertype and has no type id.
    static pure fn type_id() -> CFTypeID { fail; }
}

pub pure fn downcast<T:AbstractCFTypeRef>(r: CFTypeRef) -> T unsafe {
    assert CFGetTypeID(r) == type_id::<T>();
    cast::transmute(r)
}

pub struct CFWrapper<T:Copy AbstractCFTypeRef, PlaceholderType1, PlaceholderType2> {
    obj: T,

    drop {
        unsafe {
            assert CFGetRetainCount(cast::transmute(self.obj)) > 0 as CFIndex;
            // sadly, cannot use obj.as_type_ref() here, because drop
            // cannot make virtual method calls using trait
            // types. Instead, just transmute the bugger.
            CFRelease(cast::transmute(self.obj))
        }
    }
}

pub type CFType = CFWrapper<CFTypeRef, (), ()>;

pub impl<T:Copy AbstractCFTypeRef, E1, E2>
    CFWrapper<T, E1, E2> {
    pure fn borrow_ref(&self) -> &self/T {
        &self.obj
    }

    pure fn borrow_type_ref() -> &self/CFTypeRef unsafe {
        cast::transmute(&self.obj)
    }

    // Use this when following Core Foundation's "Create" rule; i.e., the wrapper assumes ownership.
    // The object has already been retained, so we need not increment the retain count ourself.
    static pure fn wrap_owned(some_ref: T) -> CFWrapper<T,E1,E2> {
        // N.B. we can't make any assertions about retain count here,
        // because returned things are only guaranteed to be already
        // retained. Strings, for example, could be interned.
        CFWrapper { obj: some_ref }
    }

    // Use this when following Core Foundation's "Get" rule. The wrapper does not have ownership.
    // Twe need to increment object's the retain count so it isn't freed out from under our noses.
    static pure fn wrap_shared(some_ref: T) -> CFWrapper<T,E1,E2> {
        unsafe { CFRetain(some_ref.as_type_ref()); }
        CFWrapper { obj: some_ref }
    }

    // Unwraps the wrapper, returning the underlying AbstractCFType.
    static fn unwrap(wrapper: CFWrapper<T,E1,E2>) -> T {
        wrapper.obj
    }

    static fn to_CFType(wrapper: CFWrapper<T,E1,E2>) -> CFType unsafe {
        cast::transmute(move wrapper)
    }

    static fn from_CFType(wrapper: CFType) -> CFWrapper<T,E1,E2> unsafe {
        assert wrapper.type_id() == type_id::<T>();
        cast::transmute(move wrapper)
    }

    static fn clone(wrapper: &CFWrapper<T,E1,E2>) -> CFWrapper<T,E1,E2> {
        CFWrapper::wrap_shared(*wrapper.borrow_ref())
    }

    pure fn retain_count() -> CFIndex unsafe {
        CFGetRetainCount(*self.borrow_type_ref())
    }

    pure fn type_id() -> CFTypeID unsafe {
        CFGetTypeID(*self.borrow_type_ref())
    }

    pure fn show() unsafe {
        CFShow(*self.borrow_type_ref());
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFBase.h
     */

    /* CFAllocator Reference */
    // N.B. Many CFAllocator functions and constants are omitted here.
    pub const kCFAllocatorDefault: CFAllocatorRef;
    pub const kCFAllocatorSystemDefault: CFAllocatorRef;
    pub const kCFAllocatorMalloc: CFAllocatorRef;
    pub const kCFAllocatorMallocZone: CFAllocatorRef;
    pub const kCFAllocatorNull: CFAllocatorRef;
    pub const kCFAllocatorUseContext: CFAllocatorRef;

    /* CFNull Reference */

    pub const kCFNull: CFNullRef;

    /* CFType Reference */

    //fn CFCopyDescription
    //fn CFCopyTypeIDDescription
    //fn CFEqual
    //fn CFGetAllocator
    pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
    pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
    pub fn CFHash(cf: CFTypeRef) -> CFHashCode;
    //fn CFMakeCollectable
    pub fn CFRelease(cf: CFTypeRef);
    pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
    pub fn CFShow(obj: CFTypeRef);

    /* Base Utilities Reference */
    // N.B. Some things missing here.
}
<commit_msg>Fix build<commit_after>use libc::c_long;

// a raw Core Foundation reference. It may or may not have been
// CFRetain'ed, depending on whether it was obtained via ownership or
// borrow semantics.
pub trait AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef;
    static pure fn type_id() -> CFTypeID;
}

pub type Boolean = u8;

pub type CFIndex = c_long;
pub type CFOptionFlags = u32;
pub struct CFRange {
    location: CFIndex,
    length: CFIndex
}

pub fn CFRangeMake(off: CFIndex, len: CFIndex) -> CFRange {
    CFRange { location: off, length: len }
}

struct __CFAllocator { private: () }
pub type CFAllocatorRef = *__CFAllocator;

struct __CFNull { private: () }
pub type CFNullRef = *__CFNull;

pub type CFHashCode = libc::c_ulong;
pub type CFTypeID = libc::c_ulong;

struct __CFType { private: () }
pub type CFTypeRef = *__CFType;

pub impl CFTypeRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self }
    // this can't be used, because CFType is the supertype and has no type id.
    static pure fn type_id() -> CFTypeID { fail; }
}

pub pure fn downcast<T:AbstractCFTypeRef>(r: CFTypeRef) -> T unsafe {
    assert CFGetTypeID(r) == AbstractCFTypeRef::type_id::<T>();
    cast::transmute(r)
}

pub struct CFWrapper<T:Copy AbstractCFTypeRef, PlaceholderType1, PlaceholderType2> {
    obj: T,

    drop {
        unsafe {
            assert CFGetRetainCount(cast::transmute(self.obj)) > 0 as CFIndex;
            // sadly, cannot use obj.as_type_ref() here, because drop
            // cannot make virtual method calls using trait
            // types. Instead, just transmute the bugger.
            CFRelease(cast::transmute(self.obj))
        }
    }
}

pub type CFType = CFWrapper<CFTypeRef, (), ()>;

pub impl<T:Copy AbstractCFTypeRef, E1, E2>
    CFWrapper<T, E1, E2> {
    pure fn borrow_ref(&self) -> &self/T {
        &self.obj
    }

    pure fn borrow_type_ref() -> &self/CFTypeRef unsafe {
        cast::transmute(&self.obj)
    }

    // Use this when following Core Foundation's "Create" rule; i.e., the wrapper assumes ownership.
    // The object has already been retained, so we need not increment the retain count ourself.
    static pure fn wrap_owned(some_ref: T) -> CFWrapper<T,E1,E2> {
        // N.B. we can't make any assertions about retain count here,
        // because returned things are only guaranteed to be already
        // retained. Strings, for example, could be interned.
        CFWrapper { obj: some_ref }
    }

    // Use this when following Core Foundation's "Get" rule. The wrapper does not have ownership.
    // Twe need to increment object's the retain count so it isn't freed out from under our noses.
    static pure fn wrap_shared(some_ref: T) -> CFWrapper<T,E1,E2> {
        unsafe { CFRetain(some_ref.as_type_ref()); }
        CFWrapper { obj: some_ref }
    }

    // Unwraps the wrapper, returning the underlying AbstractCFType.
    static fn unwrap(wrapper: CFWrapper<T,E1,E2>) -> T {
        wrapper.obj
    }

    static fn to_CFType(wrapper: CFWrapper<T,E1,E2>) -> CFType unsafe {
        cast::transmute(move wrapper)
    }

    static fn from_CFType(wrapper: CFType) -> CFWrapper<T,E1,E2> unsafe {
        assert wrapper.type_id() == AbstractCFTypeRef::type_id::<T>();
        cast::transmute(move wrapper)
    }

    static fn clone(wrapper: &CFWrapper<T,E1,E2>) -> CFWrapper<T,E1,E2> {
        CFWrapper::wrap_shared(*wrapper.borrow_ref())
    }

    pure fn retain_count() -> CFIndex unsafe {
        CFGetRetainCount(*self.borrow_type_ref())
    }

    pure fn type_id() -> CFTypeID unsafe {
        CFGetTypeID(*self.borrow_type_ref())
    }

    pure fn show() unsafe {
        CFShow(*self.borrow_type_ref());
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFBase.h
     */

    /* CFAllocator Reference */
    // N.B. Many CFAllocator functions and constants are omitted here.
    pub const kCFAllocatorDefault: CFAllocatorRef;
    pub const kCFAllocatorSystemDefault: CFAllocatorRef;
    pub const kCFAllocatorMalloc: CFAllocatorRef;
    pub const kCFAllocatorMallocZone: CFAllocatorRef;
    pub const kCFAllocatorNull: CFAllocatorRef;
    pub const kCFAllocatorUseContext: CFAllocatorRef;

    /* CFNull Reference */

    pub const kCFNull: CFNullRef;

    /* CFType Reference */

    //fn CFCopyDescription
    //fn CFCopyTypeIDDescription
    //fn CFEqual
    //fn CFGetAllocator
    pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
    pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
    pub fn CFHash(cf: CFTypeRef) -> CFHashCode;
    //fn CFMakeCollectable
    pub fn CFRelease(cf: CFTypeRef);
    pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
    pub fn CFShow(obj: CFTypeRef);

    /* Base Utilities Reference */
    // N.B. Some things missing here.
}
<|endoftext|>


<commit_before>use libc::c_long;

pub type Boolean = u8;

pub type CFIndex = c_long;
pub type CFOptionFlags = u32;
pub struct CFRange {
    location: CFIndex,
    length: CFIndex
}

fn CFRangeMake(off: CFIndex, len: CFIndex) -> CFRange {
    CFRange { location: off, length: len }
}

struct __CFAllocator { private: () }
pub type CFAllocatorRef = *__CFAllocator;

struct __CFNull { private: () }
pub type CFNullRef = *__CFNull;

struct __CFType { private: () }
pub type CFTypeRef = *__CFType;

pub type CFHashCode = libc::c_ulong;
pub type CFTypeID = libc::c_ulong;

struct CFType {
    obj: CFTypeRef,

    drop {
        unsafe {
            CFRelease(self.obj)
        }
    }
}

// a raw Core Foundation reference. It may or may not have been
// CFRetain'ed, depending on whether it was obtained via ownership or
// borrow semantics. See
trait AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef;
}

trait AbstractCFType<T: AbstractCFTypeRef> {
    pure fn get_ref() -> T;
    static fn wrap(T) -> self;
    static fn unwrap(wrapper: self) -> T;
}

impl CFTypeRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self }
}

impl CFType : AbstractCFType<CFTypeRef> {
    pure fn get_ref() -> CFTypeRef { self.obj }

    static fn wrap(obj: CFTypeRef) -> CFType {
        CFType { obj: obj }
    }

    static fn unwrap(wrapper: CFType) -> CFTypeRef {
        wrapper.obj
    }
}

trait CFTypeOps<T:AbstractCFTypeRef> {
    pure fn get_type_ref(&self) -> CFTypeRef;
    static fn as_CFType(o: self) -> CFType;
    static fn convert_from_CFType(o: CFType) -> self;
    fn clone_as_CFType(&self) -> CFType;
    static fn clone(&T) -> self;
    fn retain_count(&self) -> CFIndex;
    pure fn type_id() -> CFTypeID;
    fn show(&self);
}

impl<T:Copy AbstractCFTypeRef,S:AbstractCFType<T>> S : CFTypeOps<T> {
    // not actually unsafe
    pure fn get_type_ref(&self) -> CFTypeRef unsafe {
        self.get_ref().as_type_ref()
    }

    static fn as_CFType(obj: S) -> CFType {
        let tyref : CFTypeRef = base::unwrap(move obj).as_type_ref();
        CFType { obj: tyref }
    }

    static fn convert_from_CFType(obj: CFType) -> S unsafe {
        // so we don't deallocate while transferring out of CFType.
        // the call will be balanced by the dtor of the returned wrapper.
        CFRetain(obj.get_ref());
        let tyref : CFTypeRef = base::unwrap(move obj);
        let convref : T = cast::transmute(tyref);
        base::wrap(convref)
    }

    fn clone_as_CFType(&self) -> CFType {
        let tyref = self.get_ref().as_type_ref();
        CFRetain(tyref);
        CFType { obj: tyref }
    }

    static fn clone(cfref: &T) -> S {
        CFRetain(cfref.as_type_ref());
        base::wrap(copy *cfref)
    }

    fn retain_count(&self) -> CFIndex {
        CFGetRetainCount(self.get_type_ref())
    }

    pure fn type_id() -> CFTypeID unsafe {
        CFGetTypeID(self.get_type_ref())
    }

    fn show(&self) {
        CFShow(self.get_type_ref());
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFBase.h
     */

    /* CFAllocator Reference */
    // N.B. Many CFAllocator functions and constants are omitted here.
    const kCFAllocatorDefault: CFAllocatorRef;
    const kCFAllocatorSystemDefault: CFAllocatorRef;
    const kCFAllocatorMalloc: CFAllocatorRef;
    const kCFAllocatorMallocZone: CFAllocatorRef;
    const kCFAllocatorNull: CFAllocatorRef;
    const kCFAllocatorUseContext: CFAllocatorRef;

    /* CFNull Reference */

    const kCFNull: CFNullRef;

    /* CFType Reference */

    //fn CFCopyDescription
    //fn CFCopyTypeIDDescription
    //fn CFEqual
    //fn CFGetAllocator
    fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
    fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
    fn CFHash(cf: CFTypeRef) -> CFHashCode;
    //fn CFMakeCollectable
    fn CFRelease(cf: CFTypeRef);
    fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
    fn CFShow(obj: CFTypeRef);

    /* Base Utilities Reference */
    // N.B. Some things missing here.
}
<commit_msg>Fix double release caused by base::as_CFType.<commit_after>use libc::c_long;

pub type Boolean = u8;

pub type CFIndex = c_long;
pub type CFOptionFlags = u32;
pub struct CFRange {
    location: CFIndex,
    length: CFIndex
}

fn CFRangeMake(off: CFIndex, len: CFIndex) -> CFRange {
    CFRange { location: off, length: len }
}

struct __CFAllocator { private: () }
pub type CFAllocatorRef = *__CFAllocator;

struct __CFNull { private: () }
pub type CFNullRef = *__CFNull;

struct __CFType { private: () }
pub type CFTypeRef = *__CFType;

pub type CFHashCode = libc::c_ulong;
pub type CFTypeID = libc::c_ulong;

struct CFType {
    obj: CFTypeRef,

    drop {
        unsafe {
            CFRelease(self.obj)
        }
    }
}

// a raw Core Foundation reference. It may or may not have been
// CFRetain'ed, depending on whether it was obtained via ownership or
// borrow semantics. See
trait AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef;
}

trait AbstractCFType<T: AbstractCFTypeRef> {
    pure fn get_ref() -> T;
    static fn wrap(T) -> self;
    static fn unwrap(wrapper: self) -> T;
}

impl CFTypeRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self }
}

impl CFType : AbstractCFType<CFTypeRef> {
    pure fn get_ref() -> CFTypeRef { self.obj }

    static fn wrap(obj: CFTypeRef) -> CFType {
        CFType { obj: obj }
    }

    static fn unwrap(wrapper: CFType) -> CFTypeRef {
        wrapper.obj
    }
}

trait CFTypeOps<T:AbstractCFTypeRef> {
    pure fn get_type_ref(&self) -> CFTypeRef;
    static fn as_CFType(o: self) -> CFType;
    static fn convert_from_CFType(o: CFType) -> self;
    fn clone_as_CFType(&self) -> CFType;
    static fn clone(&T) -> self;
    fn retain_count(&self) -> CFIndex;
    pure fn type_id() -> CFTypeID;
    fn show(&self);
}

impl<T:Copy AbstractCFTypeRef,S:AbstractCFType<T>> S : CFTypeOps<T> {
    // not actually unsafe
    pure fn get_type_ref(&self) -> CFTypeRef unsafe {
        self.get_ref().as_type_ref()
    }

    static fn as_CFType(obj: S) -> CFType {
        // so we don't deallocate while transferring into CFType.
        // the call will be balanced by the dtor of the returned wrapper.
        CFRetain(obj.get_ref().as_type_ref());
        let tyref : CFTypeRef = base::unwrap(move obj).as_type_ref();
        CFType { obj: tyref }
    }

    static fn convert_from_CFType(obj: CFType) -> S unsafe {
        // so we don't deallocate while transferring out of CFType.
        // the call will be balanced by the dtor of the returned wrapper.
        CFRetain(obj.get_ref());
        let tyref : CFTypeRef = base::unwrap(move obj);
        let convref : T = cast::transmute(tyref);
        base::wrap(convref)
    }

    fn clone_as_CFType(&self) -> CFType {
        let tyref = self.get_ref().as_type_ref();
        CFRetain(tyref);
        CFType { obj: tyref }
    }

    static fn clone(cfref: &T) -> S {
        CFRetain(cfref.as_type_ref());
        base::wrap(copy *cfref)
    }

    fn retain_count(&self) -> CFIndex {
        CFGetRetainCount(self.get_type_ref())
    }

    pure fn type_id() -> CFTypeID unsafe {
        CFGetTypeID(self.get_type_ref())
    }

    fn show(&self) {
        CFShow(self.get_type_ref());
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFBase.h
     */

    /* CFAllocator Reference */
    // N.B. Many CFAllocator functions and constants are omitted here.
    const kCFAllocatorDefault: CFAllocatorRef;
    const kCFAllocatorSystemDefault: CFAllocatorRef;
    const kCFAllocatorMalloc: CFAllocatorRef;
    const kCFAllocatorMallocZone: CFAllocatorRef;
    const kCFAllocatorNull: CFAllocatorRef;
    const kCFAllocatorUseContext: CFAllocatorRef;

    /* CFNull Reference */

    const kCFNull: CFNullRef;

    /* CFType Reference */

    //fn CFCopyDescription
    //fn CFCopyTypeIDDescription
    //fn CFEqual
    //fn CFGetAllocator
    fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
    fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
    fn CFHash(cf: CFTypeRef) -> CFHashCode;
    //fn CFMakeCollectable
    fn CFRelease(cf: CFTypeRef);
    fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
    fn CFShow(obj: CFTypeRef);

    /* Base Utilities Reference */
    // N.B. Some things missing here.
}
<|endoftext|>


<commit_before>#[crate_id = "date#1.0"];
#[crate_type = "lib"];
#[license = "MIT"];
#[desc = "Library for simple date management" ];
#[comment = "Example of library: date management"];
/**
 * Date management
 *
 * Use "constructor", string manipulation
 * Tested with rust-0.9-pre
 *
 * @author Eliovir <http://github.com/~eliovir>
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 * @since 2013-10-24
 */
use std::from_str::FromStr;

pub struct Date {
	day: int,
	month: int,
	year: int
}

impl Date {
	pub fn addDays(&mut self, days: int) {
		let mut day = self.day;
		let mut month = self.month;
		let mut year = self.year;
		day = day + days;
		if days > 0 {
			while (day > Date::monthLength(year, month)) {
				day = day - Date::monthLength(year, month);
				month = month + 1;
				if (month > 12) {
					year = year + 1;
					month = 1;
				}
			}
		}
		if day == 0 {
			month = month - 1;
			if (month < 1) {
				month = 12;
				year = year - 1;
			}
			day = Date::monthLength(year, month);
		}
		if days < 0 {
			while (day < 1) {
				month = month - 1;
				if (month < 1) {
					year = year - 1;
					month = 12;
				}
				day = day + Date::monthLength(year, month);
			}
		}
		self.day = day;
		self.month = month;
		self.year = year;
	}

	pub fn isValid(&self) -> bool {
		if self.month < 1 || self.month > 12 {
			false
		} else if self.day < 1 || self.day > Date::monthLength(self.year, self.month) {
			false
		} else {
			true
		}
	}

	/*
	 * Static methods
	 */
	pub fn isLeap(year: int) -> bool {
		(year % 4 == 0 && year % 100 != 0) || year % 400 == 0
	}
	pub fn monthLength(year: int, month: int) -> int {
		match  month {
			1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
			2 => if Date::isLeap(year) { 29 } else { 28 },
			4 | 6 | 9 | 11 => 30,
			_ => fail!("Wrong month")
		}
	}
	pub fn new(year: int, month: int, day: int) -> Date {
		Date{day: day, month: month, year: year}
	}
	pub fn newFromString(string: &str) -> Date {
		if string.len() < 10 {
			fail!("Wrong format!");
		}
		let year = FromStr::from_str(string.slice_chars(0, 4)).unwrap();
		let month = FromStr::from_str(string.slice_chars(5, 7)).unwrap();
		let day = FromStr::from_str(string.slice_chars(8, 10)).unwrap();
		Date{day: day, month: month, year: year}
	}
}

/**
 * Operator overloading
 * @see http://maniagnosis.crsr.net/2013/04/operator-overloading-in-rust.html
 */
impl ToStr for Date {
	fn to_str(&self) -> ~str {
		format!("{:4d}-{:2d}-{:2d}", self.year, self.month, self.day)
	}
}

#[cfg(test)]
mod tests {
	#[test]
	fn addDays() {
		let mut date = ::Date::new(2013, 10, 24);
		let orig = date.to_str();
		let days = 2;
		date.addDays(days);
		let expected="2013-10-26";
		let found=date.to_str();
		assert!(expected==found, format!("Adding {:d} days to {} should return {}, not {}", days, orig, expected, found));
	}
	#[test]
	fn isLeap() {
		assert!(!::Date::isLeap(1900), "1900 is not a leap year");
		assert!(!::Date::isLeap(1901), "1901 is not a leap year");
		assert!(::Date::isLeap(2000), "2000 is leap year");
		assert!(::Date::isLeap(2004), "2004 is leap year");
	}
	#[test]
	fn isValid() {
		let mut date = ::Date::new(2013, 10, 24);
		assert!(date.isValid(), "2013-10-24 is a valid date");
		date = ::Date::new(2013, 02, 29);
		assert!(!date.isValid(), "2013-02-29 isn't a valid date");
		date = ::Date::new(2012, 02, 29);
		assert!(date.isValid(), "2012-02-29 isn't a valid date");
	}
	#[test]
	fn to_str() {
		let date = ::Date::new(2013, 10, 24);
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
	/*
	 * Static methods
	 */
	#[test]
	fn monthLength() {
		assert!(::Date::monthLength(2000, 2) == 29, "February 2000 has 29 days");
		assert!(::Date::monthLength(2001, 2) == 28, "February 2001 has 28 days");
		assert!(::Date::monthLength(2013, 2) == 28, "February 2013 has 28 days");
		assert!(::Date::monthLength(2013, 9) == 30, "September 2013 has 30 days");
		assert!(::Date::monthLength(2013, 10) == 31, "October 2013 has 31 days");
	}
	#[test]
	fn new() {
		let date = ::Date::new(2013, 10, 24);
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
	#[test]
	fn newFromString() {
		let date = ::Date::newFromString("2013-10-24 23:24:34");
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
}
/*
fn main() {
	println("This program must be build and run with --test");
}
*/

<commit_msg>date.rs : remove unnecessary parentheses<commit_after>#[crate_id = "date#1.0"];
#[crate_type = "lib"];
#[license = "MIT"];
#[desc = "Library for simple date management" ];
#[comment = "Example of library: date management"];
/**
 * Date management
 *
 * Use "constructor", string manipulation
 * Tested with rust-0.9-pre
 *
 * @author Eliovir <http://github.com/~eliovir>
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 * @since 2013-10-24
 */
use std::from_str::FromStr;

pub struct Date {
	day: int,
	month: int,
	year: int
}

impl Date {
	pub fn addDays(&mut self, days: int) {
		let mut day = self.day;
		let mut month = self.month;
		let mut year = self.year;
		day = day + days;
		if days > 0 {
			while day > Date::monthLength(year, month) {
				day = day - Date::monthLength(year, month);
				month = month + 1;
				if (month > 12) {
					year = year + 1;
					month = 1;
				}
			}
		}
		if day == 0 {
			month = month - 1;
			if month < 1 {
				month = 12;
				year = year - 1;
			}
			day = Date::monthLength(year, month);
		}
		if days < 0 {
			while day < 1 {
				month = month - 1;
				if month < 1 {
					year = year - 1;
					month = 12;
				}
				day = day + Date::monthLength(year, month);
			}
		}
		self.day = day;
		self.month = month;
		self.year = year;
	}

	pub fn isValid(&self) -> bool {
		if self.month < 1 || self.month > 12 {
			false
		} else if self.day < 1 || self.day > Date::monthLength(self.year, self.month) {
			false
		} else {
			true
		}
	}

	/*
	 * Static methods
	 */
	pub fn isLeap(year: int) -> bool {
		(year % 4 == 0 && year % 100 != 0) || year % 400 == 0
	}
	pub fn monthLength(year: int, month: int) -> int {
		match  month {
			1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
			2 => if Date::isLeap(year) { 29 } else { 28 },
			4 | 6 | 9 | 11 => 30,
			_ => fail!("Wrong month")
		}
	}
	pub fn new(year: int, month: int, day: int) -> Date {
		Date{day: day, month: month, year: year}
	}
	pub fn newFromString(string: &str) -> Date {
		if string.len() < 10 {
			fail!("Wrong format!");
		}
		let year = FromStr::from_str(string.slice_chars(0, 4)).unwrap();
		let month = FromStr::from_str(string.slice_chars(5, 7)).unwrap();
		let day = FromStr::from_str(string.slice_chars(8, 10)).unwrap();
		Date{day: day, month: month, year: year}
	}
}

/**
 * Operator overloading
 * @see http://maniagnosis.crsr.net/2013/04/operator-overloading-in-rust.html
 */
impl ToStr for Date {
	fn to_str(&self) -> ~str {
		format!("{:4d}-{:2d}-{:2d}", self.year, self.month, self.day)
	}
}

#[cfg(test)]
mod tests {
	#[test]
	fn addDays() {
		let mut date = ::Date::new(2013, 10, 24);
		let orig = date.to_str();
		let days = 2;
		date.addDays(days);
		let expected="2013-10-26";
		let found=date.to_str();
		assert!(expected==found, format!("Adding {:d} days to {} should return {}, not {}", days, orig, expected, found));
	}
	#[test]
	fn isLeap() {
		assert!(!::Date::isLeap(1900), "1900 is not a leap year");
		assert!(!::Date::isLeap(1901), "1901 is not a leap year");
		assert!(::Date::isLeap(2000), "2000 is leap year");
		assert!(::Date::isLeap(2004), "2004 is leap year");
	}
	#[test]
	fn isValid() {
		let mut date = ::Date::new(2013, 10, 24);
		assert!(date.isValid(), "2013-10-24 is a valid date");
		date = ::Date::new(2013, 02, 29);
		assert!(!date.isValid(), "2013-02-29 isn't a valid date");
		date = ::Date::new(2012, 02, 29);
		assert!(date.isValid(), "2012-02-29 isn't a valid date");
	}
	#[test]
	fn to_str() {
		let date = ::Date::new(2013, 10, 24);
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
	/*
	 * Static methods
	 */
	#[test]
	fn monthLength() {
		assert!(::Date::monthLength(2000, 2) == 29, "February 2000 has 29 days");
		assert!(::Date::monthLength(2001, 2) == 28, "February 2001 has 28 days");
		assert!(::Date::monthLength(2013, 2) == 28, "February 2013 has 28 days");
		assert!(::Date::monthLength(2013, 9) == 30, "September 2013 has 30 days");
		assert!(::Date::monthLength(2013, 10) == 31, "October 2013 has 31 days");
	}
	#[test]
	fn new() {
		let date = ::Date::new(2013, 10, 24);
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
	#[test]
	fn newFromString() {
		let date = ::Date::newFromString("2013-10-24 23:24:34");
		let expected = "2013-10-24";
		let found = date.to_str();
		assert!(expected == found, format!("{}!={}", expected, found));
	}
}
#[cfg(not(test))]
fn main() {
	println("This program must be build and run with --test");
}

<|endoftext|>


<commit_before>pub use super::{Command, CommandType, CommandGroup};

use std::collections::HashMap;
use std::default::Default;
use std::sync::Arc;
use ::client::Context;
use ::model::{Message, Permissions};

pub struct CreateCommand(pub Command);

impl CreateCommand {
    /// Adds a ratelimit bucket.
    pub fn bucket(mut self, bucket: &str) -> Self {
        self.0.bucket = Some(bucket.to_owned());

        self
    }

    /// Adds a "check" to a command, which checks whether or not the command's
    /// function should be called.
    ///
    /// # Examples
    ///
    /// Ensure that the user who created a message, calling a "ping" command,
    /// is the owner.
    ///
    /// ```rust,no_run
    /// use serenity::client::{Client, Context};
    /// use serenity::model::Message;
    /// use std::env;
    ///
    /// let mut client = Client::login_bot(&env::var("DISCORD_TOKEN").unwrap());
    ///
    /// client.with_framework(|f| f
    ///     .configure(|c| c.prefix("~"))
    ///     .command("ping", |c| c
    ///         .check(owner_check)
    ///         .desc("Replies to a ping with a pong")
    ///         .exec(ping)));
    ///
    /// fn ping(context: &Context, _message: &Message, _args: Vec<String>) -> Result<(), String> {
    ///     let _ = context.say("Pong!");
    ///
    ///     Ok(())
    /// }
    ///
    /// fn owner_check(_context: &Context, message: &Message) -> bool {
    ///     // replace with your user ID
    ///     message.author.id == 7
    /// }
    /// ```
    pub fn check<F>(mut self, check: F) -> Self
        where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static {
        self.0.checks.push(Box::new(check));

        self
    }

    /// Description, used by other commands.
    pub fn desc(mut self, desc: &str) -> Self {
        self.0.desc = Some(desc.to_owned());

        self
    }

    /// Whether command can be used only privately or not.
    pub fn dm_only(mut self, dm_only: bool) -> Self {
        self.0.dm_only = dm_only;

        self
    }

    /// A function that can be called when a command is received.
    /// You can return Err(string) if there's an error.
    ///
    /// See [`exec_str`] if you _only_ need to return a string on command use.
    ///
    /// [`exec_str`]: #method.exec_str
    pub fn exec<F>(mut self, func: F) -> Self
        where F: Fn(&Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static {
        self.0.exec = CommandType::Basic(Box::new(func));

        self
    }

    /// Sets a function that's called when a command is called that can access
    /// the internal HashMap of usages, used specifically for creating a help
    /// command.
    ///
    /// You can return Err(string) if there's an error.
    pub fn exec_help<F>(mut self, f: F) -> Self
        where F: Fn(&Context, &Message, HashMap<String, Arc<CommandGroup>>, Vec<String>) -> Result<(), String> + Send + Sync + 'static {
        self.0.exec = CommandType::WithCommands(Box::new(f));

        self
    }

    /// Sets a string to be sent in the channel of context on command. This can
    /// be useful for an `about`, `invite`, `ping`, etc. command.
    ///
    /// # Examples
    ///
    /// Create a command named "ping" that returns "Pong!":
    ///
    /// ```rust,ignore
    /// client.with_framework(|f| f
    ///     .command("ping", |c| c.exec_str("Pong!")));
    /// ```
    pub fn exec_str(mut self, content: &str) -> Self {
        self.0.exec = CommandType::StringResponse(content.to_owned());

        self
    }

    /// Whether command can be used only in guilds or not.
    pub fn guild_only(mut self, guild_only: bool) -> Self {
        self.0.guild_only = guild_only;

        self
    }

    /// Whether command should be displayed in help list or not, used by other commands.
    pub fn help_available(mut self, help_available: bool) -> Self {
        self.0.help_available = help_available;

        self
    }

    /// Maximum amount of arguments that can be passed.
    pub fn max_args(mut self, max_args: i32) -> Self {
        self.0.max_args = Some(max_args);

        self
    }

    /// Minumum amount of arguments that should be passed.
    pub fn min_args(mut self, min_args: i32) -> Self {
        self.0.min_args = Some(min_args);

        self
    }

    /// Whether command can be used only privately or not.
    pub fn owners_only(mut self, owners_only: bool) -> Self {
        self.0.owners_only = owners_only;

        self
    }

    /// The permissions that a user must have in the contextual channel in order
    /// for the command to be processed.
    pub fn required_permissions(mut self, permissions: Permissions) -> Self {
        self.0.required_permissions = permissions;

        self
    }

    /// Command usage schema, used by other commands.
    pub fn usage(mut self, usage: &str) -> Self {
        self.0.usage = Some(usage.to_owned());

        self
    }

    /// Whether or not arguments should be parsed using the quotation parser.
    ///
    /// Enabling this will parse `~command "this is arg 1" "this is arg 2"` as
    /// two arguments: `this is arg 1` and `this is arg 2`.
    ///
    /// Disabling this will parse `~command "this is arg 1" "this is arg 2"` as
    /// eight arguments: `"this`, `is`, `arg`, `1"`, `"this`, `is`, `arg`, `2"`.
    ///
    /// Refer to [`utils::parse_quotes`] for information on the parser.
    ///
    /// [`utils::parse_quotes`]: ../../utils/fn.parse_quotes.html
    pub fn use_quotes(mut self, use_quotes: bool) -> Self {
        self.0.use_quotes = use_quotes;

        self
    }
}

impl Default for Command {
    fn default() -> Command {
        Command {
            checks: Vec::default(),
            exec: CommandType::Basic(Box::new(|_, _, _| Ok(()))),
            desc: None,
            usage: None,
            use_quotes: true,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false
        }
    }
}
<commit_msg>Default Framework command use_quotes to false<commit_after>pub use super::{Command, CommandType, CommandGroup};

use std::collections::HashMap;
use std::default::Default;
use std::sync::Arc;
use ::client::Context;
use ::model::{Message, Permissions};

pub struct CreateCommand(pub Command);

impl CreateCommand {
    /// Adds a ratelimit bucket.
    pub fn bucket(mut self, bucket: &str) -> Self {
        self.0.bucket = Some(bucket.to_owned());

        self
    }

    /// Adds a "check" to a command, which checks whether or not the command's
    /// function should be called.
    ///
    /// # Examples
    ///
    /// Ensure that the user who created a message, calling a "ping" command,
    /// is the owner.
    ///
    /// ```rust,no_run
    /// use serenity::client::{Client, Context};
    /// use serenity::model::Message;
    /// use std::env;
    ///
    /// let mut client = Client::login_bot(&env::var("DISCORD_TOKEN").unwrap());
    ///
    /// client.with_framework(|f| f
    ///     .configure(|c| c.prefix("~"))
    ///     .command("ping", |c| c
    ///         .check(owner_check)
    ///         .desc("Replies to a ping with a pong")
    ///         .exec(ping)));
    ///
    /// fn ping(context: &Context, _message: &Message, _args: Vec<String>) -> Result<(), String> {
    ///     let _ = context.say("Pong!");
    ///
    ///     Ok(())
    /// }
    ///
    /// fn owner_check(_context: &Context, message: &Message) -> bool {
    ///     // replace with your user ID
    ///     message.author.id == 7
    /// }
    /// ```
    pub fn check<F>(mut self, check: F) -> Self
        where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static {
        self.0.checks.push(Box::new(check));

        self
    }

    /// Description, used by other commands.
    pub fn desc(mut self, desc: &str) -> Self {
        self.0.desc = Some(desc.to_owned());

        self
    }

    /// Whether command can be used only privately or not.
    pub fn dm_only(mut self, dm_only: bool) -> Self {
        self.0.dm_only = dm_only;

        self
    }

    /// A function that can be called when a command is received.
    /// You can return Err(string) if there's an error.
    ///
    /// See [`exec_str`] if you _only_ need to return a string on command use.
    ///
    /// [`exec_str`]: #method.exec_str
    pub fn exec<F>(mut self, func: F) -> Self
        where F: Fn(&Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static {
        self.0.exec = CommandType::Basic(Box::new(func));

        self
    }

    /// Sets a function that's called when a command is called that can access
    /// the internal HashMap of usages, used specifically for creating a help
    /// command.
    ///
    /// You can return Err(string) if there's an error.
    pub fn exec_help<F>(mut self, f: F) -> Self
        where F: Fn(&Context, &Message, HashMap<String, Arc<CommandGroup>>, Vec<String>) -> Result<(), String> + Send + Sync + 'static {
        self.0.exec = CommandType::WithCommands(Box::new(f));

        self
    }

    /// Sets a string to be sent in the channel of context on command. This can
    /// be useful for an `about`, `invite`, `ping`, etc. command.
    ///
    /// # Examples
    ///
    /// Create a command named "ping" that returns "Pong!":
    ///
    /// ```rust,ignore
    /// client.with_framework(|f| f
    ///     .command("ping", |c| c.exec_str("Pong!")));
    /// ```
    pub fn exec_str(mut self, content: &str) -> Self {
        self.0.exec = CommandType::StringResponse(content.to_owned());

        self
    }

    /// Whether command can be used only in guilds or not.
    pub fn guild_only(mut self, guild_only: bool) -> Self {
        self.0.guild_only = guild_only;

        self
    }

    /// Whether command should be displayed in help list or not, used by other commands.
    pub fn help_available(mut self, help_available: bool) -> Self {
        self.0.help_available = help_available;

        self
    }

    /// Maximum amount of arguments that can be passed.
    pub fn max_args(mut self, max_args: i32) -> Self {
        self.0.max_args = Some(max_args);

        self
    }

    /// Minumum amount of arguments that should be passed.
    pub fn min_args(mut self, min_args: i32) -> Self {
        self.0.min_args = Some(min_args);

        self
    }

    /// Whether command can be used only privately or not.
    pub fn owners_only(mut self, owners_only: bool) -> Self {
        self.0.owners_only = owners_only;

        self
    }

    /// The permissions that a user must have in the contextual channel in order
    /// for the command to be processed.
    pub fn required_permissions(mut self, permissions: Permissions) -> Self {
        self.0.required_permissions = permissions;

        self
    }

    /// Command usage schema, used by other commands.
    pub fn usage(mut self, usage: &str) -> Self {
        self.0.usage = Some(usage.to_owned());

        self
    }

    /// Whether or not arguments should be parsed using the quotation parser.
    ///
    /// Enabling this will parse `~command "this is arg 1" "this is arg 2"` as
    /// two arguments: `this is arg 1` and `this is arg 2`.
    ///
    /// Disabling this will parse `~command "this is arg 1" "this is arg 2"` as
    /// eight arguments: `"this`, `is`, `arg`, `1"`, `"this`, `is`, `arg`, `2"`.
    ///
    /// Refer to [`utils::parse_quotes`] for information on the parser.
    ///
    /// [`utils::parse_quotes`]: ../../utils/fn.parse_quotes.html
    pub fn use_quotes(mut self, use_quotes: bool) -> Self {
        self.0.use_quotes = use_quotes;

        self
    }
}

impl Default for Command {
    fn default() -> Command {
        Command {
            checks: Vec::default(),
            exec: CommandType::Basic(Box::new(|_, _, _| Ok(()))),
            desc: None,
            usage: None,
            use_quotes: false,
            min_args: None,
            bucket: None,
            max_args: None,
            required_permissions: Permissions::empty(),
            dm_only: false,
            guild_only: false,
            help_available: true,
            owners_only: false
        }
    }
}
<|endoftext|>


<commit_before>use super::{
    device::{Device, DeviceColor, DeviceId, DeviceSceneState, DeviceState},
    events::{Message, TxEventChannel},
    integration::IntegrationId,
    scene::{SceneDescriptor, SceneId},
    scenes_manager::ScenesManager,
};
use palette::Hsv;
use std::{collections::HashMap, time::Instant};

pub type DeviceStateKey = (IntegrationId, DeviceId);
pub type DevicesState = HashMap<DeviceStateKey, Device>;

pub fn get_device_state_key(device: &Device) -> DeviceStateKey {
    (device.integration_id.clone(), device.id.clone())
}

pub fn mk_device_state_key(integration_id: &IntegrationId, device_id: &DeviceId) -> DeviceStateKey {
    (integration_id.clone(), device_id.clone())
}

pub struct DevicesManager {
    sender: TxEventChannel,
    state: DevicesState,
    scenes_manager: ScenesManager,
}

fn cmp_light_state(
    a: &Option<DeviceColor>,
    a_bri: &Option<f64>,
    b: &Option<DeviceColor>,
    b_bri: &Option<f64>,
) -> bool {
    let hue_delta = 2.0;
    let sat_delta = 0.03;
    let val_delta = 0.03;

    match (a, b) {
        (None, None) => true,
        (None, Some(_)) => false,
        (Some(_), None) => false,
        (Some(a), Some(b)) => {
            let mut a_hsv: Hsv = a.clone().into();
            let mut b_hsv: Hsv = b.clone().into();

            a_hsv.value = a_hsv.value * (a_bri.unwrap_or(1.0) as f32);
            b_hsv.value = b_hsv.value * (b_bri.unwrap_or(1.0) as f32);

            if f32::abs(a_hsv.hue.to_degrees() - b_hsv.hue.to_degrees()) > hue_delta {
                return false;
            }
            if f32::abs(a_hsv.saturation - b_hsv.saturation) > sat_delta {
                return false;
            }
            if f32::abs(a_hsv.value - b_hsv.value) > val_delta {
                return false;
            }

            true
        }
    }
}

fn cmp_device_states(a: &DeviceState, b: &DeviceState) -> bool {
    match (a, b) {
        (DeviceState::OnOffDevice(a), DeviceState::OnOffDevice(b)) => a.power == b.power,
        (DeviceState::Light(a), DeviceState::Light(b)) => {
            if a.power != b.power {
                return false;
            }
            // If both lights are turned off, state matches
            if a.power == false && b.power == false {
                return true;
            }
            return cmp_light_state(&a.color, &a.brightness, &b.color, &b.brightness);
        }
        (DeviceState::MultiSourceLight(a), DeviceState::MultiSourceLight(b)) => {
            if a.power != b.power {
                return false;
            }
            a.lights
                .iter()
                .zip(b.lights.iter())
                .map(|(light_a, light_b)| {
                    cmp_light_state(
                        &Some(light_a.clone()),
                        &a.brightness,
                        &Some(light_b.clone()),
                        &b.brightness,
                    )
                })
                .all(|value| value)
        }
        _ => false,
    }
}

impl DevicesManager {
    pub fn new(sender: TxEventChannel, scenes_manager: ScenesManager) -> Self {
        DevicesManager {
            sender,
            state: HashMap::new(),
            scenes_manager,
        }
    }

    /// Checks whether device values were changed or not due to refresh
    pub fn handle_integration_device_refresh(&mut self, device: Device) {
        // println!("handle_integration_device_refresh {:?}", device);
        let state_device = self.get_device(&device.integration_id, &device.id);

        // recompute expected_state here as it may have changed since we last
        // computed it
        let expected_state = state_device.map(|d| self.get_expected_state(&d, false));

        // Take action if the device state has changed from stored state
        if Some(&device) != state_device || expected_state != Some(device.state.clone()) {
            let kind = device.state.clone();

            match (kind, state_device, expected_state) {
                // Device was seen for the first time
                (_, None, _) => {
                    println!("Discovered device: {:?}", device);
                    self.set_device_state(&device, false);
                }

                // Sensor state has changed, defer handling of this update
                // to other subsystems
                (DeviceState::Sensor(_), Some(_), _) => {
                    self.set_device_state(&device, false);
                }

                // Device state does not match expected state, maybe the
                // device missed a state update or forgot its state? Try
                // fixing this by emitting a SetIntegrationDeviceState
                // message back to integration
                (_, _, Some(expected_state)) => {
                    if cmp_device_states(&device.state, &expected_state) {
                        return;
                    }

                    println!(
                        "Device state mismatch detected ({}/{}): (was: {:?}, expected: {:?})",
                        device.integration_id, device.id, device.state, expected_state
                    );

                    let mut device = device.clone();
                    device.state = expected_state;

                    self.sender
                        .clone()
                        .send(Message::SetIntegrationDeviceState { device })
                        .unwrap();
                }

                // Expected device state was not found
                (_, _, None) => {
                    self.set_device_state(&device, false);
                }
            }
        }
    }

    /// Returns expected state for given device based on possible active scene.
    /// If no scene active and set_state is false, previous device state is returned.
    /// If no scene active and set_state is true, passed device state is returned.
    fn get_expected_state(&self, device: &Device, set_state: bool) -> DeviceState {
        match device.state {
            // Sensors should always use the most recent sensor reading
            DeviceState::Sensor(_) => device.state.clone(),

            _ => {
                let scene_device_state = self
                    .scenes_manager
                    .find_scene_device_state(&device, &self.state);

                scene_device_state.unwrap_or_else(|| {
                    // TODO: why would we ever want to do this
                    if set_state {
                        device.state.clone()
                    } else {
                        let device = self
                            .state
                            .get(&get_device_state_key(device))
                            .unwrap_or(device)
                            .clone();

                        device.state
                    }
                })
            }
        }
    }

    /// Sets stored state for given device and dispatches DeviceUpdate
    pub fn set_device_state(&mut self, device: &Device, set_scene: bool) -> Device {
        let old: Option<Device> = self.get_device(&device.integration_id, &device.id).cloned();
        let old_state = self.state.clone();

        let mut device = device.clone();

        // Restore scene if set_scene is false
        match (set_scene, old.clone()) {
            (false, Some(old)) => {
                device.scene = old.scene;
            }
            _ => {}
        }

        // Allow active scene to override device state
        let expected_state = self.get_expected_state(&device, true);
        device.state = expected_state;

        self.state
            .insert(get_device_state_key(&device), device.clone());

        self.sender
            .send(Message::DeviceUpdate {
                old_state,
                new_state: self.state.clone(),
                old,
                new: device.clone(),
            })
            .unwrap();

        device
    }

    pub fn get_device(
        &self,
        integration_id: &IntegrationId,
        device_id: &DeviceId,
    ) -> Option<&Device> {
        self.state
            .get(&mk_device_state_key(&integration_id, &device_id))
    }

    pub fn activate_scene(&mut self, scene_id: &SceneId) -> Option<bool> {
        println!("Activating scene {:?}", scene_id);

        let scene_devices_config = self
            .scenes_manager
            .find_scene_devices_config(&self.state, scene_id)?;
        let device_scene_state = Some(DeviceSceneState {
            scene_id: scene_id.to_owned(),
            activation_time: Instant::now(),
        });

        for (integration_id, devices) in scene_devices_config {
            for (device_id, _) in devices {
                let device = self.get_device(&integration_id, &device_id);

                match device {
                    Some(device) => {
                        let mut device = device.clone();
                        device.scene = device_scene_state.clone();
                        let device = self.set_device_state(&device, true);

                        self.sender
                            .clone()
                            .send(Message::SetIntegrationDeviceState { device })
                            .unwrap();
                    }
                    None => {}
                }
            }
        }

        Some(true)
    }

    pub fn cycle_scenes(&mut self, scene_descriptors: &Vec<SceneDescriptor>) -> Option<bool> {
        let active_scene_index = scene_descriptors.iter().position(|sd| {
            let scene_devices_config = self
                .scenes_manager
                .find_scene_devices_config(&self.state, &sd.scene_id);

            // try finding any device in scene_devices_config that has this scene active
            match scene_devices_config {
                Some(integrations) => integrations
                    .iter()
                    .find(|(integration_id, devices)| {
                        devices
                            .iter()
                            .find(|(device_id, _)| {
                                let device =
                                    find_device(&self.state, integration_id, Some(device_id), None);
                                let device_scene = device.map(|d| d.scene).flatten();

                                device_scene.map_or(false, |ds| ds.scene_id == sd.scene_id)
                            })
                            .is_some()
                    })
                    .is_some(),
                None => false,
            }
        });

        let next_scene = match active_scene_index {
            Some(index) => {
                let next_scene_index = (index + 1) % scene_descriptors.len();
                scene_descriptors.iter().nth(next_scene_index)
            }
            None => scene_descriptors.first(),
        }?;

        self.activate_scene(&next_scene.scene_id);

        Some(true)
    }
}

pub fn find_device(
    devices: &DevicesState,
    integration_id: &IntegrationId,
    device_id: Option<&DeviceId>,
    name: Option<&String>,
) -> Option<Device> {
    let (_, device) = devices.iter().find(
        |((candidate_integration_id, candidate_device_id), candidate_device)| {
            if integration_id != candidate_integration_id {
                return false;
            }
            if device_id.is_some() && device_id != Some(candidate_device_id) {
                return false;
            }

            // TODO: regex matches
            if name.is_some() && name != Some(&candidate_device.name) {
                return false;
            }

            true
        },
    )?;

    Some(device.clone())
}
<commit_msg>only consider state of devices in all cycled scenes<commit_after>use super::{
    device::{Device, DeviceColor, DeviceId, DeviceSceneState, DeviceState},
    events::{Message, TxEventChannel},
    integration::IntegrationId,
    scene::{SceneDescriptor, SceneId},
    scenes_manager::ScenesManager,
};
use palette::Hsv;
use std::{collections::HashMap, time::Instant};

pub type DeviceStateKey = (IntegrationId, DeviceId);
pub type DevicesState = HashMap<DeviceStateKey, Device>;

pub fn get_device_state_key(device: &Device) -> DeviceStateKey {
    (device.integration_id.clone(), device.id.clone())
}

pub fn mk_device_state_key(integration_id: &IntegrationId, device_id: &DeviceId) -> DeviceStateKey {
    (integration_id.clone(), device_id.clone())
}

pub struct DevicesManager {
    sender: TxEventChannel,
    state: DevicesState,
    scenes_manager: ScenesManager,
}

fn cmp_light_state(
    a: &Option<DeviceColor>,
    a_bri: &Option<f64>,
    b: &Option<DeviceColor>,
    b_bri: &Option<f64>,
) -> bool {
    let hue_delta = 2.0;
    let sat_delta = 0.03;
    let val_delta = 0.03;

    match (a, b) {
        (None, None) => true,
        (None, Some(_)) => false,
        (Some(_), None) => false,
        (Some(a), Some(b)) => {
            let mut a_hsv: Hsv = a.clone().into();
            let mut b_hsv: Hsv = b.clone().into();

            a_hsv.value = a_hsv.value * (a_bri.unwrap_or(1.0) as f32);
            b_hsv.value = b_hsv.value * (b_bri.unwrap_or(1.0) as f32);

            if f32::abs(a_hsv.hue.to_degrees() - b_hsv.hue.to_degrees()) > hue_delta {
                return false;
            }
            if f32::abs(a_hsv.saturation - b_hsv.saturation) > sat_delta {
                return false;
            }
            if f32::abs(a_hsv.value - b_hsv.value) > val_delta {
                return false;
            }

            true
        }
    }
}

fn cmp_device_states(a: &DeviceState, b: &DeviceState) -> bool {
    match (a, b) {
        (DeviceState::OnOffDevice(a), DeviceState::OnOffDevice(b)) => a.power == b.power,
        (DeviceState::Light(a), DeviceState::Light(b)) => {
            if a.power != b.power {
                return false;
            }
            // If both lights are turned off, state matches
            if a.power == false && b.power == false {
                return true;
            }
            return cmp_light_state(&a.color, &a.brightness, &b.color, &b.brightness);
        }
        (DeviceState::MultiSourceLight(a), DeviceState::MultiSourceLight(b)) => {
            if a.power != b.power {
                return false;
            }
            a.lights
                .iter()
                .zip(b.lights.iter())
                .map(|(light_a, light_b)| {
                    cmp_light_state(
                        &Some(light_a.clone()),
                        &a.brightness,
                        &Some(light_b.clone()),
                        &b.brightness,
                    )
                })
                .all(|value| value)
        }
        _ => false,
    }
}

impl DevicesManager {
    pub fn new(sender: TxEventChannel, scenes_manager: ScenesManager) -> Self {
        DevicesManager {
            sender,
            state: HashMap::new(),
            scenes_manager,
        }
    }

    /// Checks whether device values were changed or not due to refresh
    pub fn handle_integration_device_refresh(&mut self, device: Device) {
        // println!("handle_integration_device_refresh {:?}", device);
        let state_device = self.get_device(&device.integration_id, &device.id);

        // recompute expected_state here as it may have changed since we last
        // computed it
        let expected_state = state_device.map(|d| self.get_expected_state(&d, false));

        // Take action if the device state has changed from stored state
        if Some(&device) != state_device || expected_state != Some(device.state.clone()) {
            let kind = device.state.clone();

            match (kind, state_device, expected_state) {
                // Device was seen for the first time
                (_, None, _) => {
                    println!("Discovered device: {:?}", device);
                    self.set_device_state(&device, false);
                }

                // Sensor state has changed, defer handling of this update
                // to other subsystems
                (DeviceState::Sensor(_), Some(_), _) => {
                    self.set_device_state(&device, false);
                }

                // Device state does not match expected state, maybe the
                // device missed a state update or forgot its state? Try
                // fixing this by emitting a SetIntegrationDeviceState
                // message back to integration
                (_, _, Some(expected_state)) => {
                    if cmp_device_states(&device.state, &expected_state) {
                        return;
                    }

                    println!(
                        "Device state mismatch detected ({}/{}): (was: {:?}, expected: {:?})",
                        device.integration_id, device.id, device.state, expected_state
                    );

                    let mut device = device.clone();
                    device.state = expected_state;

                    self.sender
                        .clone()
                        .send(Message::SetIntegrationDeviceState { device })
                        .unwrap();
                }

                // Expected device state was not found
                (_, _, None) => {
                    self.set_device_state(&device, false);
                }
            }
        }
    }

    /// Returns expected state for given device based on possible active scene.
    /// If no scene active and set_state is false, previous device state is returned.
    /// If no scene active and set_state is true, passed device state is returned.
    fn get_expected_state(&self, device: &Device, set_state: bool) -> DeviceState {
        match device.state {
            // Sensors should always use the most recent sensor reading
            DeviceState::Sensor(_) => device.state.clone(),

            _ => {
                let scene_device_state = self
                    .scenes_manager
                    .find_scene_device_state(&device, &self.state);

                scene_device_state.unwrap_or_else(|| {
                    // TODO: why would we ever want to do this
                    if set_state {
                        device.state.clone()
                    } else {
                        let device = self
                            .state
                            .get(&get_device_state_key(device))
                            .unwrap_or(device)
                            .clone();

                        device.state
                    }
                })
            }
        }
    }

    /// Sets stored state for given device and dispatches DeviceUpdate
    pub fn set_device_state(&mut self, device: &Device, set_scene: bool) -> Device {
        let old: Option<Device> = self.get_device(&device.integration_id, &device.id).cloned();
        let old_state = self.state.clone();

        let mut device = device.clone();

        // Restore scene if set_scene is false
        match (set_scene, old.clone()) {
            (false, Some(old)) => {
                device.scene = old.scene;
            }
            _ => {}
        }

        // Allow active scene to override device state
        let expected_state = self.get_expected_state(&device, true);
        device.state = expected_state;

        self.state
            .insert(get_device_state_key(&device), device.clone());

        self.sender
            .send(Message::DeviceUpdate {
                old_state,
                new_state: self.state.clone(),
                old,
                new: device.clone(),
            })
            .unwrap();

        device
    }

    pub fn get_device(
        &self,
        integration_id: &IntegrationId,
        device_id: &DeviceId,
    ) -> Option<&Device> {
        self.state
            .get(&mk_device_state_key(&integration_id, &device_id))
    }

    pub fn activate_scene(&mut self, scene_id: &SceneId) -> Option<bool> {
        println!("Activating scene {:?}", scene_id);

        let scene_devices_config = self
            .scenes_manager
            .find_scene_devices_config(&self.state, scene_id)?;
        let device_scene_state = Some(DeviceSceneState {
            scene_id: scene_id.to_owned(),
            activation_time: Instant::now(),
        });

        for (integration_id, devices) in scene_devices_config {
            for (device_id, _) in devices {
                let device = self.get_device(&integration_id, &device_id);

                match device {
                    Some(device) => {
                        let mut device = device.clone();
                        device.scene = device_scene_state.clone();
                        let device = self.set_device_state(&device, true);

                        self.sender
                            .clone()
                            .send(Message::SetIntegrationDeviceState { device })
                            .unwrap();
                    }
                    None => {}
                }
            }
        }

        Some(true)
    }

    pub fn cycle_scenes(&mut self, scene_descriptors: &Vec<SceneDescriptor>) -> Option<bool> {
        let mut scenes_common_devices: Vec<(IntegrationId, DeviceId)> = Vec::new();

        // gather a Vec<Vec(IntegrationId, DeviceId)>> of all devices in cycled scenes
        let scenes_devices: Vec<Vec<(IntegrationId, DeviceId)>> = scene_descriptors
            .iter()
            .map(|sd| {
                let scene_devices_config = self
                    .scenes_manager
                    .find_scene_devices_config(&self.state, &sd.scene_id);

                let mut scene_devices: Vec<(IntegrationId, DeviceId)> = Vec::new();
                match scene_devices_config {
                    Some(integrations) => {
                        for (integration_id, integration) in integrations {
                            for (device_id, _) in integration {
                                scene_devices.push((integration_id.clone(), device_id));
                            }
                        }
                    }
                    None => {}
                }

                scene_devices
            })
            .collect();

        // gather devices which exist in all cycled scenes into scenes_common_devices
        scenes_devices.first().map(|first_scene_devices| {
            for scene_device in first_scene_devices {
                if scenes_devices
                    .iter()
                    .all(|scene_devices| scene_devices.contains(scene_device))
                {
                    scenes_common_devices.push(scene_device.clone());
                }
            }
        });

        let active_scene_index = scene_descriptors.iter().position(|sd| {
            let scene_devices_config = self
                .scenes_manager
                .find_scene_devices_config(&self.state, &sd.scene_id);

            // try finding any device in scene_devices_config that has this scene active
            match scene_devices_config {
                Some(integrations) => integrations
                    .iter()
                    .find(|(integration_id, devices)| {
                        devices
                            .iter()
                            .find(|(device_id, _)| {
                                // only consider devices which are common across all cycled scenes
                                if !scenes_common_devices
                                    .contains(&(integration_id.to_string(), device_id.to_string()))
                                {
                                    return false;
                                }

                                let device =
                                    find_device(&self.state, integration_id, Some(device_id), None);
                                let device_scene = device.map(|d| d.scene).flatten();

                                device_scene.map_or(false, |ds| ds.scene_id == sd.scene_id)
                            })
                            .is_some()
                    })
                    .is_some(),
                None => false,
            }
        });

        let next_scene = match active_scene_index {
            Some(index) => {
                let next_scene_index = (index + 1) % scene_descriptors.len();
                scene_descriptors.iter().nth(next_scene_index)
            }
            None => scene_descriptors.first(),
        }?;

        self.activate_scene(&next_scene.scene_id);

        Some(true)
    }
}

pub fn find_device(
    devices: &DevicesState,
    integration_id: &IntegrationId,
    device_id: Option<&DeviceId>,
    name: Option<&String>,
) -> Option<Device> {
    let (_, device) = devices.iter().find(
        |((candidate_integration_id, candidate_device_id), candidate_device)| {
            if integration_id != candidate_integration_id {
                return false;
            }
            if device_id.is_some() && device_id != Some(candidate_device_id) {
                return false;
            }

            // TODO: regex matches
            if name.is_some() && name != Some(&candidate_device.name) {
                return false;
            }

            true
        },
    )?;

    Some(device.clone())
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// Information concerning the machine representation of various types.

#![allow(non_camel_case_types)]

use llvm;
use llvm::{ValueRef};
use llvm::False;
use trans::common::*;

use trans::type_::Type;

pub type llbits = u64;
pub type llsize = u64;
pub type llalign = u32;

// ______________________________________________________________________
// compute sizeof / alignof

// Returns the number of bytes clobbered by a Store to this type.
pub fn llsize_of_store(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        return llvm::LLVMStoreSizeOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the number of bytes between successive elements of type T in an
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        return llvm::LLVMABISizeOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns, as near as we can figure, the "real" size of a type. As in, the
// bits in this number of bytes actually carry data related to the datum
// with the type. Not junk, padding, accidentally-damaged words, or
// whatever. Rounds up to the nearest byte though, so if you have a 1-bit
// value, we return 1 here, not 0. Most of rustc works in bytes. Be warned
// that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
// at the codegen level! In general you should prefer `llbitsize_of_real`
// below.
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        let nbits = llvm::LLVMSizeOfTypeInBits(cx.td().lltd, ty.to_ref());
        if nbits & 7 != 0 {
            // Not an even number of bytes, spills into "next" byte.
            1 + (nbits >> 3)
        } else {
            nbits >> 3
        }
    }
}

/// Returns the "real" size of the type in bits.
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> llbits {
    unsafe {
        llvm::LLVMSizeOfTypeInBits(cx.td().lltd, ty.to_ref())
    }
}

/// Returns the size of the type as an LLVM constant integer value.
pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    // Once upon a time, this called LLVMSizeOf, which does a
    // getelementptr(1) on a null pointer and casts to an int, in
    // order to obtain the type size as a value without requiring the
    // target data layout.  But we have the target data layout, so
    // there's no need for that contrivance.  The instruction
    // selection DAG generator would flatten that GEP(1) node into a
    // constant of the type's alloc size, so let's save it some work.
    return C_uint(cx, llsize_of_alloc(cx, ty));
}

// Returns the "default" size of t (see above), or 1 if the size would
// be zero.  This is important for things like vectors that expect
// space to be consumed.
pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    if llbitsize_of_real(cx, ty) == 0 {
        unsafe { llvm::LLVMConstInt(cx.int_type().to_ref(), 1, False) }
    } else {
        llsize_of(cx, ty)
    }
}

// Returns the preferred alignment of the given type for the current target.
// The preferred alignment may be larger than the alignment used when
// packing the type into structs. This will be used for things like
// allocations inside a stack frame, which LLVM has a free hand in.
pub fn llalign_of_pref(cx: &CrateContext, ty: Type) -> llalign {
    unsafe {
        return llvm::LLVMPreferredAlignmentOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the minimum alignment of a type required by the platform.
// This is the alignment that will be used for struct fields, arrays,
// and similar ABI-mandated things.
pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> llalign {
    unsafe {
        return llvm::LLVMABIAlignmentOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the "default" alignment of t, which is calculated by casting
// null to a record containing a single-bit followed by a t value, then
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
    unsafe {
        return llvm::LLVMConstIntCast(
            llvm::LLVMAlignOf(ty.to_ref()), cx.int_type().to_ref(), False);
    }
}

pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 {
    unsafe {
        return llvm::LLVMOffsetOfElement(cx.td().lltd, struct_ty.to_ref(),
                                         element as u32);
    }
}
<commit_msg>Correct the comment of the function `llsize_of_real`<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// Information concerning the machine representation of various types.

#![allow(non_camel_case_types)]

use llvm;
use llvm::{ValueRef};
use llvm::False;
use trans::common::*;

use trans::type_::Type;

pub type llbits = u64;
pub type llsize = u64;
pub type llalign = u32;

// ______________________________________________________________________
// compute sizeof / alignof

// Returns the number of bytes clobbered by a Store to this type.
pub fn llsize_of_store(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        return llvm::LLVMStoreSizeOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the number of bytes between successive elements of type T in an
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        return llvm::LLVMABISizeOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns, as near as we can figure, the "real" size of a type. As in, the
// bits in this number of bytes actually carry data related to the datum
// with the type. Not junk, accidentally-damaged words, or whatever.
// Note that padding of the type will be included for structs, but not for the
// other types (i.e. SIMD types).
// Rounds up to the nearest byte though, so if you have a 1-bit
// value, we return 1 here, not 0. Most of rustc works in bytes. Be warned
// that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
// at the codegen level! In general you should prefer `llbitsize_of_real`
// below.
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> llsize {
    unsafe {
        let nbits = llvm::LLVMSizeOfTypeInBits(cx.td().lltd, ty.to_ref());
        if nbits & 7 != 0 {
            // Not an even number of bytes, spills into "next" byte.
            1 + (nbits >> 3)
        } else {
            nbits >> 3
        }
    }
}

/// Returns the "real" size of the type in bits.
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> llbits {
    unsafe {
        llvm::LLVMSizeOfTypeInBits(cx.td().lltd, ty.to_ref())
    }
}

/// Returns the size of the type as an LLVM constant integer value.
pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    // Once upon a time, this called LLVMSizeOf, which does a
    // getelementptr(1) on a null pointer and casts to an int, in
    // order to obtain the type size as a value without requiring the
    // target data layout.  But we have the target data layout, so
    // there's no need for that contrivance.  The instruction
    // selection DAG generator would flatten that GEP(1) node into a
    // constant of the type's alloc size, so let's save it some work.
    return C_uint(cx, llsize_of_alloc(cx, ty));
}

// Returns the "default" size of t (see above), or 1 if the size would
// be zero.  This is important for things like vectors that expect
// space to be consumed.
pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    if llbitsize_of_real(cx, ty) == 0 {
        unsafe { llvm::LLVMConstInt(cx.int_type().to_ref(), 1, False) }
    } else {
        llsize_of(cx, ty)
    }
}

// Returns the preferred alignment of the given type for the current target.
// The preferred alignment may be larger than the alignment used when
// packing the type into structs. This will be used for things like
// allocations inside a stack frame, which LLVM has a free hand in.
pub fn llalign_of_pref(cx: &CrateContext, ty: Type) -> llalign {
    unsafe {
        return llvm::LLVMPreferredAlignmentOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the minimum alignment of a type required by the platform.
// This is the alignment that will be used for struct fields, arrays,
// and similar ABI-mandated things.
pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> llalign {
    unsafe {
        return llvm::LLVMABIAlignmentOfType(cx.td().lltd, ty.to_ref());
    }
}

// Returns the "default" alignment of t, which is calculated by casting
// null to a record containing a single-bit followed by a t value, then
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
    unsafe {
        return llvm::LLVMConstIntCast(
            llvm::LLVMAlignOf(ty.to_ref()), cx.int_type().to_ref(), False);
    }
}

pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 {
    unsafe {
        return llvm::LLVMOffsetOfElement(cx.td().lltd, struct_ty.to_ref(),
                                         element as u32);
    }
}
<|endoftext|>


<commit_before>//! Telegram bot types.

pub mod requests;
pub use requests::*;

pub use telegram_bot_raw::{Integer, Float, Request, DetachedRequest};
pub use telegram_bot_raw::{ResponseType, JsonResponse, JsonIdResponse, JsonTrueToUnitResponse};
pub use telegram_bot_raw::{Update, UpdateKind};
pub use telegram_bot_raw::{User, Group, Supergroup, Channel, Chat};
pub use telegram_bot_raw::{UserId, GroupId, SupergroupId, ChannelId, ChatId, ChatRef};
pub use telegram_bot_raw::{CallbackQuery, CallbackQueryId};
pub use telegram_bot_raw::{Message, MessageId, MessageKind, Forward, ForwardFrom};
pub use telegram_bot_raw::{MessageEntity, MessageEntityKind};
pub use telegram_bot_raw::{Audio, Document, PhotoSize, Sticker, Video, Voice};
pub use telegram_bot_raw::{Contact, Location, Venue, File, FileRef};
pub use telegram_bot_raw::{ToChatRef, ToUserId, ToMessageId, ToSourceChat, ToFileRef};

pub use telegram_bot_raw::{ParseMode};
pub use telegram_bot_raw::{ReplyMarkup, ReplyKeyboardMarkup, KeyboardButton};
pub use telegram_bot_raw::{InlineKeyboardMarkup, InlineKeyboardButton};
pub use telegram_bot_raw::{ReplyKeyboardRemove, ForceReply};
pub use telegram_bot_raw::{ChatAction};
<commit_msg>feat: reexport ToCallbackQueryId<commit_after>//! Telegram bot types.

pub mod requests;
pub use requests::*;

pub use telegram_bot_raw::{Integer, Float, Request, DetachedRequest};
pub use telegram_bot_raw::{ResponseType, JsonResponse, JsonIdResponse, JsonTrueToUnitResponse};
pub use telegram_bot_raw::{Update, UpdateKind};
pub use telegram_bot_raw::{User, Group, Supergroup, Channel, Chat};
pub use telegram_bot_raw::{UserId, GroupId, SupergroupId, ChannelId, ChatId, ChatRef};
pub use telegram_bot_raw::{CallbackQuery, CallbackQueryId};
pub use telegram_bot_raw::{Message, MessageId, MessageKind, Forward, ForwardFrom};
pub use telegram_bot_raw::{MessageEntity, MessageEntityKind};
pub use telegram_bot_raw::{Audio, Document, PhotoSize, Sticker, Video, Voice};
pub use telegram_bot_raw::{Contact, Location, Venue, File, FileRef};
pub use telegram_bot_raw::{ToChatRef, ToUserId, ToMessageId, ToSourceChat, ToFileRef, ToCallbackQueryId};

pub use telegram_bot_raw::{ParseMode};
pub use telegram_bot_raw::{ReplyMarkup, ReplyKeyboardMarkup, KeyboardButton};
pub use telegram_bot_raw::{InlineKeyboardMarkup, InlineKeyboardButton};
pub use telegram_bot_raw::{ReplyKeyboardRemove, ForceReply};
pub use telegram_bot_raw::{ChatAction};
<|endoftext|>