<commit_before>#![feature(test)]

#[macro_use]
extern crate lazy_static;
extern crate test;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use test::Bencher;

extern crate hyphenation;
use hyphenation::{load, Corpus, Hyphenation, Language};
use hyphenation::exception::{Exceptions};
use hyphenation::pattern::{Patterns};

fn fiat_io(lang: Language) -> Corpus {
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push("patterns");

    hyphenation::set_pattern_folder(path.as_path());
    load::language(lang).unwrap()
}

lazy_static! {
    static ref DATAPATH: PathBuf = {
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("patterns");

        path
    };

    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[bench]
fn parse_patterns_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::patterns(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut ps = Patterns::empty();
    b.iter(|| {
        for p in &v {
            for val in p { ps.insert(&*val) };
        }
    });
}

#[bench]
fn parse_exceptions_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::exceptions(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut exs = Exceptions::empty();
    b.iter(|| {
        for ex in &v {
            for val in ex { exs.insert(&*val) };
        }
    });
}

#[bench]
fn opportunities_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.opportunities(&EN_US);
        }
    })
}

#[bench]
fn hyphenate_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.hyphenate(&EN_US).count();
        }
    })
}
<commit_msg>Reuse path constant in benchmarks<commit_after>#![feature(test)]

#[macro_use]
extern crate lazy_static;
extern crate test;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use test::Bencher;

extern crate hyphenation;
use hyphenation::{load, Corpus, Hyphenation, Language};
use hyphenation::exception::{Exceptions};
use hyphenation::pattern::{Patterns};

fn fiat_io(lang: Language) -> Corpus {
    hyphenation::set_pattern_folder(&DATAPATH.as_path());
    load::language(lang).unwrap()
}

lazy_static! {
    static ref DATAPATH: PathBuf = {
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("patterns");

        path
    };

    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[bench]
fn parse_patterns_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::patterns(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut ps = Patterns::empty();
    b.iter(|| {
        for p in &v {
            for val in p { ps.insert(&*val) };
        }
    });
}

#[bench]
fn parse_exceptions_en_us(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let by_line = load::exceptions(Language::English_US).unwrap();
    let v: Vec<_> = by_line.collect();

    let mut exs = Exceptions::empty();
    b.iter(|| {
        for ex in &v {
            for val in ex { exs.insert(&*val) };
        }
    });
}

#[bench]
fn opportunities_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.opportunities(&EN_US);
        }
    })
}

#[bench]
fn hyphenate_words(b: &mut Bencher) {
    hyphenation::set_pattern_folder(DATAPATH.as_path());
    let mut ws = WORDS.iter();

    b.iter(|| {
        for w in ws.by_ref() {
            w.hyphenate(&EN_US).count();
        }
    })
}
<|endoftext|>


<commit_before>extern crate pnet;
extern crate pnet_datalink;

use std::env;
use std::io::{self, Write};
use std::net::{AddrParseError, IpAddr, Ipv4Addr};
use std::process;

use pnet_datalink::{Channel, MacAddr, NetworkInterface};

use pnet::packet::arp::{ArpHardwareTypes, ArpOperations};
use pnet::packet::arp::{ArpPacket, MutableArpPacket};
use pnet::packet::ethernet::EtherTypes;
use pnet::packet::ethernet::MutableEthernetPacket;
use pnet::packet::{MutablePacket, Packet};

fn get_mac_through_arp(interface: NetworkInterface, target_ip: Ipv4Addr) -> MacAddr {
    let source_ip = interface
        .ips
        .iter()
        .find(|ip| ip.is_ipv4())
        .map(|ip| match ip.ip() {
            IpAddr::V4(ip) => ip,
            _ => unreachable!(),
        })
        .unwrap();

    let (mut sender, mut receiver) = match pnet_datalink::channel(&interface, Default::default()) {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unknown channel type"),
        Err(e) => panic!("Error happened {}", e),
    };

    let mut ethernet_buffer = [0u8; 42];
    let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();

    ethernet_packet.set_destination(MacAddr::broadcast());
    ethernet_packet.set_source(interface.mac_address());
    ethernet_packet.set_ethertype(EtherTypes::Arp);

    let mut arp_buffer = [0u8; 28];
    let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

    arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
    arp_packet.set_protocol_type(EtherTypes::Ipv4);
    arp_packet.set_hw_addr_len(6);
    arp_packet.set_proto_addr_len(4);
    arp_packet.set_operation(ArpOperations::Request);
    arp_packet.set_sender_hw_addr(interface.mac_address());
    arp_packet.set_sender_proto_addr(source_ip);
    arp_packet.set_target_hw_addr(MacAddr::zero());
    arp_packet.set_target_proto_addr(target_ip);

    ethernet_packet.set_payload(arp_packet.packet_mut());

    sender
        .send_to(ethernet_packet.packet(), None)
        .unwrap()
        .unwrap();

    println!("Sent ARP request");

    let buf = receiver.next().unwrap();

    let arp = ArpPacket::new(&buf[MutableEthernetPacket::minimum_packet_size()..]).unwrap();

    println!("Received reply");

    arp.get_sender_hw_addr()
}

fn main() {
    let mut args = env::args().skip(1);
    let iface_name = match args.next() {
        Some(n) => n,
        None => {
            writeln!(
                io::stderr(),
                "USAGE: packetdump <NETWORK INTERFACE> <TARGET IP>"
            )
            .unwrap();
            process::exit(1);
        }
    };

    let target_ip: Result<Ipv4Addr, AddrParseError> = match args.next() {
        Some(n) => n.parse(),
        None => {
            writeln!(
                io::stderr(),
                "USAGE: packetdump <NETWORK INTERFACE> <TARGET IP>"
            )
            .unwrap();
            process::exit(1);
        }
    };

    let interfaces = pnet_datalink::interfaces();
    let interface = interfaces
        .into_iter()
        .find(|iface| iface.name == iface_name)
        .unwrap();
    let _source_mac = interface.mac_address();

    let target_mac = get_mac_through_arp(interface, target_ip.unwrap());

    println!("Target MAC address: {}", target_mac);
}

<commit_msg>Typo fix in arp_packet example.<commit_after>extern crate pnet;
extern crate pnet_datalink;

use std::env;
use std::io::{self, Write};
use std::net::{AddrParseError, IpAddr, Ipv4Addr};
use std::process;

use pnet_datalink::{Channel, MacAddr, NetworkInterface};

use pnet::packet::arp::{ArpHardwareTypes, ArpOperations};
use pnet::packet::arp::{ArpPacket, MutableArpPacket};
use pnet::packet::ethernet::EtherTypes;
use pnet::packet::ethernet::MutableEthernetPacket;
use pnet::packet::{MutablePacket, Packet};

fn get_mac_through_arp(interface: NetworkInterface, target_ip: Ipv4Addr) -> MacAddr {
    let source_ip = interface
        .ips
        .iter()
        .find(|ip| ip.is_ipv4())
        .map(|ip| match ip.ip() {
            IpAddr::V4(ip) => ip,
            _ => unreachable!(),
        })
        .unwrap();

    let (mut sender, mut receiver) = match pnet_datalink::channel(&interface, Default::default()) {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unknown channel type"),
        Err(e) => panic!("Error happened {}", e),
    };

    let mut ethernet_buffer = [0u8; 42];
    let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();

    ethernet_packet.set_destination(MacAddr::broadcast());
    ethernet_packet.set_source(interface.mac_address());
    ethernet_packet.set_ethertype(EtherTypes::Arp);

    let mut arp_buffer = [0u8; 28];
    let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

    arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
    arp_packet.set_protocol_type(EtherTypes::Ipv4);
    arp_packet.set_hw_addr_len(6);
    arp_packet.set_proto_addr_len(4);
    arp_packet.set_operation(ArpOperations::Request);
    arp_packet.set_sender_hw_addr(interface.mac_address());
    arp_packet.set_sender_proto_addr(source_ip);
    arp_packet.set_target_hw_addr(MacAddr::zero());
    arp_packet.set_target_proto_addr(target_ip);

    ethernet_packet.set_payload(arp_packet.packet_mut());

    sender
        .send_to(ethernet_packet.packet(), None)
        .unwrap()
        .unwrap();

    println!("Sent ARP request");

    let buf = receiver.next().unwrap();

    let arp = ArpPacket::new(&buf[MutableEthernetPacket::minimum_packet_size()..]).unwrap();

    println!("Received reply");

    arp.get_sender_hw_addr()
}

fn main() {
    let mut args = env::args().skip(1);
    let iface_name = match args.next() {
        Some(n) => n,
        None => {
            writeln!(
                io::stderr(),
                "USAGE: arp_packet <NETWORK INTERFACE> <TARGET IP>"
            )
            .unwrap();
            process::exit(1);
        }
    };

    let target_ip: Result<Ipv4Addr, AddrParseError> = match args.next() {
        Some(n) => n.parse(),
        None => {
            writeln!(
                io::stderr(),
                "USAGE: arp_packet <NETWORK INTERFACE> <TARGET IP>"
            )
            .unwrap();
            process::exit(1);
        }
    };

    let interfaces = pnet_datalink::interfaces();
    let interface = interfaces
        .into_iter()
        .find(|iface| iface.name == iface_name)
        .unwrap();
    let _source_mac = interface.mac_address();

    let target_mac = get_mac_through_arp(interface, target_ip.unwrap());

    println!("Target MAC address: {}", target_mac);
}

<|endoftext|>


<commit_before>use std::{fmt, path::Path};

use async_trait::async_trait;
use language_tags::LanguageTag;
use serde::{Deserialize, Serialize};

use crate::{build::BuildStep, bundle::KbdgenBundle};

const REPOSITORY: &str = "repo";
const HOSTING_APP: &str = "HostingApp";
const INFO_PLIST_STRINGS: &str = "InfoPlist.strings";

const KEYBOARD: &str = "Keyboard";
const NORTHERN_SAMI: &str = "northern-sami-keyboard";
const INFO_PLIST: &str = "Info.plist";

#[derive(Serialize, Deserialize, Debug)]
pub struct XcodeInfoPlist {
    #[serde(rename = "CFBundleName")]
    cf_bundle_name: String,
    #[serde(rename = "CFBundleDisplayName")]
    cf_bundle_display_name: String,
}

impl fmt::Display for XcodeInfoPlist {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(&format!(
            "\"CFBundleName\" = {:?};\n\"CFBundleDisplayName\" = {:?};",
            self.cf_bundle_name, self.cf_bundle_display_name
        ))
    }
}

// LAYOUT PLIST START

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlistExtensionAttributes {
    #[serde(rename = "IsASCIICapable")]
    is_ascii_capable: bool,
    #[serde(rename = "PrefersRightToLeft")]
    prefers_right_to_left: bool,
    #[serde(rename = "PrimaryLanguage")]
    primary_language: String,
    #[serde(rename = "RequestsOpenAccess")]
    requests_open_access: bool,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlistExtension {
    #[serde(rename = "NSExtensionAttributes")]
    ns_extension_attributes: LayoutInfoPlistExtensionAttributes,
    #[serde(rename = "NSExtensionPointIdentifier")]
    ns_extension_point_identifier: String,
    #[serde(rename = "NSExtensionPrincipalClass")]
    ns_extension_principal_class: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlist {
    #[serde(rename = "DivvunSpellerPath")]
    divvun_speller_path: String,
    #[serde(rename = "DivvunSpellerPackageKey")]
    divvun_speller_package_key: String,
    #[serde(rename = "CFBundleDevelopmentRegion")]
    cf_bundle_development_region: String,
    #[serde(rename = "CFBundleDisplayName")]
    cf_bundle_display_name: String,
    #[serde(rename = "CFBundleExecutable")]
    cf_bundle_executable: String,
    #[serde(rename = "CFBundleIdentifier")]
    cf_bundle_identifier: String,
    #[serde(rename = "CFBundleInfoDictionaryVersion")]
    cf_bundle_info_dictionary_version: String,
    #[serde(rename = "CFBundleName")]
    cf_bundle_name: String,
    #[serde(rename = "CFBundlePackageType")]
    cf_bundle_package_type: String,
    #[serde(rename = "CFBundleShortVersionString")]
    cf_bundle_short_version_string: String,
    #[serde(rename = "CFBundleSignature")]
    cf_bundle_signature: String,
    #[serde(rename = "CFBundleVersion")]
    cf_bundle_version: String,
    #[serde(rename = "DivvunKeyboardIndex")]
    divvun_keyboard_index: usize,
    #[serde(rename = "ITSAppUsesNonExemptEncryption")]
    its_app_uses_non_exempt_encryption: bool,
    #[serde(rename = "LSApplicationQueriesSchemes")]
    ls_application_queries_schemes: Vec<String>,
    #[serde(rename = "NSExtension")]
    ns_extension: LayoutInfoPlistExtension,
}

// LAYOUT PLIST END
pub struct GenerateXcode;

#[async_trait(?Send)]
impl BuildStep for GenerateXcode {
    async fn build(&self, bundle: &KbdgenBundle, output_path: &Path) {
        let repository_path = output_path.join(REPOSITORY);

        // let file = File::open(info_path).unwrap();
        // let xml_info = Document::from_file(file);

        // GENERATE LOCALES
        for (layout_index, (language_tag, layout)) in bundle.layouts.iter().enumerate() {
            if let Some(ios_target) = &bundle.targets.ios {
                if let Some(_ios_layout) = &layout.i_os {
                    for (locale_name, locale_info) in &bundle.project.locales {
                        let hosting_app_path = repository_path.join(HOSTING_APP);
                        let locale_name = if locale_name == "en" {
                            "Base"
                        } else {
                            locale_name
                        };
                        let locale_path = hosting_app_path.join(&format!("{}.lproj", locale_name));
                        let info_path = locale_path.join(INFO_PLIST_STRINGS);
                        println!("{:?}", locale_path);

                        std::fs::create_dir_all(&locale_path).unwrap();

                        let info_plist = XcodeInfoPlist {
                            cf_bundle_name: locale_info.name.to_string(),
                            cf_bundle_display_name: locale_info.name.to_string(),
                        };
                        std::fs::write(info_path, info_plist.to_string()).unwrap();

                        let keyboard_path = repository_path.join(KEYBOARD);
                        let info_plist_template = keyboard_path.join(INFO_PLIST);

                        let layout_path = keyboard_path.join(NORTHERN_SAMI);
                        let layout_info_plist_path = layout_path.join(INFO_PLIST);

                        std::fs::create_dir_all(&layout_path).unwrap();

                        let mut parsed_plist: LayoutInfoPlist =
                            plist::from_file(info_plist_template.clone()).expect("valid stuff");

                        parsed_plist.cf_bundle_display_name = layout.autonym().to_string();
                        parsed_plist.cf_bundle_short_version_string = ios_target.version.clone();
                        parsed_plist.cf_bundle_version = ios_target.build.clone();
                        parsed_plist.ls_application_queries_schemes[0] = ios_target.package_id.clone();
                        parsed_plist
                            .ns_extension
                            .ns_extension_attributes
                            .primary_language = language_tag.to_string();
                        parsed_plist.divvun_keyboard_index = layout_index;

                        plist::to_file_xml(layout_info_plist_path.clone(), &parsed_plist).unwrap();
                    }
                }
            }
        }
    }
}<commit_msg>generate keyboard name from project<commit_after>use std::{cmp::Ordering, fmt, path::Path};

use async_trait::async_trait;
use language_tags::LanguageTag;
use regex::Regex;
use serde::{Deserialize, Serialize};

use crate::{build::BuildStep, bundle::KbdgenBundle};

const REPOSITORY: &str = "repo";
const HOSTING_APP: &str = "HostingApp";
const INFO_PLIST_STRINGS: &str = "InfoPlist.strings";

const KEYBOARD: &str = "Keyboard";
const NORTHERN_SAMI: &str = "northern-sami-keyboard";
const INFO_PLIST: &str = "Info.plist";

#[derive(Serialize, Deserialize, Debug)]
pub struct XcodeInfoPlist {
    #[serde(rename = "CFBundleName")]
    cf_bundle_name: String,
    #[serde(rename = "CFBundleDisplayName")]
    cf_bundle_display_name: String,
}

impl fmt::Display for XcodeInfoPlist {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(&format!(
            "\"CFBundleName\" = {:?};\n\"CFBundleDisplayName\" = {:?};",
            self.cf_bundle_name, self.cf_bundle_display_name
        ))
    }
}

// LAYOUT PLIST START

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlistExtensionAttributes {
    #[serde(rename = "IsASCIICapable")]
    is_ascii_capable: bool,
    #[serde(rename = "PrefersRightToLeft")]
    prefers_right_to_left: bool,
    #[serde(rename = "PrimaryLanguage")]
    primary_language: String,
    #[serde(rename = "RequestsOpenAccess")]
    requests_open_access: bool,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlistExtension {
    #[serde(rename = "NSExtensionAttributes")]
    ns_extension_attributes: LayoutInfoPlistExtensionAttributes,
    #[serde(rename = "NSExtensionPointIdentifier")]
    ns_extension_point_identifier: String,
    #[serde(rename = "NSExtensionPrincipalClass")]
    ns_extension_principal_class: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutInfoPlist {
    #[serde(rename = "DivvunSpellerPath")]
    divvun_speller_path: String,
    #[serde(rename = "DivvunSpellerPackageKey")]
    divvun_speller_package_key: String,
    #[serde(rename = "CFBundleDevelopmentRegion")]
    cf_bundle_development_region: String,
    #[serde(rename = "CFBundleDisplayName")]
    cf_bundle_display_name: String,
    #[serde(rename = "CFBundleExecutable")]
    cf_bundle_executable: String,
    #[serde(rename = "CFBundleIdentifier")]
    cf_bundle_identifier: String,
    #[serde(rename = "CFBundleInfoDictionaryVersion")]
    cf_bundle_info_dictionary_version: String,
    #[serde(rename = "CFBundleName")]
    cf_bundle_name: String,
    #[serde(rename = "CFBundlePackageType")]
    cf_bundle_package_type: String,
    #[serde(rename = "CFBundleShortVersionString")]
    cf_bundle_short_version_string: String,
    #[serde(rename = "CFBundleSignature")]
    cf_bundle_signature: String,
    #[serde(rename = "CFBundleVersion")]
    cf_bundle_version: String,
    #[serde(rename = "DivvunKeyboardIndex")]
    divvun_keyboard_index: usize,
    #[serde(rename = "ITSAppUsesNonExemptEncryption")]
    its_app_uses_non_exempt_encryption: bool,
    #[serde(rename = "LSApplicationQueriesSchemes")]
    ls_application_queries_schemes: Vec<String>,
    #[serde(rename = "NSExtension")]
    ns_extension: LayoutInfoPlistExtension,
}

// LAYOUT PLIST END

pub fn replace_all_occurances(input: String, character: char, replace_with: char) -> String {
    input
        .as_str()
        .chars()
        .map(|curr| {
            if curr.cmp(&character) != Ordering::Equal {
                curr
            } else {
                replace_with
            }
        })
        .into_iter()
        .collect::<String>()
}

pub struct GenerateXcode;

#[async_trait(?Send)]
impl BuildStep for GenerateXcode {
    async fn build(&self, bundle: &KbdgenBundle, output_path: &Path) {
        let repository_path = output_path.join(REPOSITORY);

        for (layout_index, (language_tag, layout)) in bundle.layouts.iter().enumerate() {
            if let Some(target) = &bundle.targets.ios {
                if let Some(_ios_layout) = &layout.i_os {
                    // GENERATE LOCALES
                    for (locale_name, locale_info) in &bundle.project.locales {
                        let hosting_app_path = repository_path.join(HOSTING_APP);
                        let locale_name = if locale_name == "en" {
                            "Base"
                        } else {
                            locale_name
                        };
                        let locale_path = hosting_app_path.join(&format!("{}.lproj", locale_name));
                        let info_path = locale_path.join(INFO_PLIST_STRINGS);
                        println!("{:?}", locale_path);

                        std::fs::create_dir_all(&locale_path).unwrap();

                        let info_plist = XcodeInfoPlist {
                            cf_bundle_name: locale_info.name.to_string(),
                            cf_bundle_display_name: locale_info.name.to_string(),
                        };
                        std::fs::write(info_path, info_plist.to_string()).unwrap();
                    }

                    // GENERATE LAYOUTS

                    let keyboard_name = replace_all_occurances(
                        bundle
                            .project
                            .locales
                            .get("en")
                            .unwrap()
                            .name
                            .to_lowercase(),
                        ' ',
                        '-',
                    );

                    let keyboard_path = repository_path.join(KEYBOARD);
                    let info_plist_template = keyboard_path.join(INFO_PLIST);

                    let layout_path = keyboard_path.join(keyboard_name);
                    let layout_info_plist_path = layout_path.join(INFO_PLIST);

                    std::fs::create_dir_all(&layout_path).unwrap();

                    let mut parsed_plist: LayoutInfoPlist =
                        plist::from_file(info_plist_template.clone()).expect("valid stuff");

                    parsed_plist.cf_bundle_display_name = layout.autonym().to_string();
                    parsed_plist.cf_bundle_short_version_string = target.version.clone();
                    parsed_plist.cf_bundle_version = target.build.clone();
                    parsed_plist.ls_application_queries_schemes[0] = target.package_id.clone();
                    parsed_plist
                        .ns_extension
                        .ns_extension_attributes
                        .primary_language = language_tag.to_string();
                    parsed_plist.divvun_keyboard_index = layout_index;

                    plist::to_file_xml(layout_info_plist_path.clone(), &parsed_plist).unwrap();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use serde::Serialize;
use serde_json::value::RawValue as RawJsonValue;

use crate::serde::Raw;

/// The base trait that all event content types implement.
///
/// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually.
pub trait EventContent: Sized + Serialize {
    /// The Rust enum for the event kind's known types.
    type EventType;

    /// Get the event's type, like `m.room.message`.
    fn event_type(&self) -> Self::EventType;

    /// Constructs the given event content.
    #[doc(hidden)]
    fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self>;
}

impl<T> Raw<T>
where
    T: EventContent,
    T::EventType: fmt::Display,
{
    /// Try to deserialize the JSON as an event's content.
    pub fn deserialize_content(&self, event_type: T::EventType) -> serde_json::Result<T> {
        T::from_parts(&event_type.to_string(), self.json())
    }
}

/// The base trait that all redacted event content types implement.
///
/// This trait's associated functions and methods should not be used to build
/// redacted events, prefer the `redact` method on `AnyStateEvent` and
/// `AnyMessageLikeEvent` and their "sync" and "stripped" counterparts. The
/// `RedactedEventContent` trait is an implementation detail, ruma makes no
/// API guarantees.
pub trait RedactedEventContent: EventContent {
    /// Constructs the redacted event content.
    ///
    /// If called for anything but "empty" redacted content this will error.
    #[doc(hidden)]
    fn empty(_event_type: &str) -> serde_json::Result<Self> {
        Err(serde::de::Error::custom("this event is not redacted"))
    }

    /// Determines if the redacted event content needs to serialize fields.
    #[doc(hidden)]
    fn has_serialize_fields(&self) -> bool;

    /// Determines if the redacted event content needs to deserialize fields.
    #[doc(hidden)]
    fn has_deserialize_fields() -> HasDeserializeFields;
}

/// `HasDeserializeFields` is used in the code generated by the `Event` derive
/// to aid in deserializing redacted events.
#[doc(hidden)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub enum HasDeserializeFields {
    /// Deserialize the event's content, failing if invalid.
    True,

    /// Return the redacted version of this event's content.
    False,

    /// `Optional` is used for `RedactedAliasesEventContent` since it has
    /// an empty version and one with content left after redaction that
    /// must be supported together.
    Optional,
}

/// Trait for abstracting over event content structs.
///
/// … but *not* enums which don't always have an event type and kind (e.g. message vs state) that's
/// fixed / known at compile time.
pub trait StaticEventContent: EventContent {
    /// The event's "kind".
    ///
    /// See the type's documentation.
    const KIND: EventKind;

    /// The event type.
    const TYPE: &'static str;
}

/// The "kind" of an event.
///
/// This corresponds directly to the event content marker traits.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum EventKind {
    /// Global account data event kind.
    GlobalAccountData,

    /// Room account data event kind.
    RoomAccountData,

    /// Ephemeral room event kind.
    EphemeralRoomData,

    /// Message-like event kind.
    ///
    /// Since redacted / non-redacted message-like events are used in the same places but have
    /// different sets of fields, these two variations are treated as two closely-related event
    /// kinds.
    MessageLike {
        /// Redacted variation?
        redacted: bool,
    },

    /// State event kind.
    ///
    /// Since redacted / non-redacted state events are used in the same places but have different
    /// sets of fields, these two variations are treated as two closely-related event kinds.
    State {
        /// Redacted variation?
        redacted: bool,
    },

    /// To-device event kind.
    ToDevice,

    /// Presence event kind.
    Presence,

    /// Hierarchy space child kind.
    HierarchySpaceChild,
}
<commit_msg>events: Remove unused EventKind<commit_after>use std::fmt;

use serde::Serialize;
use serde_json::value::RawValue as RawJsonValue;

use crate::serde::Raw;

/// The base trait that all event content types implement.
///
/// Use [`macros::EventContent`] to derive this traits. It is not meant to be implemented manually.
pub trait EventContent: Sized + Serialize {
    /// The Rust enum for the event kind's known types.
    type EventType;

    /// Get the event's type, like `m.room.message`.
    fn event_type(&self) -> Self::EventType;

    /// Constructs the given event content.
    #[doc(hidden)]
    fn from_parts(event_type: &str, content: &RawJsonValue) -> serde_json::Result<Self>;
}

impl<T> Raw<T>
where
    T: EventContent,
    T::EventType: fmt::Display,
{
    /// Try to deserialize the JSON as an event's content.
    pub fn deserialize_content(&self, event_type: T::EventType) -> serde_json::Result<T> {
        T::from_parts(&event_type.to_string(), self.json())
    }
}

/// The base trait that all redacted event content types implement.
///
/// This trait's associated functions and methods should not be used to build
/// redacted events, prefer the `redact` method on `AnyStateEvent` and
/// `AnyMessageLikeEvent` and their "sync" and "stripped" counterparts. The
/// `RedactedEventContent` trait is an implementation detail, ruma makes no
/// API guarantees.
pub trait RedactedEventContent: EventContent {
    /// Constructs the redacted event content.
    ///
    /// If called for anything but "empty" redacted content this will error.
    #[doc(hidden)]
    fn empty(_event_type: &str) -> serde_json::Result<Self> {
        Err(serde::de::Error::custom("this event is not redacted"))
    }

    /// Determines if the redacted event content needs to serialize fields.
    #[doc(hidden)]
    fn has_serialize_fields(&self) -> bool;

    /// Determines if the redacted event content needs to deserialize fields.
    #[doc(hidden)]
    fn has_deserialize_fields() -> HasDeserializeFields;
}

/// `HasDeserializeFields` is used in the code generated by the `Event` derive
/// to aid in deserializing redacted events.
#[doc(hidden)]
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub enum HasDeserializeFields {
    /// Deserialize the event's content, failing if invalid.
    True,

    /// Return the redacted version of this event's content.
    False,

    /// `Optional` is used for `RedactedAliasesEventContent` since it has
    /// an empty version and one with content left after redaction that
    /// must be supported together.
    Optional,
}

/// Trait for abstracting over event content structs.
///
/// … but *not* enums which don't always have an event type and kind (e.g. message vs state) that's
/// fixed / known at compile time.
pub trait StaticEventContent: EventContent {
    /// The event's "kind".
    ///
    /// See the type's documentation.
    const KIND: EventKind;

    /// The event type.
    const TYPE: &'static str;
}

/// The "kind" of an event.
///
/// This corresponds directly to the event content marker traits.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum EventKind {
    /// Global account data event kind.
    GlobalAccountData,

    /// Room account data event kind.
    RoomAccountData,

    /// Ephemeral room event kind.
    EphemeralRoomData,

    /// Message-like event kind.
    ///
    /// Since redacted / non-redacted message-like events are used in the same places but have
    /// different sets of fields, these two variations are treated as two closely-related event
    /// kinds.
    MessageLike {
        /// Redacted variation?
        redacted: bool,
    },

    /// State event kind.
    ///
    /// Since redacted / non-redacted state events are used in the same places but have different
    /// sets of fields, these two variations are treated as two closely-related event kinds.
    State {
        /// Redacted variation?
        redacted: bool,
    },

    /// To-device event kind.
    ToDevice,

    /// Presence event kind.
    Presence,
}
<|endoftext|>


<commit_before>//! Types for extensible text message events ([MSC1767]).
//!
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

mod content_serde;

use content_serde::MessageContentSerDeHelper;

use super::room::message::Relation;

/// Text message content.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Text {
    /// The mime type of the `body`.
    #[serde(default = "Text::default_mimetype")]
    pub mimetype: String,

    /// The text content.
    pub body: String,
}

impl Text {
    /// Creates a new plain text message body.
    pub fn plain(body: impl Into<String>) -> Self {
        Self { mimetype: "text/plain".to_owned(), body: body.into() }
    }

    /// Creates a new HTML-formatted message body.
    pub fn html(body: impl Into<String>) -> Self {
        Self { mimetype: "text/html".to_owned(), body: body.into() }
    }

    /// Creates a new HTML-formatted message body by parsing the Markdown in `body`.
    ///
    /// Returns `None` if no Markdown formatting was found.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str>) -> Option<Self> {
        let body = body.as_ref();
        let mut html_body = String::new();

        pulldown_cmark::html::push_html(&mut html_body, pulldown_cmark::Parser::new(body));

        (html_body != format!("
{}
\n", body)).then(|| Self::html(html_body))
    }

    fn default_mimetype() -> String {
        "text/plain".to_owned()
    }
}

/// Text message content.
#[derive(Clone, Debug, Deserialize)]
#[serde(try_from = "MessageContentSerDeHelper")]
pub struct MessageContent(pub(crate) Vec<Text>);

impl MessageContent {
    /// A convenience constructor to create a plain text message.
    pub fn plain(body: impl Into<String>) -> Self {
        Self(vec![Text::plain(body)])
    }

    /// A convenience constructor to create an HTML message.
    pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
        Self(vec![Text::html(html_body), Text::plain(body)])
    }

    /// A convenience constructor to create a Markdown message.
    ///
    /// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
    /// text message.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
        let mut message = Vec::with_capacity(2);
        if let Some(html_body) = Text::markdown(&body) {
            message.push(html_body);
        }
        message.push(Text::plain(body));
        Self(message)
    }

    /// Get the plain text representation of this message.
    pub fn find_plain(&self) -> Option<&str> {
        self.variants()
            .iter()
            .find(|content| content.mimetype == "text/plain")
            .map(|content| content.body.as_ref())
    }

    /// Get the HTML representation of this message.
    pub fn find_html(&self) -> Option<&str> {
        self.variants()
            .iter()
            .find(|content| content.mimetype == "text/html")
            .map(|content| content.body.as_ref())
    }

    /// Get all the text representations of this message.
    pub fn variants(&self) -> &[Text] {
        &self.0
    }
}

/// The payload for an extensible text message.
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.message", kind = MessageLike)]
pub struct MessageEventContent {
    /// The message's text content.
    #[serde(flatten)]
    pub message: MessageContent,

    /// Information about related messages for [rich replies].
    ///
    /// [rich replies]: https://spec.matrix.org/v1.2/client-server-api/#rich-replies
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub relates_to: Option<Relation>,
}

impl MessageEventContent {
    /// A convenience constructor to create a plain text message.
    pub fn plain(body: impl Into<String>) -> Self {
        Self { message: MessageContent::plain(body), relates_to: None }
    }

    /// A convenience constructor to create an HTML message.
    pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
        Self { message: MessageContent::html(body, html_body), relates_to: None }
    }

    /// A convenience constructor to create a Markdown message.
    ///
    /// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
    /// text message.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
        Self { message: MessageContent::markdown(body), relates_to: None }
    }
}
<commit_msg>common: Reorder events::message types<commit_after>//! Types for extensible text message events ([MSC1767]).
//!
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

mod content_serde;

use content_serde::MessageContentSerDeHelper;

use super::room::message::Relation;

/// The payload for an extensible text message.
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.message", kind = MessageLike)]
pub struct MessageEventContent {
    /// The message's text content.
    #[serde(flatten)]
    pub message: MessageContent,

    /// Information about related messages for [rich replies].
    ///
    /// [rich replies]: https://spec.matrix.org/v1.2/client-server-api/#rich-replies
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    pub relates_to: Option<Relation>,
}

impl MessageEventContent {
    /// A convenience constructor to create a plain text message.
    pub fn plain(body: impl Into<String>) -> Self {
        Self { message: MessageContent::plain(body), relates_to: None }
    }

    /// A convenience constructor to create an HTML message.
    pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
        Self { message: MessageContent::html(body, html_body), relates_to: None }
    }

    /// A convenience constructor to create a Markdown message.
    ///
    /// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
    /// text message.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
        Self { message: MessageContent::markdown(body), relates_to: None }
    }
}

/// Text message content.
#[derive(Clone, Debug, Deserialize)]
#[serde(try_from = "MessageContentSerDeHelper")]
pub struct MessageContent(pub(crate) Vec<Text>);

impl MessageContent {
    /// A convenience constructor to create a plain text message.
    pub fn plain(body: impl Into<String>) -> Self {
        Self(vec![Text::plain(body)])
    }

    /// A convenience constructor to create an HTML message.
    pub fn html(body: impl Into<String>, html_body: impl Into<String>) -> Self {
        Self(vec![Text::html(html_body), Text::plain(body)])
    }

    /// A convenience constructor to create a Markdown message.
    ///
    /// Returns an HTML message if some Markdown formatting was detected, otherwise returns a plain
    /// text message.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
        let mut message = Vec::with_capacity(2);
        if let Some(html_body) = Text::markdown(&body) {
            message.push(html_body);
        }
        message.push(Text::plain(body));
        Self(message)
    }

    /// Get the plain text representation of this message.
    pub fn find_plain(&self) -> Option<&str> {
        self.variants()
            .iter()
            .find(|content| content.mimetype == "text/plain")
            .map(|content| content.body.as_ref())
    }

    /// Get the HTML representation of this message.
    pub fn find_html(&self) -> Option<&str> {
        self.variants()
            .iter()
            .find(|content| content.mimetype == "text/html")
            .map(|content| content.body.as_ref())
    }

    /// Get all the text representations of this message.
    pub fn variants(&self) -> &[Text] {
        &self.0
    }
}

/// Text message content.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Text {
    /// The mime type of the `body`.
    #[serde(default = "Text::default_mimetype")]
    pub mimetype: String,

    /// The text content.
    pub body: String,
}

impl Text {
    /// Creates a new plain text message body.
    pub fn plain(body: impl Into<String>) -> Self {
        Self { mimetype: "text/plain".to_owned(), body: body.into() }
    }

    /// Creates a new HTML-formatted message body.
    pub fn html(body: impl Into<String>) -> Self {
        Self { mimetype: "text/html".to_owned(), body: body.into() }
    }

    /// Creates a new HTML-formatted message body by parsing the Markdown in `body`.
    ///
    /// Returns `None` if no Markdown formatting was found.
    #[cfg(feature = "markdown")]
    pub fn markdown(body: impl AsRef<str>) -> Option<Self> {
        let body = body.as_ref();
        let mut html_body = String::new();

        pulldown_cmark::html::push_html(&mut html_body, pulldown_cmark::Parser::new(body));

        (html_body != format!("
{}
\n", body)).then(|| Self::html(html_body))
    }

    fn default_mimetype() -> String {
        "text/plain".to_owned()
    }
}
<|endoftext|>


<commit_before>extern crate serialport;

use std::collections::HashMap;
use std::num::Wrapping;
use std::rc::Weak;
use std::sync::mpsc::{Sender, Receiver, TryRecvError};
use std::sync::mpsc;
use std::thread;
use std::thread::JoinHandle;
use std::time::Duration;

use serialport as sp;

use serial_support::common::*;
use serial_support::messages::*;

/// Convenience type for a listener
/// that accepts weak refs of Senders of Serial Reponses
/// This is how the manager will communicate
/// results back to the websockets
type SubscReceiver = Receiver<Weak<Sender<SerialResponse>>>;

/// Struct for containing Port information
pub struct OpenPort<'a> {
  /// The opened serial port
  port: &'a mut sp::SerialPort,
  /// Handle that controls writes to port
  write_handle: String,
  /// Send channel used to send responses to
  /// all clients who opened the port
  clients: &'a mut Vec<Sender<SerialResponse>>,
}

/// Manages tracking and reading/writing from serial
/// ports
struct SerialPortManager<'a> {
  /// Maintains list of ports
  open_ports: HashMap<String, OpenPort<'a>>,
  /// Receiver for serial requests
  receiver: Receiver<SerialRequest>,
  /// Receiver for response subscription requests
  subsc_receiver: SubscReceiver,
}

impl<'a> SerialPortManager<'a> {
  fn open_port(&self, port: String) {
    // Check if port is already open

    // If not, open it
    let spSettings = sp::SerialPortSettings {
      baud_rate: sp::BaudRate::Baud115200,
      data_bits: sp::DataBits::Eight,
      flow_control: sp::FlowControl::None,
      parity: sp::Parity::None,
      stop_bits: sp::StopBits::One,
      timeout: Duration::from_millis(1),
    };

  }

  fn add_sender(&self, port: String, sender: Sender<SerialResponse>) {}

  fn release_write_lock(&self, handle: String, port: Option<String>) {}

  fn add_write_lock(&self, handle: String, port: String) {}

  fn write_port(&self, handle: String, port: String, data: String, base64: Option<bool>) {}

  fn close_port(&self, port: String) {}

  /// Handles and dispatches SerialRequest sent by
  /// the channel
  fn handle_serial_request(&self, msg: SerialRequest) {
    match msg {
      SerialRequest::Open { port } => self.open_port(port),
      SerialRequest::WriteLock { handle, port } => self.add_write_lock(handle, port),
      SerialRequest::ReleaseWriteLock { handle, port } => self.release_write_lock(handle, port),
      SerialRequest::Write {
        handle,
        port,
        data,
        base64,
      } => self.write_port(handle, port, data, base64),
      SerialRequest::Close { port } => self.close_port(port),
    }
  }

  /// Fire up the port manager
  ///
  /// TODO Right now this is spinning a thread between reading
  /// subscription requests, reading serial port data
  /// etc. This will cause high cpu usage
  ///
  /// TODO Once this is working, refactor to avoid
  /// thread spinning?
  ///
  fn run(&mut self) {

    let mut shutdown = false;
    let sleep_dur = Duration::from_millis(50);
    let mut serial_buf: Vec<u8> = vec![0; 4096];

    while !shutdown {
      // Sleep for a little bit to avoid pegging cpu
      thread::sleep(sleep_dur);

      // Handle serial operation requests
      match self.receiver.try_recv(){
        Err(e) => {
          match e {
            TryRecvError::Empty => {
              // nothing to do
            }
            TryRecvError::Disconnected => {
              // Remote end hung up, time to shutdown
              info!("Shutting down SerialPortManager");
            }
          }
        }
        Ok(req) => self.handle_serial_request(req)
      }

      // Check for new data on each port
      for (portName, openPort) in self.open_ports.iter_mut() {
        // If we have data, send it back
        let bytes_read = openPort.port.read(serial_buf.as_mut_slice());
        // Remove all dead weak references
        // TODO SEND THE DATA
        // openPort.clients.retain(|r| r.upgrade().is_some());
        // for client in openPort.clients.iter_mut(){
        //   match client.upgrade() {
        //     Some(v) => {}
        //     _ => {}
        //   }
        // }
      }

      // Check for Subscribe requests
      match self.subsc_receiver.try_recv() {
        Err(e) => {
          match e {
            TryRecvError::Empty => {
              // nothing to do
            }
            TryRecvError::Disconnected => {
              // Remote end hung up, time to shutdown
              shutdown = true;
              info!("Shutting down SerialPortManager");
            }
          }
        }
        Ok(subs) => {

        }
      }
    }
  }
}

// TODO How to spawn and fire it up
// TODO Document that closing subscription sender will result in
// portmanager shutdown.
// fn spawnManager() -> {}
<commit_msg>Still working on guts, fighting lifetime types<commit_after>
use std::collections::HashMap;
use std::num::Wrapping;
use std::rc::Weak;
use std::sync::mpsc::{Sender, Receiver, TryRecvError};
use std::sync::mpsc;
use std::thread;
use std::thread::JoinHandle;
use std::time::Duration;

use serialport as sp;
use base64;

use serial_support::common::*;
use serial_support::messages::*;

/// Convenience type for a listener
/// that accepts weak refs of Senders of Serial Reponses
/// This is how the manager will communicate
/// results back to the websockets
type SubscReceiver = Receiver<Sender<SerialResponse>>;

/// Struct for containing Port information
pub struct open_port<'a> {
  /// The opened serial port
  port: &'a sp::SerialPort,
  /// Handle that controls writes to port
  write_handle: String,
  /// Send channel used to send responses to
  /// all clients who opened the port
  clients: &'a Vec<Sender<SerialResponse>>,
}

/// Manages tracking and reading/writing from serial
/// ports
struct SerialPortManager<'a> {
  /// Maintains list of ports
  open_ports: &'a mut HashMap<String, open_port<'a>>,
  /// Receiver for serial requests
  receiver: Receiver<SerialRequest>,
  /// Receiver for response subscription requests
  subsc_receiver: SubscReceiver,
}

impl<'a> SerialPortManager<'a> {
  fn open_port(&self, port: String) {
    // Check if port is already open

    // If not, open it
    let spSettings = sp::SerialPortSettings {
      baud_rate: sp::BaudRate::Baud115200,
      data_bits: sp::DataBits::Eight,
      flow_control: sp::FlowControl::None,
      parity: sp::Parity::None,
      stop_bits: sp::StopBits::One,
      timeout: Duration::from_millis(1),
    };

  }

  fn add_sender(&self, port: String, sender: Sender<SerialResponse>) {}

  fn release_write_lock(&self, handle: String, port: Option<String>) {}

  fn add_write_lock(&self, handle: String, port: String) {}

  fn write_port(&self, handle: String, port: String, data: String, base64: bool) {}

  fn close_port(&self, port: String) {}

  /// Handles and dispatches SerialRequest sent by
  /// the channel
  fn handle_serial_request(&self, msg: SerialRequest) {
    match msg {
      SerialRequest::Open { port } => self.open_port(port),
      SerialRequest::WriteLock { handle, port } => self.add_write_lock(handle, port),
      SerialRequest::ReleaseWriteLock { handle, port } => self.release_write_lock(handle, port),
      SerialRequest::Write {
        handle,
        port,
        data,
        base64,
      } => self.write_port(handle, port, data, base64.unwrap_or(false)),
      SerialRequest::Close { port } => self.close_port(port),
    }
  }

  /// Fire up the port manager
  ///
  /// TODO Right now this is spinning a thread between reading
  /// subscription requests, reading serial port data
  /// etc. This will cause high cpu usage
  ///
  /// TODO Once this is working, refactor to avoid
  /// thread spinning?
  ///
  fn run(&self) {

    let mut shutdown = false;
    let sleep_dur = Duration::from_millis(50);
    let mut serial_buf: Vec<u8> = vec![0; 4096];

    while !shutdown {
      // Sleep for a little bit to avoid pegging cpu
      thread::sleep(sleep_dur);

      // Handle serial operation requests
      match self.receiver.try_recv(){
        Err(e) => {
          match e {
            TryRecvError::Empty => {
              // nothing to do
            }
            TryRecvError::Disconnected => {
              // Remote end hung up, time to shutdown
              info!("Shutting down SerialPortManager");
            }
          }
        }
        Ok(req) => self.handle_serial_request(req)
      }

      /*
      // Check for new data on each port
      for port_name in self.open_ports.keys() {
        let open_port = self.open_ports.get(port_name).unwrap();
        // If we have data, send it back
        // Read needs to borrow &mut self, so wrap port in RC?
        let result = match open_port.port.read(serial_buf.as_mut_slice()){
          Ok(bytes_read) => {
              let bytes = &serial_buf[0..bytes_read];
              match String::from_utf8(bytes.to_vec()) {
                Err(_)=>SerialResponse::Read{
                  port:port_name.to_string(),
                  data: base64::encode(bytes),
                  base64: Some(true)
                },
                Ok(s) =>SerialResponse::Read{
                  port:port_name.to_string(),
                  data: s,
                  base64: Some(false)
                }
              }
            },
          Err(_) => SerialResponse::Error{
              kind: ErrorType::ReadError,
              msg: "Error reading serial port '{}'".to_string(),
              detail: None,
              port: Some(port_name.to_string()),
              handle:None
            }
        };
        */
        // open_port.clients.each
        // for client in open_port.clients{
        //   client.send(result.clone());
        // }
      // }

      // Check for Subscribe requests
      match self.subsc_receiver.try_recv() {
        Err(e) => {
          match e {
            TryRecvError::Empty => {
              // nothing to do
            }
            TryRecvError::Disconnected => {
              // Remote end hung up, time to shutdown
              shutdown = true;
              info!("Shutting down SerialPortManager");
            }
          }
        }
        Ok(subs) => {

        }
      }
    }
  }
}

// TODO How to spawn and fire it up
// TODO Document that closing subscription sender will result in
// portmanager shutdown.
// fn spawnManager() -> {}
<|endoftext|>


<commit_before>//! Scheduling primitives for Uni.rs.
<commit_msg>libuni: Add definition of some thread related types<commit_after>//! Scheduling primitives for Uni.rs.

use alloc::boxed::Box;

use intrusive::link::Link;
use intrusive::list::{Node, Owner};

const DEFAULT_STACK_SIZE: usize = 8192;

pub struct Thread {
    t_impl: Box<ThreadImpl>,
}

impl Thread {
    pub fn spawn<F>(fun: F) -> Thread where F: Fn() -> () {
        Builder::new().spawn(fun)
    }
}

pub struct Builder {
    stack_size: usize,
}

impl Builder {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn stack_size(mut self, stack_size: usize) -> Builder {
        self.stack_size = stack_size;
        self
    }

    pub fn spawn<F>(self, _fun: F) -> Thread where F: Fn() -> () {
        let thread_impl = Box::new(ThreadImpl::new());

        Thread {
            t_impl: thread_impl,
        }
    }
}

impl Default for Builder {
    fn default() -> Self {
        Builder {
            stack_size: DEFAULT_STACK_SIZE,
        }
    }
}

struct ThreadImpl {
    prev: Link<ThreadImpl>,
    next: Link<ThreadImpl>,
}

impl ThreadImpl {
    pub fn new() -> Self {
        ThreadImpl {
            prev: Link::none(),
            next: Link::none(),
        }
    }
}

impl Node for ThreadImpl {
    #[inline]
    fn prev(&self) -> &Link<Self> {
        &self.prev
    }

    #[inline]
    fn next(&self) -> &Link<Self> {
        &self.next
    }

    #[inline]
    fn prev_mut(&mut self) -> &mut Link<Self> {
        &mut self.prev
    }

    #[inline]
    fn next_mut(&mut self) -> &mut Link<Self> {
        &mut self.prev
    }
}

// This trait cannot be implemented for Box in libintrusive as it must not
// depend on rust's liballoc
type ThreadImplBox = Box<ThreadImpl>;

impl Owner<ThreadImpl> for ThreadImplBox {
    #[inline]
    fn get(&self) -> &ThreadImpl {
        &**self
    }

    #[inline]
    fn get_mut(&mut self) -> &mut ThreadImpl {
        &mut **self
    }

    #[inline]
    fn take(self) {
        Box::into_raw(self);
    }

    unsafe fn from_raw_ptr(ptr: *mut ThreadImpl) -> Self {
        Box::from_raw(ptr)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use std::{
    fmt::{Display, Formatter},
    result,
};

use kvm_bindings::KVM_API_VERSION;
use kvm_ioctls::Kvm;

/// Errors associated with the wrappers over KVM ioctls.
#[derive(Debug)]
pub enum Error {
    /// The host kernel reports an invalid KVM API version.
    KvmApiVersion(i32),
    /// Cannot initialize the KVM context due to missing capabilities.
    KvmCap(kvm_ioctls::Cap),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        use self::Error::*;

        match self {
            KvmApiVersion(v) => write!(
                f,
                "The host kernel reports an invalid KVM API version: {}",
                v
            ),
            KvmCap(cap) => write!(f, "Missing KVM capabilities: {:?}", cap),
        }
    }
}

type Result<T> = result::Result<T, Error>;

/// Describes a KVM context that gets attached to the microVM.
/// It gives access to the functionality of the KVM wrapper as
/// long as every required KVM capability is present on the host.
pub struct KvmContext {
    kvm: Kvm,
    max_memslots: usize,
}

impl KvmContext {
    pub fn new() -> Result<Self> {
        use kvm_ioctls::Cap::*;
        let kvm = Kvm::new().expect("Error creating the Kvm object");

        // Check that KVM has the correct version.
        if kvm.get_api_version() != KVM_API_VERSION as i32 {
            return Err(Error::KvmApiVersion(kvm.get_api_version()));
        }

        // A list of KVM capabilities we want to check.
        #[cfg(target_arch = "x86_64")]
        let capabilities = vec![
            Irqchip,
            Ioeventfd,
            Irqfd,
            UserMemory,
            SetTssAddr,
            Pit2,
            PitState2,
            AdjustClock,
            Debugregs,
            MpState,
            VcpuEvents,
            Xcrs,
            Xsave,
            ExtCpuid,
        ];

        #[cfg(target_arch = "aarch64")]
        let capabilities = vec![
            Ioeventfd, Irqfd, UserMemory, ArmPsci02, DeviceCtrl, MpState, OneReg,
        ];

        // Check that all desired capabilities are supported.
        match capabilities
            .iter()
            .find(|&capability| !kvm.check_extension(*capability))
        {
            None => {
                let max_memslots = kvm.get_nr_memslots();
                Ok(KvmContext { kvm, max_memslots })
            }

            Some(c) => Err(Error::KvmCap(*c)),
        }
    }

    pub fn fd(&self) -> &Kvm {
        &self.kvm
    }

    /// Get the maximum number of memory slots reported by this KVM context.
    pub fn max_memslots(&self) -> usize {
        self.max_memslots
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;

    use super::*;

    #[test]
    fn test_kvm_context() {
        use std::os::unix::fs::MetadataExt;
        use std::os::unix::io::{AsRawFd, FromRawFd};

        let c = KvmContext::new().unwrap();

        assert!(c.max_memslots() >= 32);

        let kvm = Kvm::new().unwrap();
        let f = unsafe { File::from_raw_fd(kvm.as_raw_fd()) };
        let m1 = f.metadata().unwrap();
        let m2 = File::open("/dev/kvm").unwrap().metadata().unwrap();

        assert_eq!(m1.dev(), m2.dev());
        assert_eq!(m1.ino(), m2.ino());
    }
}
<commit_msg>Add KVM init error with Permission denied details<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use std::{
    fmt::{Display, Formatter},
    result,
};

use kvm_bindings::KVM_API_VERSION;
use kvm_ioctls::{Error as KvmIoctlsError, Kvm};

/// Errors associated with the wrappers over KVM ioctls.
#[derive(Debug)]
pub enum Error {
    /// The host kernel reports an invalid KVM API version.
    KvmApiVersion(i32),
    /// Cannot initialize the KVM context due to missing capabilities.
    KvmCap(kvm_ioctls::Cap),
    /// Cannot initialize the KVM context.
    KvmInit(KvmIoctlsError),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        use self::Error::*;

        match self {
            KvmApiVersion(v) => write!(
                f,
                "The host kernel reports an invalid KVM API version: {}",
                v
            ),
            KvmCap(cap) => write!(f, "Missing KVM capabilities: {:?}", cap),
            KvmInit(err) => {
                if err.errno() == libc::EACCES {
                    write!(
                        f,
                        "Error creating KVM object. [{}]\n\
                         Make sure the user launching the firecracker process \
                         is configured on the /dev/kvm file's ACL.",
                        err
                    )
                } else {
                    write!(f, "Error creating KVM object. [{}]", err)
                }
            }
        }
    }
}

type Result<T> = result::Result<T, Error>;

/// Describes a KVM context that gets attached to the microVM.
/// It gives access to the functionality of the KVM wrapper as
/// long as every required KVM capability is present on the host.
pub struct KvmContext {
    kvm: Kvm,
    max_memslots: usize,
}

impl KvmContext {
    pub fn new() -> Result<Self> {
        use kvm_ioctls::Cap::*;
        let kvm = Kvm::new().map_err(Error::KvmInit)?;

        // Check that KVM has the correct version.
        if kvm.get_api_version() != KVM_API_VERSION as i32 {
            return Err(Error::KvmApiVersion(kvm.get_api_version()));
        }

        // A list of KVM capabilities we want to check.
        #[cfg(target_arch = "x86_64")]
        let capabilities = vec![
            Irqchip,
            Ioeventfd,
            Irqfd,
            UserMemory,
            SetTssAddr,
            Pit2,
            PitState2,
            AdjustClock,
            Debugregs,
            MpState,
            VcpuEvents,
            Xcrs,
            Xsave,
            ExtCpuid,
        ];

        #[cfg(target_arch = "aarch64")]
        let capabilities = vec![
            Ioeventfd, Irqfd, UserMemory, ArmPsci02, DeviceCtrl, MpState, OneReg,
        ];

        // Check that all desired capabilities are supported.
        match capabilities
            .iter()
            .find(|&capability| !kvm.check_extension(*capability))
        {
            None => {
                let max_memslots = kvm.get_nr_memslots();
                Ok(KvmContext { kvm, max_memslots })
            }

            Some(c) => Err(Error::KvmCap(*c)),
        }
    }

    pub fn fd(&self) -> &Kvm {
        &self.kvm
    }

    /// Get the maximum number of memory slots reported by this KVM context.
    pub fn max_memslots(&self) -> usize {
        self.max_memslots
    }
}

#[cfg(test)]
mod tests {
    use std::fs::File;

    use super::*;

    #[test]
    fn test_kvm_context() {
        use std::os::unix::fs::MetadataExt;
        use std::os::unix::io::{AsRawFd, FromRawFd};

        let c = KvmContext::new().unwrap();

        assert!(c.max_memslots() >= 32);

        let kvm = Kvm::new().unwrap();
        let f = unsafe { File::from_raw_fd(kvm.as_raw_fd()) };
        let m1 = f.metadata().unwrap();
        let m2 = File::open("/dev/kvm").unwrap().metadata().unwrap();

        assert_eq!(m1.dev(), m2.dev());
        assert_eq!(m1.ino(), m2.ino());
    }
}
<|endoftext|>


<commit_before>use primal_bit::{BitVec};
use std::{cmp};

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11];
const PRESIEVE_NEXT: usize = 13;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let mut current = match wheel::MODULO {
            6 => 5,
            30 => 7,
            210 => 11,
            _ => unimplemented!(),
        };
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = if PRESIEVE_ACTIVE {
            current = PRESIEVE_NEXT;
            compute_presieve(elems)
        } else {
            BitVec::new()
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        let top = bytes.len();

        for wi in self.primes.iter_mut() {
            let mut si = wi.sieve_index;
            let mut wi_ = wi.wheel_index;
            let p = wi.prime;
            while si < top {
                wheel::set_bit(bytes, &mut si, &mut wi_, p);
            }
            // if this wraps, we've hit the limit, and so won't be
            // continuing, so whatever, it can be junk.
            wi.sieve_index = si.wrapping_sub(top);
            wi.wheel_index = wi_;
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push(wheel::compute_wheel_elem(s, low));
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<commit_msg>sieve: presieve up to 13.<commit_after>use primal_bit::{BitVec};
use std::{cmp};

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11 * 13;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11, 13];
const PRESIEVE_NEXT: usize = 17;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let mut current = match wheel::MODULO {
            6 => 5,
            30 => 7,
            210 => 11,
            _ => unimplemented!(),
        };
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = if PRESIEVE_ACTIVE {
            current = PRESIEVE_NEXT;
            compute_presieve(elems)
        } else {
            BitVec::new()
        };

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        let top = bytes.len();

        for wi in self.primes.iter_mut() {
            let mut si = wi.sieve_index;
            let mut wi_ = wi.wheel_index;
            let p = wi.prime;
            while si < top {
                wheel::set_bit(bytes, &mut si, &mut wi_, p);
            }
            // if this wraps, we've hit the limit, and so won't be
            // continuing, so whatever, it can be junk.
            wi.sieve_index = si.wrapping_sub(top);
            wi.wheel_index = wi_;
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push(wheel::compute_wheel_elem(s, low));
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<|endoftext|>


<commit_before>pub const BYTE_SIZE: usize = 8;
pub const BYTE_MODULO: usize = 30;

pub fn bit_index(n: usize) -> (bool, usize) {
    const POS: &'static [(bool, u8); BYTE_MODULO] = &[
        // 0
        (false, 0), (true, 0), (false, 1), (false, 1), (false, 1), (false, 1),
        // 6
        (false, 1), (true, 1), (false, 2), (false, 2), (false, 2), (true, 2),
        // 12
        (false, 3), (true, 3), (false, 4), (false, 4), (false, 4), (true, 4),
        // 18
        (false, 5), (true, 5), (false, 6), (false, 6), (false, 6), (true, 6),
        // 24
        (false, 7), (false, 7), (false, 7), (false, 7), (false, 7), (true, 7),
        ];
    let init = &POS[n % BYTE_MODULO];
    (init.0, (n / BYTE_MODULO) * BYTE_SIZE + init.1 as usize)
}
pub fn from_bit_index(bit: usize) -> usize {
    const TRUE_AT_BIT: &'static [usize; 8] = &[
        1, 7, 11, 13, 17, 19, 23, 29
            ];
    (bit / BYTE_SIZE) * BYTE_MODULO + TRUE_AT_BIT[bit % BYTE_SIZE]
}

pub use self::wheel30::Wheel30;
pub use self::wheel210::Wheel210;

pub trait Wheel {
    fn modulo(&self) -> usize;
    fn size(&self) -> usize;
    fn wheel(&self) -> &'static [WheelElem];
    fn init(&self) -> &'static [WheelInit];
    unsafe fn hardcoded_sieve(&self,
                              bytes: &mut [u8], si_: &mut usize, wi_: &mut usize, prime: usize);
}

#[derive(Debug)]
pub struct WheelInfo<W> {
    wheel: W,
    true_prime: usize,
    prime: usize,
    wheel_index: usize,
    sieve_index: usize,
}
impl<W: Wheel> WheelInfo<W> {
    #[inline]
    pub fn sieve(&mut self, bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();

        let mut si = self.sieve_index;
        let mut wi = self.wheel_index;
        let p = self.prime;
        while si < top {
            raw_set_bit(self.wheel.wheel(),
                        bytes, &mut si, &mut wi, p)
        }
        self.sieve_index = si.wrapping_sub(top);
        self.wheel_index = wi;
    }
    #[inline]
    pub fn sieve_pair(&mut self, self2: &mut WheelInfo<W>, bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();
        let wheel = self.wheel.wheel();

        let mut si1 = self.sieve_index;
        let mut wi1 = self.wheel_index;
        let p1 = self.prime;
        let mut si2 = self2.sieve_index;
        let mut wi2 = self2.wheel_index;
        let p2 = self2.prime;

        while si1 < top && si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }
        while si1 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
        }
        while si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }

        // if this wraps, we've hit the limit, and so won't be
        // continuing, so whatever, it can be junk.
        self.sieve_index = si1.wrapping_sub(top);
        self.wheel_index = wi1;
        self2.sieve_index = si2.wrapping_sub(top);
        self2.wheel_index = wi2;
    }
    pub fn sieve_triple(&mut self, self2: &mut WheelInfo<W>, self3: &mut WheelInfo<W>,
                        bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();
        let wheel = self.wheel.wheel();

        let mut si1 = self.sieve_index;
        let mut wi1 = self.wheel_index;
        let p1 = self.prime;
        let mut si2 = self2.sieve_index;
        let mut wi2 = self2.wheel_index;
        let p2 = self2.prime;
        let mut si3 = self3.sieve_index;
        let mut wi3 = self3.wheel_index;
        let p3 = self3.prime;

        while si1 < top && si2 < top && si3 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
            raw_set_bit(wheel,
                        bytes, &mut si3, &mut wi3, p3);
        }
        while si1 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
        }
        while si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }
        while si3 < top {
            raw_set_bit(wheel,
                        bytes, &mut si3, &mut wi3, p3);
        }
        // if this wraps, we've hit the limit, and so won't be
        // continuing, so whatever, it can be junk.
        self.sieve_index = si1.wrapping_sub(top);
        self.wheel_index = wi1;
        self2.sieve_index = si2.wrapping_sub(top);
        self2.wheel_index = wi2;
        self3.sieve_index = si3.wrapping_sub(top);
        self3.wheel_index = wi3;
    }

    pub fn sieve_hardcoded(&mut self, bytes: &mut [u8]) {
        unsafe {
            self.wheel.hardcoded_sieve(bytes,
                                       &mut self.sieve_index, &mut self.wheel_index, self.prime)
        }
    }
}

#[derive(Debug)]
pub struct WheelInit {
    pub next_mult_factor: u8,
    pub wheel_index: u8,
}
#[macro_escape]
macro_rules! init {
    ($nmf: expr, $wi: expr) => { ::wheel::WheelInit { next_mult_factor: $nmf, wheel_index: $wi }}
}
#[derive(Debug)]
pub struct WheelElem {
    pub unset_bit: u8,
    pub next_mult_factor: u8,
    pub correction: u8,
    pub next: i8,
}

#[macro_escape]
macro_rules! count_ints {
    // count non-recursively, to avoid recursion limits
    ($($x: expr, )*) => { sum!($(0usize * $x as usize + 1usize,)*) }
}
#[macro_escape]
macro_rules! sum {
    ($($x: expr, )*) => { 0 $(+ $x)* }
}

#[macro_escape]
macro_rules! elems {
    ($([$($bit: expr, $nmf: expr, $c: expr, $n: expr;)*],)*) => {
        const WHEEL: &'static [::wheel::WheelElem; sum!($(count_ints!($($bit,)*),)*)] = &[
            $($(::wheel::WheelElem {
                unset_bit: 1u8 << $bit,
                next_mult_factor: $nmf,
                correction: $c,
                next: $n,
            },)*)*
                ];
    }
}

#[inline(always)]
fn raw_set_bit(wheel: &'static [WheelElem],
               x: &mut [u8], si: &mut usize, wi: &mut usize, prime: usize) {
    unsafe {
        let WheelElem { unset_bit, next_mult_factor, correction, next } =
            *wheel.get_unchecked(*wi);
        *x.get_unchecked_mut(*si) |= unset_bit;

        *si += prime * next_mult_factor as usize;
        *si += correction as usize;
        *wi = wi.wrapping_add(next as usize);
    }
}

const WHEEL_OFFSETS: &'static [usize; BYTE_MODULO] = &[
    0, 0, 0, 0, 0, 0,
    0, 1, 0, 0, 0, 2,
    0, 3, 0, 0, 0, 4,
    0, 5, 0, 0, 0, 6,
    0, 0, 0, 0, 0, 7,
    ];

#[inline(never)]
pub fn compute_wheel_elem<W: Wheel>(w: W, p: usize, low: usize) -> WheelInfo<W> {
    let mut mult = p * p;

    let init = &w.init()[p % w.modulo()];
    let next_mult_factor = init.next_mult_factor;
    mult += p * next_mult_factor as usize;

    let wheel_index = WHEEL_OFFSETS[p % BYTE_MODULO] * w.size();
    let sieve_index = mult * BYTE_SIZE / BYTE_MODULO / 8;

    let mut ret = WheelInfo {
        wheel: w,
        true_prime: p,
        prime: p / BYTE_MODULO,
        sieve_index: sieve_index,
        wheel_index: wheel_index,
    };
    // run the wheel until its above `low`... this is ugly and should be done analytically.
    let wheel = ret.wheel.wheel();
    while ret.sieve_index * BYTE_MODULO < low {
        let WheelElem { next_mult_factor, correction, next, .. } = wheel[ret.wheel_index];
        ret.sieve_index += ret.prime * next_mult_factor as usize;
        ret.sieve_index += correction as usize;
        ret.wheel_index = ret.wheel_index.wrapping_add(next as usize);
    }
    ret.sieve_index -= low / BYTE_MODULO;
    ret

}

mod wheel30;
mod wheel210;
<commit_msg>sieve: slash the size of a WheelInfo to a quarter.<commit_after>pub const BYTE_SIZE: usize = 8;
pub const BYTE_MODULO: usize = 30;

pub fn bit_index(n: usize) -> (bool, usize) {
    const POS: &'static [(bool, u8); BYTE_MODULO] = &[
        // 0
        (false, 0), (true, 0), (false, 1), (false, 1), (false, 1), (false, 1),
        // 6
        (false, 1), (true, 1), (false, 2), (false, 2), (false, 2), (true, 2),
        // 12
        (false, 3), (true, 3), (false, 4), (false, 4), (false, 4), (true, 4),
        // 18
        (false, 5), (true, 5), (false, 6), (false, 6), (false, 6), (true, 6),
        // 24
        (false, 7), (false, 7), (false, 7), (false, 7), (false, 7), (true, 7),
        ];
    let init = &POS[n % BYTE_MODULO];
    (init.0, (n / BYTE_MODULO) * BYTE_SIZE + init.1 as usize)
}
pub fn from_bit_index(bit: usize) -> usize {
    const TRUE_AT_BIT: &'static [usize; 8] = &[
        1, 7, 11, 13, 17, 19, 23, 29
            ];
    (bit / BYTE_SIZE) * BYTE_MODULO + TRUE_AT_BIT[bit % BYTE_SIZE]
}

pub use self::wheel30::Wheel30;
pub use self::wheel210::Wheel210;

pub trait Wheel {
    fn modulo(&self) -> usize;
    fn size(&self) -> usize;
    fn wheel(&self) -> &'static [WheelElem];
    fn init(&self) -> &'static [WheelInit];
    unsafe fn hardcoded_sieve(&self,
                              bytes: &mut [u8], si_: &mut usize, wi_: &mut usize, prime: usize);
}

#[derive(Debug)]
pub struct WheelInfo<W> {
    wheel: W,
    prime: u32,
    wheel_index: u16,
    sieve_index: u16,
}
impl<W: Wheel> WheelInfo<W> {
    #[inline]
    pub fn sieve(&mut self, bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();

        let mut si = self.sieve_index as usize;
        let mut wi = self.wheel_index as usize;
        let p = self.prime as usize;
        while si < top {
            raw_set_bit(self.wheel.wheel(),
                        bytes, &mut si, &mut wi, p)
        }
        self.sieve_index = si.wrapping_sub(top) as u16;
        self.wheel_index = wi as u16;
    }
    #[inline]
    pub fn sieve_pair(&mut self, self2: &mut WheelInfo<W>, bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();
        let wheel = self.wheel.wheel();

        let mut si1 = self.sieve_index as usize;
        let mut wi1 = self.wheel_index as usize;
        let p1 = self.prime as usize;
        let mut si2 = self2.sieve_index as usize;
        let mut wi2 = self2.wheel_index as usize;
        let p2 = self2.prime as usize;

        while si1 < top && si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }
        while si1 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
        }
        while si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }

        // if this wraps, we've hit the limit, and so won't be
        // continuing, so whatever, it can be junk.
        self.sieve_index = si1.wrapping_sub(top) as u16;
        self.wheel_index = wi1 as u16;
        self2.sieve_index = si2.wrapping_sub(top) as u16;
        self2.wheel_index = wi2 as u16;
    }
    pub fn sieve_triple(&mut self, self2: &mut WheelInfo<W>, self3: &mut WheelInfo<W>,
                        bytes: &mut [u8]) {
        let bytes = bytes;
        let top = bytes.len();
        let wheel = self.wheel.wheel();

        let mut si1 = self.sieve_index as usize;
        let mut wi1 = self.wheel_index as usize;
        let p1 = self.prime as usize;
        let mut si2 = self2.sieve_index as usize;
        let mut wi2 = self2.wheel_index as usize;
        let p2 = self2.prime as usize;
        let mut si3 = self3.sieve_index as usize;
        let mut wi3 = self3.wheel_index as usize;
        let p3 = self3.prime as usize;

        while si1 < top && si2 < top && si3 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
            raw_set_bit(wheel,
                        bytes, &mut si3, &mut wi3, p3);
        }
        while si1 < top {
            raw_set_bit(wheel,
                        bytes, &mut si1, &mut wi1, p1);
        }
        while si2 < top {
            raw_set_bit(wheel,
                        bytes, &mut si2, &mut wi2, p2);
        }
        while si3 < top {
            raw_set_bit(wheel,
                        bytes, &mut si3, &mut wi3, p3);
        }
        // if this wraps, we've hit the limit, and so won't be
        // continuing, so whatever, it can be junk.
        self.sieve_index = si1.wrapping_sub(top) as u16;
        self.wheel_index = wi1 as u16;
        self2.sieve_index = si2.wrapping_sub(top) as u16;
        self2.wheel_index = wi2 as u16;
        self3.sieve_index = si3.wrapping_sub(top) as u16;
        self3.wheel_index = wi3 as u16;
    }

    pub fn sieve_hardcoded(&mut self, bytes: &mut [u8]) {
        let mut si = self.sieve_index as usize;
        let mut wi = self.wheel_index as usize;
        unsafe {
            self.wheel.hardcoded_sieve(bytes,
                                       &mut si, &mut wi, self.prime as usize)
        }
        self.sieve_index = si as u16;
        self.wheel_index = wi as u16;
    }
}

#[derive(Debug)]
pub struct WheelInit {
    pub next_mult_factor: u8,
    pub wheel_index: u8,
}
#[macro_escape]
macro_rules! init {
    ($nmf: expr, $wi: expr) => { ::wheel::WheelInit { next_mult_factor: $nmf, wheel_index: $wi }}
}
#[derive(Debug)]
pub struct WheelElem {
    pub unset_bit: u8,
    pub next_mult_factor: u8,
    pub correction: u8,
    pub next: i8,
}

#[macro_escape]
macro_rules! count_ints {
    // count non-recursively, to avoid recursion limits
    ($($x: expr, )*) => { sum!($(0usize * $x as usize + 1usize,)*) }
}
#[macro_escape]
macro_rules! sum {
    ($($x: expr, )*) => { 0 $(+ $x)* }
}

#[macro_escape]
macro_rules! elems {
    ($([$($bit: expr, $nmf: expr, $c: expr, $n: expr;)*],)*) => {
        const WHEEL: &'static [::wheel::WheelElem; sum!($(count_ints!($($bit,)*),)*)] = &[
            $($(::wheel::WheelElem {
                unset_bit: 1u8 << $bit,
                next_mult_factor: $nmf,
                correction: $c,
                next: $n,
            },)*)*
                ];
    }
}

#[inline(always)]
fn raw_set_bit(wheel: &'static [WheelElem],
               x: &mut [u8], si: &mut usize, wi: &mut usize, prime: usize) {
    unsafe {
        let WheelElem { unset_bit, next_mult_factor, correction, next } =
            *wheel.get_unchecked(*wi);
        *x.get_unchecked_mut(*si) |= unset_bit;

        *si += prime * next_mult_factor as usize;
        *si += correction as usize;
        *wi = wi.wrapping_add(next as usize);
    }
}

const WHEEL_OFFSETS: &'static [usize; BYTE_MODULO] = &[
    0, 0, 0, 0, 0, 0,
    0, 1, 0, 0, 0, 2,
    0, 3, 0, 0, 0, 4,
    0, 5, 0, 0, 0, 6,
    0, 0, 0, 0, 0, 7,
    ];

#[inline(never)]
pub fn compute_wheel_elem<W: Wheel>(w: W, p: usize, low: usize) -> WheelInfo<W> {
    let mut mult = p * p;

    let init = &w.init()[p % w.modulo()];
    let next_mult_factor = init.next_mult_factor;
    mult += p * next_mult_factor as usize;

    let mut wheel_index = WHEEL_OFFSETS[p % BYTE_MODULO] * w.size();
    let mut sieve_index = mult * BYTE_SIZE / BYTE_MODULO / 8;

    let prime = p / BYTE_MODULO;
    // run the wheel until its above `low`... this is ugly and should be done analytically.
    while sieve_index * BYTE_MODULO < low {
        let WheelElem { next_mult_factor, correction, next, .. } = w.wheel()[wheel_index];
        sieve_index += prime * next_mult_factor as usize;
        sieve_index += correction as usize;
        wheel_index = wheel_index.wrapping_add(next as usize);
    }

    sieve_index -= low / BYTE_MODULO;
    let ret = WheelInfo {
        wheel: w,
        prime: prime as u32,
        sieve_index: sieve_index as u16,
        wheel_index: wheel_index as u16,
    };
    ret

}

mod wheel30;
mod wheel210;
<|endoftext|>