<commit_before>// # Pre-tokenized text example
//
// This example shows how to use pre-tokenized text. Sometimes yout might
// want to index and search through text which is already split into
// tokens by some external tool.
//
// In this example we will:
// - use tantivy tokenizer to create tokens and load them directly into tantivy,
// - import tokenized text straight from json,
// - perform a search on documents with pre-tokenized text

use tantivy::collector::{Count, TopDocs};
use tantivy::query::TermQuery;
use tantivy::schema::*;
use tantivy::tokenizer::{PreTokenizedString, SimpleTokenizer, Token, Tokenizer};
use tantivy::{doc, Index, ReloadPolicy};
use tempfile::TempDir;

fn pre_tokenize_text(text: &str) -> Vec<Token> {
    let mut token_stream = SimpleTokenizer.token_stream(text);
    let mut tokens = vec![];
    while token_stream.advance() {
        tokens.push(token_stream.token().clone());
    }
    tokens
}

fn main() -> tantivy::Result<()> {
    let index_path = TempDir::new()?;

    let mut schema_builder = Schema::builder();

    schema_builder.add_text_field("title", TEXT | STORED);
    schema_builder.add_text_field("body", TEXT);

    let schema = schema_builder.build();

    let index = Index::create_in_dir(&index_path, schema.clone())?;

    let mut index_writer = index.writer(50_000_000)?;

    // We can create a document manually, by setting the fields
    // one by one in a Document object.
    let title = schema.get_field("title").unwrap();
    let body = schema.get_field("body").unwrap();

    let title_text = "The Old Man and the Sea";
    let body_text = "He was an old man who fished alone in a skiff in the Gulf Stream";

    // Content of our first document
    // We create `PreTokenizedString` which contains original text and vector of tokens
    let title_tok = PreTokenizedString {
        text: String::from(title_text),
        tokens: pre_tokenize_text(title_text),
    };

    println!(
        "Original text: \"{}\" and tokens: {:?}",
        title_tok.text, title_tok.tokens
    );

    let body_tok = PreTokenizedString {
        text: String::from(body_text),
        tokens: pre_tokenize_text(body_text),
    };

    // Now lets create a document and add our `PreTokenizedString`
    let old_man_doc = doc!(title => title_tok, body => body_tok);

    // ... now let's just add it to the IndexWriter
    index_writer.add_document(old_man_doc);

    // Pretokenized text can also be fed as JSON
    let short_man_json = r#"{
        "title":[{
            "text":"The Old Man",
            "tokens":[
                {"offset_from":0,"offset_to":3,"position":0,"text":"The","position_length":1},
                {"offset_from":4,"offset_to":7,"position":1,"text":"Old","position_length":1},
                {"offset_from":8,"offset_to":11,"position":2,"text":"Man","position_length":1}
            ]
        }]
    }"#;

    let short_man_doc = schema.parse_document(&short_man_json)?;

    index_writer.add_document(short_man_doc);

    // Let's commit changes
    index_writer.commit()?;

    // ... and now is the time to query our index

    let reader = index
        .reader_builder()
        .reload_policy(ReloadPolicy::OnCommit)
        .try_into()?;

    let searcher = reader.searcher();

    // We want to get documents with token "Man", we will use TermQuery to do it
    // Using PreTokenizedString means the tokens are stored as is avoiding stemming
    // and lowercasing, which preserves full words in their original form
    let query = TermQuery::new(
        Term::from_field_text(title, "Man"),
        IndexRecordOption::Basic,
    );

    let (top_docs, count) = searcher
        .search(&query, &(TopDocs::with_limit(2), Count))
        .unwrap();

    assert_eq!(count, 2);

    // Now let's print out the results.
    // Note that the tokens are not stored along with the original text
    // in the document store
    for (_score, doc_address) in top_docs {
        let retrieved_doc = searcher.doc(doc_address)?;
        println!("Document: {}", schema.to_json(&retrieved_doc));
    }

    // In contrary to the previous query, when we search for the "man" term we
    // should get no results, as it's not one of the indexed tokens. SimpleTokenizer
    // only splits text on whitespace / punctuation.

    let query = TermQuery::new(
        Term::from_field_text(title, "man"),
        IndexRecordOption::Basic,
    );

    let (_top_docs, count) = searcher
        .search(&query, &(TopDocs::with_limit(2), Count))
        .unwrap();

    assert_eq!(count, 0);

    Ok(())
}
<commit_msg>Fixed spelling<commit_after>// # Pre-tokenized text example
//
// This example shows how to use pre-tokenized text. Sometimes you might
// want to index and search through text which is already split into
// tokens by some external tool.
//
// In this example we will:
// - use tantivy tokenizer to create tokens and load them directly into tantivy,
// - import tokenized text straight from json,
// - perform a search on documents with pre-tokenized text

use tantivy::collector::{Count, TopDocs};
use tantivy::query::TermQuery;
use tantivy::schema::*;
use tantivy::tokenizer::{PreTokenizedString, SimpleTokenizer, Token, Tokenizer};
use tantivy::{doc, Index, ReloadPolicy};
use tempfile::TempDir;

fn pre_tokenize_text(text: &str) -> Vec<Token> {
    let mut token_stream = SimpleTokenizer.token_stream(text);
    let mut tokens = vec![];
    while token_stream.advance() {
        tokens.push(token_stream.token().clone());
    }
    tokens
}

fn main() -> tantivy::Result<()> {
    let index_path = TempDir::new()?;

    let mut schema_builder = Schema::builder();

    schema_builder.add_text_field("title", TEXT | STORED);
    schema_builder.add_text_field("body", TEXT);

    let schema = schema_builder.build();

    let index = Index::create_in_dir(&index_path, schema.clone())?;

    let mut index_writer = index.writer(50_000_000)?;

    // We can create a document manually, by setting the fields
    // one by one in a Document object.
    let title = schema.get_field("title").unwrap();
    let body = schema.get_field("body").unwrap();

    let title_text = "The Old Man and the Sea";
    let body_text = "He was an old man who fished alone in a skiff in the Gulf Stream";

    // Content of our first document
    // We create `PreTokenizedString` which contains original text and vector of tokens
    let title_tok = PreTokenizedString {
        text: String::from(title_text),
        tokens: pre_tokenize_text(title_text),
    };

    println!(
        "Original text: \"{}\" and tokens: {:?}",
        title_tok.text, title_tok.tokens
    );

    let body_tok = PreTokenizedString {
        text: String::from(body_text),
        tokens: pre_tokenize_text(body_text),
    };

    // Now lets create a document and add our `PreTokenizedString`
    let old_man_doc = doc!(title => title_tok, body => body_tok);

    // ... now let's just add it to the IndexWriter
    index_writer.add_document(old_man_doc);

    // Pretokenized text can also be fed as JSON
    let short_man_json = r#"{
        "title":[{
            "text":"The Old Man",
            "tokens":[
                {"offset_from":0,"offset_to":3,"position":0,"text":"The","position_length":1},
                {"offset_from":4,"offset_to":7,"position":1,"text":"Old","position_length":1},
                {"offset_from":8,"offset_to":11,"position":2,"text":"Man","position_length":1}
            ]
        }]
    }"#;

    let short_man_doc = schema.parse_document(&short_man_json)?;

    index_writer.add_document(short_man_doc);

    // Let's commit changes
    index_writer.commit()?;

    // ... and now is the time to query our index

    let reader = index
        .reader_builder()
        .reload_policy(ReloadPolicy::OnCommit)
        .try_into()?;

    let searcher = reader.searcher();

    // We want to get documents with token "Man", we will use TermQuery to do it
    // Using PreTokenizedString means the tokens are stored as is avoiding stemming
    // and lowercasing, which preserves full words in their original form
    let query = TermQuery::new(
        Term::from_field_text(title, "Man"),
        IndexRecordOption::Basic,
    );

    let (top_docs, count) = searcher
        .search(&query, &(TopDocs::with_limit(2), Count))
        .unwrap();

    assert_eq!(count, 2);

    // Now let's print out the results.
    // Note that the tokens are not stored along with the original text
    // in the document store
    for (_score, doc_address) in top_docs {
        let retrieved_doc = searcher.doc(doc_address)?;
        println!("Document: {}", schema.to_json(&retrieved_doc));
    }

    // In contrary to the previous query, when we search for the "man" term we
    // should get no results, as it's not one of the indexed tokens. SimpleTokenizer
    // only splits text on whitespace / punctuation.

    let query = TermQuery::new(
        Term::from_field_text(title, "man"),
        IndexRecordOption::Basic,
    );

    let (_top_docs, count) = searcher
        .search(&query, &(TopDocs::with_limit(2), Count))
        .unwrap();

    assert_eq!(count, 0);

    Ok(())
}
<|endoftext|>


<commit_before>extern crate lwnvulns;
extern crate scraper;
extern crate curl;

use lwnvulns::tokenize::{tokenize, Token, Header, Issue, SourceLink};
use lwnvulns::parse::parse;
use lwnvulns::writer::write;
use lwnvulns::transform::collapse_anemic;
use scraper::{Html, Selector};
use curl::easy::Easy;

use std::io::{Read, Write};
use std::fs::File;

struct LwnRow {
    url: String,
    id: String,
    packages: String,
    description: String,
}

fn load_db(src: &str) -> Vec<String> {
    let mut db: Vec<String> = vec![];
    {
        let mut f = File::open(src).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();
        for entry in s.split_whitespace() {
            db.push(entry.to_string());
        }
    }

    return db;
}

fn main() {
    let db = load_db("./db");

    let mut tokens: Vec<Token> = tokenize(include_str!("./instructions.md").to_string());

    let mut page = 0;
    let mut pages_with_nothing = 0;

    loop {
        let mut found = 0;
        for token in tokens_from_html(fetch_page(page)) {
            if let Token::Issue(ref issue) = token {
                if db.contains(&issue.source.id) {
                    continue;
                } else {
                    found += 1;
                }
            }
            tokens.push(token);
        }

        writeln!(&mut std::io::stderr(),
                 "Page {page} yielded {found} issues, after {none} pages with nothing",
                 page = page,
                 found = found,
                 none = pages_with_nothing)
            .unwrap();

        page += 1;

        if found == 0 {
            pages_with_nothing += 1;
        } else {
            pages_with_nothing = 0;
        }

        if pages_with_nothing >= 2 {
            break;
        }

        if page > 10 {
            panic!("Not sure we should be hitting 10 pages!");
        }
    }

    print!("{}", write(&collapse_anemic(parse(tokens).unwrap())));

}

fn fetch_page(page: usize) -> scraper::Html {
    let url = format!("https://lwn.net/Vulnerabilities/?n={}&offset={}",
                      100,
                      page * 100);
    let mut data = Vec::new();

    let mut easy = Easy::new();
    easy.url(&url).unwrap();

    {
        let mut transfer = easy.transfer();
        transfer.write_function(|chunk| {
                data.extend_from_slice(chunk);
                Ok(chunk.len())
            })
            .unwrap();
        transfer.perform().unwrap();
    }

    return Html::parse_document(&String::from_utf8(data).unwrap());
}

fn tokens_from_html(html: scraper::Html) -> Vec<Token> {
    let mut tokens: Vec<Token> = vec![];

    let rows = Selector::parse("tr").unwrap();
    let links = Selector::parse("td:nth-child(1) a").unwrap();
    let packages = Selector::parse("td:nth-child(3)").unwrap();
    let descriptions = Selector::parse("td:nth-child(4)").unwrap();
    for row in html.select(&rows) {
        if let Some(link) = row.select(&links).next() {
            let package = row.select(&packages).next().unwrap().text().next().unwrap();
            let description = row.select(&descriptions).next().unwrap().text().next().unwrap();

            let lwnrow = LwnRow {
                url: link.value().attr("href").unwrap().to_string(),
                id: link.inner_html(),
                packages: package.to_string(),
                description: description.to_string(),
            };
            for token in row_to_tokens(lwnrow) {
                tokens.push(token);
            }
        }
    }

    return tokens;
}

fn row_to_tokens(row: LwnRow) -> Vec<Token> {
    let mut tokens = vec![];

    let url = format!("https://lwn.net{}", row.url);
    for pkg in split_packages(row.packages) {
        tokens.push(Token::Header(Header {
            issue_count: 0,
            notes: None,
            package: pkg.clone(),
        }));

        tokens.push(Token::Issue(Issue {
            complete: false,
            source: SourceLink {
                id: row.id.clone(),
                url: url.clone(),
            },
            content: format!(
                "([search]({search_url}), [files]({files_url}))  {description}",
                search_url = format!(
                    "http://search.nix.gsc.io/?q={package}&i=fosho&repos=nixos-nixpkgs",
                    package=pkg
                ),
                files_url = format!(
                    "{root}?utf8=%E2%9C%93&q={package}+in%3Apath&type=Code",
                    root="https://github.com/NixOS/nixpkgs/search",
                    package=pkg
                ),
                description=row.description
            ),
        }));
    }

    return tokens;
}

fn split_packages(packages: String) -> Vec<String> {
    let pkgs = packages.split_whitespace()
        .map(|s| s.replace(",", "").to_string())
        .map(|s| if s == "tiff" {
            "libtiff".to_string()
        } else if s == "libgc" {
            "boehm-gc".to_string()
        } else if s == "perl-DBD-MySQL" {
            "DBD-mysql".to_string()
        } else if s == "httpd" {
            "apache-httpd".to_string()
        } else {
            s
        })
        .collect();

    return pkgs;
}
<commit_msg>Dedup code by extracting cell text in a separate fn<commit_after>extern crate lwnvulns;
extern crate scraper;
extern crate curl;

use lwnvulns::tokenize::{tokenize, Token, Header, Issue, SourceLink};
use lwnvulns::parse::parse;
use lwnvulns::writer::write;
use lwnvulns::transform::collapse_anemic;
use scraper::{Html, Selector};
use curl::easy::Easy;

use std::io::{Read, Write};
use std::fs::File;

struct LwnRow {
    url: String,
    id: String,
    packages: String,
    description: String,
}

fn load_db(src: &str) -> Vec<String> {
    let mut db: Vec<String> = vec![];
    {
        let mut f = File::open(src).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();
        for entry in s.split_whitespace() {
            db.push(entry.to_string());
        }
    }

    return db;
}

fn main() {
    let db = load_db("./db");

    let mut tokens: Vec<Token> = tokenize(include_str!("./instructions.md").to_string());

    let mut page = 0;
    let mut pages_with_nothing = 0;

    loop {
        let mut found = 0;
        for token in tokens_from_html(fetch_page(page)) {
            if let Token::Issue(ref issue) = token {
                if db.contains(&issue.source.id) {
                    continue;
                } else {
                    found += 1;
                }
            }
            tokens.push(token);
        }

        writeln!(&mut std::io::stderr(),
                 "Page {page} yielded {found} issues, after {none} pages with nothing",
                 page = page,
                 found = found,
                 none = pages_with_nothing)
            .unwrap();

        page += 1;

        if found == 0 {
            pages_with_nothing += 1;
        } else {
            pages_with_nothing = 0;
        }

        if pages_with_nothing >= 2 {
            break;
        }

        if page > 10 {
            panic!("Not sure we should be hitting 10 pages!");
        }
    }

    print!("{}", write(&collapse_anemic(parse(tokens).unwrap())));

}

fn fetch_page(page: usize) -> scraper::Html {
    let url = format!("https://lwn.net/Vulnerabilities/?n={}&offset={}",
                      100,
                      page * 100);
    let mut data = Vec::new();

    let mut easy = Easy::new();
    easy.url(&url).unwrap();

    {
        let mut transfer = easy.transfer();
        transfer.write_function(|chunk| {
                data.extend_from_slice(chunk);
                Ok(chunk.len())
            })
            .unwrap();
        transfer.perform().unwrap();
    }

    return Html::parse_document(&String::from_utf8(data).unwrap());
}

fn tokens_from_html(html: scraper::Html) -> Vec<Token> {
    let mut tokens: Vec<Token> = vec![];

    let rows = Selector::parse("tr").unwrap();
    let links = Selector::parse("td:nth-child(1) a").unwrap();
    let packages = Selector::parse("td:nth-child(3)").unwrap();
    let descriptions = Selector::parse("td:nth-child(4)").unwrap();
    for row in html.select(&rows) {
        if let Some(link) = row.select(&links).next() {
            let package = extract_cell_text(row.select(&packages))
                .unwrap_or("unknown package".to_string());
            let description = extract_cell_text(row.select(&descriptions))
                .unwrap_or(package.clone()); // sometimes the desc is missing

            let lwnrow = LwnRow {
                url: link.value().attr("href").unwrap().to_string(),
                id: link.inner_html(),
                packages: package,
                description: description,
            };
            for token in row_to_tokens(lwnrow) {
                tokens.push(token);
            }
        }
    }

    return tokens;
}

fn extract_cell_text(mut cell: scraper::element_ref::Select) -> Option<String> {
    if let Some(td_elem) = cell.next() {
        let mut text_iterator = td_elem.text();
        if let Some(description) = text_iterator.next() {
            return Some(description.to_string());
        }
    }

    return None;
}

fn row_to_tokens(row: LwnRow) -> Vec<Token> {
    let mut tokens = vec![];

    let url = format!("https://lwn.net{}", row.url);
    for pkg in split_packages(row.packages) {
        tokens.push(Token::Header(Header {
            issue_count: 0,
            notes: None,
            package: pkg.clone(),
        }));

        tokens.push(Token::Issue(Issue {
            complete: false,
            source: SourceLink {
                id: row.id.clone(),
                url: url.clone(),
            },
            content: format!(
                "([search]({search_url}), [files]({files_url}))  {description}",
                search_url = format!(
                    "http://search.nix.gsc.io/?q={package}&i=fosho&repos=nixos-nixpkgs",
                    package=pkg
                ),
                files_url = format!(
                    "{root}?utf8=%E2%9C%93&q={package}+in%3Apath&type=Code",
                    root="https://github.com/NixOS/nixpkgs/search",
                    package=pkg
                ),
                description=row.description
            ),
        }));
    }

    return tokens;
}

fn split_packages(packages: String) -> Vec<String> {
    let pkgs = packages.split_whitespace()
        .map(|s| s.replace(",", "").to_string())
        .map(|s| if s == "tiff" {
            "libtiff".to_string()
        } else if s == "libgc" {
            "boehm-gc".to_string()
        } else if s == "perl-DBD-MySQL" {
            "DBD-mysql".to_string()
        } else if s == "httpd" {
            "apache-httpd".to_string()
        } else {
            s
        })
        .collect();

    return pkgs;
}
<|endoftext|>


<commit_before>use std::any::TypeId;
use std::fmt;
use std::fmt::Formatter;
use std::hash::Hash;

use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::enums::Enum;
use crate::reflect::enums::generated::GeneratedEnumDescriptor;
use crate::reflect::file::index::EnumIndex;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::FileDescriptor;
use crate::reflect::MessageDescriptor;
use crate::EnumFull;

pub(crate) mod generated;
pub(crate) mod path;

/// Description for enum variant.
///
/// Used in reflection.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumValueDescriptor {
    pub(crate) enum_descriptor: EnumDescriptor,
    pub(crate) index: usize,
}

fn _assert_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<EnumValueDescriptor>();
}

impl fmt::Debug for EnumValueDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumValueDescriptor")
            .field("enum_descriptor", &self.enum_descriptor)
            .field("name", &self.name())
            .finish()
    }
}

impl fmt::Display for EnumValueDescriptor {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl EnumValueDescriptor {
    pub(crate) fn new(enum_descriptor: EnumDescriptor, index: usize) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor,
            index,
        }
    }

    /// `.proto` object which declared this value.
    pub fn proto(&self) -> &EnumValueDescriptorProto {
        &self.enum_descriptor.proto().value[self.index]
    }

    /// Name of enum variant as specified in proto file
    pub fn name(&self) -> &str {
        self.proto().name()
    }

    /// Fully qualified enum value name: fully qualified enum name followed by value name.
    pub fn full_name(&self) -> String {
        format!("{}.{}", self.enum_descriptor.full_name(), self.name())
    }

    /// `i32` value of the enum variant
    pub fn value(&self) -> i32 {
        self.proto().number()
    }

    /// Get descriptor of enum holding this value.
    pub fn enum_descriptor(&self) -> &EnumDescriptor {
        &self.enum_descriptor
    }

    /// Convert this value descriptor into proper enum object.
    ///
    /// ```
    /// # use protobuf::well_known_types::NullValue;
    /// # use protobuf::EnumFull;
    /// # use protobuf::reflect::EnumValueDescriptor;
    ///
    /// # if !cfg!(miri) {
    /// let value: EnumValueDescriptor = NullValue::NULL_VALUE.descriptor();
    /// let null: Option<NullValue> = value.cast();
    /// assert_eq!(Some(NullValue::NULL_VALUE), null);
    /// # }
    /// ```
    pub fn cast<E: EnumFull>(&self) -> Option<E> {
        if self.enum_descriptor != E::enum_descriptor() {
            return None;
        }
        E::from_i32(self.value())
    }
}

/// Dynamic representation of enum type.
///
/// Can be used in reflective operations.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumDescriptor")
            .field("full_name", &self.full_name())
            .finish_non_exhaustive()
    }
}

impl EnumDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> EnumDescriptor {
        EnumDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    fn get_impl(&self) -> EnumDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                EnumDescriptorImplRef::Generated(&g.enums[self.index])
            }
            FileDescriptorImpl::Dynamic(..) => EnumDescriptorImplRef::Dynamic,
        }
    }

    /// Descriptor objects which defined this enum.
    pub fn proto(&self) -> &EnumDescriptorProto {
        self.index_entry()
            .enum_path
            .eval(self.file_descriptor.proto())
    }

    /// Enum name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.proto().name()
    }

    fn index_entry(&self) -> &EnumIndex {
        self.file_descriptor.enum_index_entry(self.index)
    }

    /// Fully qualified protobuf name of enum
    pub fn full_name(&self) -> &str {
        &self.index_entry().full_name
    }

    /// Name relative to the package where the message is declared.
    pub fn name_to_package(&self) -> &str {
        &self.index_entry().name_to_package
    }

    /// Get `EnumDescriptor` object for given enum type
    pub fn for_type<E: EnumFull>() -> EnumDescriptor {
        E::enum_descriptor()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> EnumDescriptor {
        EnumDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get a message containing this message, or `None` if this message is declared at file level.
    pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
        self.index_entry()
            .enclosing_message
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
    }

    /// This enum values
    pub fn values<'a>(&'a self) -> impl Iterator<Item = EnumValueDescriptor> + 'a {
        let value_len = self.proto().value.len();
        (0..value_len).map(move |index| EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        })
    }

    /// First variant (also default in proto3).
    pub fn first_value(&self) -> EnumValueDescriptor {
        self.values().next().unwrap()
    }

    /// Find enum variant by name
    pub fn value_by_name(&self, name: &str) -> Option<EnumValueDescriptor> {
        let index = *self.file_descriptor.common().enums[self.index]
            .index_by_name
            .get(name)?;
        Some(EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        })
    }

    /// Find enum variant by number
    pub fn value_by_number(&self, number: i32) -> Option<EnumValueDescriptor> {
        let index = *self.file_descriptor.common().enums[self.index]
            .index_by_number
            .get(&number)?;
        Some(self.value_by_index(index))
    }

    /// Get enum variant by index (as declared in `.proto` file).
    pub fn value_by_index(&self, index: usize) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        }
    }

    /// Default enum value (first variant)
    pub fn default_value(&self) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index: 0,
        }
    }

    /// Find enum variant by number or return default (first) enum value
    pub fn value_by_number_or_default(&self, number: i32) -> EnumValueDescriptor {
        match self.value_by_number(number) {
            Some(v) => v,
            None => self.default_value(),
        }
    }

    /// Check if this enum descriptor corresponds given enum type
    ///
    /// ```
    /// # use protobuf::EnumFull;
    /// # use protobuf::descriptor::field_descriptor_proto::Label;
    /// # use protobuf::reflect::EnumDescriptor;
    ///
    /// # if !cfg!(miri) {
    /// let descriptor: EnumDescriptor = Label::enum_descriptor();
    ///
    /// assert!(descriptor.is::<Label>())
    /// }
    /// ```
    pub fn is<E: Enum>(&self) -> bool {
        match self.get_impl() {
            EnumDescriptorImplRef::Generated(g) => g.type_id == TypeId::of::<E>(),
            EnumDescriptorImplRef::Dynamic => false,
        }
    }
}

enum EnumDescriptorImplRef {
    Generated(&'static GeneratedEnumDescriptor),
    Dynamic,
}

#[cfg(test)]
mod test {
    use crate::descriptor::field_descriptor_proto::Label;
    use crate::descriptor::field_descriptor_proto::Type;
    use crate::descriptor::FieldDescriptorProto;
    use crate::well_known_types::NullValue;
    use crate::EnumFull;
    use crate::MessageFull;

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn enclosing_message() {
        assert_eq!(
            Some(FieldDescriptorProto::descriptor()),
            Type::enum_descriptor().enclosing_message()
        );
        assert_eq!(None, NullValue::enum_descriptor().enclosing_message());
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn to_string() {
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label",
            Label::enum_descriptor().to_string()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label",
            Label::enum_descriptor().full_name()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
            Label::LABEL_REPEATED.descriptor().to_string()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
            Label::LABEL_REPEATED.descriptor().full_name()
        );
    }
}
<commit_msg>Dead code<commit_after>use std::any::TypeId;
use std::fmt;
use std::fmt::Formatter;
use std::hash::Hash;

use crate::descriptor::EnumDescriptorProto;
use crate::descriptor::EnumValueDescriptorProto;
use crate::enums::Enum;
use crate::reflect::enums::generated::GeneratedEnumDescriptor;
use crate::reflect::file::index::EnumIndex;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::FileDescriptor;
use crate::reflect::MessageDescriptor;
use crate::EnumFull;

pub(crate) mod generated;
pub(crate) mod path;

/// Description for enum variant.
///
/// Used in reflection.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumValueDescriptor {
    pub(crate) enum_descriptor: EnumDescriptor,
    pub(crate) index: usize,
}

fn _assert_send_sync() {
    fn _assert_send_sync<T: Send + Sync>() {}
    _assert_send_sync::<EnumValueDescriptor>();
}

impl fmt::Debug for EnumValueDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumValueDescriptor")
            .field("enum_descriptor", &self.enum_descriptor)
            .field("name", &self.name())
            .finish()
    }
}

impl fmt::Display for EnumValueDescriptor {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl EnumValueDescriptor {
    pub(crate) fn new(enum_descriptor: EnumDescriptor, index: usize) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor,
            index,
        }
    }

    /// `.proto` object which declared this value.
    pub fn proto(&self) -> &EnumValueDescriptorProto {
        &self.enum_descriptor.proto().value[self.index]
    }

    /// Name of enum variant as specified in proto file
    pub fn name(&self) -> &str {
        self.proto().name()
    }

    /// Fully qualified enum value name: fully qualified enum name followed by value name.
    pub fn full_name(&self) -> String {
        format!("{}.{}", self.enum_descriptor.full_name(), self.name())
    }

    /// `i32` value of the enum variant
    pub fn value(&self) -> i32 {
        self.proto().number()
    }

    /// Get descriptor of enum holding this value.
    pub fn enum_descriptor(&self) -> &EnumDescriptor {
        &self.enum_descriptor
    }

    /// Convert this value descriptor into proper enum object.
    ///
    /// ```
    /// # use protobuf::well_known_types::NullValue;
    /// # use protobuf::EnumFull;
    /// # use protobuf::reflect::EnumValueDescriptor;
    ///
    /// # if !cfg!(miri) {
    /// let value: EnumValueDescriptor = NullValue::NULL_VALUE.descriptor();
    /// let null: Option<NullValue> = value.cast();
    /// assert_eq!(Some(NullValue::NULL_VALUE), null);
    /// # }
    /// ```
    pub fn cast<E: EnumFull>(&self) -> Option<E> {
        if self.enum_descriptor != E::enum_descriptor() {
            return None;
        }
        E::from_i32(self.value())
    }
}

/// Dynamic representation of enum type.
///
/// Can be used in reflective operations.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct EnumDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for EnumDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EnumDescriptor")
            .field("full_name", &self.full_name())
            .finish_non_exhaustive()
    }
}

impl EnumDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> EnumDescriptor {
        EnumDescriptor {
            file_descriptor,
            index,
        }
    }

    fn get_impl(&self) -> EnumDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                EnumDescriptorImplRef::Generated(&g.enums[self.index])
            }
            FileDescriptorImpl::Dynamic(..) => EnumDescriptorImplRef::Dynamic,
        }
    }

    /// Descriptor objects which defined this enum.
    pub fn proto(&self) -> &EnumDescriptorProto {
        self.index_entry()
            .enum_path
            .eval(self.file_descriptor.proto())
    }

    /// Enum name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.proto().name()
    }

    fn index_entry(&self) -> &EnumIndex {
        self.file_descriptor.enum_index_entry(self.index)
    }

    /// Fully qualified protobuf name of enum
    pub fn full_name(&self) -> &str {
        &self.index_entry().full_name
    }

    /// Name relative to the package where the message is declared.
    pub fn name_to_package(&self) -> &str {
        &self.index_entry().name_to_package
    }

    /// Get `EnumDescriptor` object for given enum type
    pub fn for_type<E: EnumFull>() -> EnumDescriptor {
        E::enum_descriptor()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> EnumDescriptor {
        EnumDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get a message containing this message, or `None` if this message is declared at file level.
    pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
        self.index_entry()
            .enclosing_message
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
    }

    /// This enum values
    pub fn values<'a>(&'a self) -> impl Iterator<Item = EnumValueDescriptor> + 'a {
        let value_len = self.proto().value.len();
        (0..value_len).map(move |index| EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        })
    }

    /// First variant (also default in proto3).
    pub fn first_value(&self) -> EnumValueDescriptor {
        self.values().next().unwrap()
    }

    /// Find enum variant by name
    pub fn value_by_name(&self, name: &str) -> Option<EnumValueDescriptor> {
        let index = *self.file_descriptor.common().enums[self.index]
            .index_by_name
            .get(name)?;
        Some(EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        })
    }

    /// Find enum variant by number
    pub fn value_by_number(&self, number: i32) -> Option<EnumValueDescriptor> {
        let index = *self.file_descriptor.common().enums[self.index]
            .index_by_number
            .get(&number)?;
        Some(self.value_by_index(index))
    }

    /// Get enum variant by index (as declared in `.proto` file).
    pub fn value_by_index(&self, index: usize) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index,
        }
    }

    /// Default enum value (first variant)
    pub fn default_value(&self) -> EnumValueDescriptor {
        EnumValueDescriptor {
            enum_descriptor: self.clone(),
            index: 0,
        }
    }

    /// Find enum variant by number or return default (first) enum value
    pub fn value_by_number_or_default(&self, number: i32) -> EnumValueDescriptor {
        match self.value_by_number(number) {
            Some(v) => v,
            None => self.default_value(),
        }
    }

    /// Check if this enum descriptor corresponds given enum type
    ///
    /// ```
    /// # use protobuf::EnumFull;
    /// # use protobuf::descriptor::field_descriptor_proto::Label;
    /// # use protobuf::reflect::EnumDescriptor;
    ///
    /// # if !cfg!(miri) {
    /// let descriptor: EnumDescriptor = Label::enum_descriptor();
    ///
    /// assert!(descriptor.is::<Label>())
    /// }
    /// ```
    pub fn is<E: Enum>(&self) -> bool {
        match self.get_impl() {
            EnumDescriptorImplRef::Generated(g) => g.type_id == TypeId::of::<E>(),
            EnumDescriptorImplRef::Dynamic => false,
        }
    }
}

enum EnumDescriptorImplRef {
    Generated(&'static GeneratedEnumDescriptor),
    Dynamic,
}

#[cfg(test)]
mod test {
    use crate::descriptor::field_descriptor_proto::Label;
    use crate::descriptor::field_descriptor_proto::Type;
    use crate::descriptor::FieldDescriptorProto;
    use crate::well_known_types::NullValue;
    use crate::EnumFull;
    use crate::MessageFull;

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn enclosing_message() {
        assert_eq!(
            Some(FieldDescriptorProto::descriptor()),
            Type::enum_descriptor().enclosing_message()
        );
        assert_eq!(None, NullValue::enum_descriptor().enclosing_message());
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn to_string() {
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label",
            Label::enum_descriptor().to_string()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label",
            Label::enum_descriptor().full_name()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
            Label::LABEL_REPEATED.descriptor().to_string()
        );
        assert_eq!(
            "google.protobuf.FieldDescriptorProto.Label.LABEL_REPEATED",
            Label::LABEL_REPEATED.descriptor().full_name()
        );
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

pub fn puzzle(input: &str) -> i32 {
    for line in input.lines() {
        let line = line.trim();
    }
    0
}

#[derive(Debug, PartialEq)]
pub enum Instruction {
    Copy(FromLocation, Register),
}

impl std::str::FromStr for Instruction {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut parts = s.split_whitespace();
        match parts.next() {
            Some("cpy") => Ok(
                Instruction::Copy(
                    parts.next().ok_or("no from location")?.parse()?,
                    parts.next().ok_or("no register")?.parse()?
                )
            ),
            _ => unimplemented!(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum FromLocation {
    Integer(i32),
}

impl std::str::FromStr for FromLocation {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(FromLocation::Integer(s.parse()?))
    }
}

#[derive(Debug, PartialEq)]
pub enum Register {
    A,
}

impl std::str::FromStr for Register {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "a" => Ok(Register::A),
            _ => unimplemented!(),
        }
    }
}

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

    #[test]
    fn parse_cpy() {
        let instr: Instruction = "cpy 41 a".parse().expect("couldn't parse");
        assert_eq!(
            instr,
            Instruction::Copy(FromLocation::Integer(41), Register::A)
        );
    }

    #[test]
    fn sample() {
        let input = "cpy 41 a
            inc a
            inc a
            dec a
            jnz a 2
            dec a";
        assert_eq!(puzzle(input), 42);
    }
}
<commit_msg>Clean up traits<commit_after>use std::error::Error;
use std::str::FromStr;

pub fn puzzle(input: &str) -> i32 {
    for line in input.lines() {
        let line = line.trim();
    }
    0
}

#[derive(Debug, PartialEq)]
pub enum Instruction {
    Copy(FromLocation, Register),
}

impl FromStr for Instruction {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut parts = s.split_whitespace();
        match parts.next() {
            Some("cpy") => Ok(
                Instruction::Copy(
                    parts.next().ok_or("no from location")?.parse()?,
                    parts.next().ok_or("no register")?.parse()?
                )
            ),
            _ => unimplemented!(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum FromLocation {
    Integer(i32),
}

impl FromStr for FromLocation {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(FromLocation::Integer(s.parse()?))
    }
}

#[derive(Debug, PartialEq)]
pub enum Register {
    A,
}

impl FromStr for Register {
    type Err = Box<Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "a" => Ok(Register::A),
            _ => unimplemented!(),
        }
    }
}

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

    #[test]
    fn parse_cpy() {
        let instr: Instruction = "cpy 41 a".parse().expect("couldn't parse");
        assert_eq!(
            instr,
            Instruction::Copy(FromLocation::Integer(41), Register::A)
        );
    }

    #[test]
    fn sample() {
        let input = "cpy 41 a
            inc a
            inc a
            dec a
            jnz a 2
            dec a";
        assert_eq!(puzzle(input), 42);
    }
}
<|endoftext|>


<commit_before>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//! Alternatively, specify the program to open something with. It should expect to receive the path or URL as first argument.
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::with("http://rust-lang.org", "firefox").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```

use std::{ffi::OsStr, io, process::ExitStatus, thread};

#[cfg(target_os = "windows")]
pub use windows::{that, with};

#[cfg(target_os = "macos")]
pub use macos::{that, with};

#[cfg(any(
    target_os = "linux",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
pub use unix::{that, with};

/// Convenience function for opening the passed path in a new thread.
/// See documentation of `that(...)` for more details.
pub fn that_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    thread::spawn(|| that(path))
}

pub fn with_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
    app: impl Into<String>,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    let app = app.into();
    thread::spawn(|| with(path, app))
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::{ffi::OsStrExt, process::ExitStatusExt};
    use std::process::ExitStatus;
    use std::ptr;

    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
        const SW_SHOW: c_int = 5;

        let path = convert_path(path.as_ref())?;
        let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                ptr::null(),
                SW_SHOW,
            )
        };
        if result as c_int > 32 {
            Ok(ExitStatus::from_raw(0))
        } else {
            Err(io::Error::last_os_error())
        }
    }

    pub fn with<T: AsRef<OsStr> + Sized>(
        path: T,
        app: impl Into<String>,
    ) -> io::Result<ExitStatus> {
        const SW_SHOW: c_int = 5;

        let path = convert_path(path.as_ref())?;
        let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
        let app_name: Vec<u16> = OsStr::new(&format!("{}\0", app.into()))
            .encode_wide()
            .collect();
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                app_name.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                SW_SHOW,
            )
        };
        if result as c_int > 32 {
            Ok(ExitStatus::from_raw(0))
        } else {
            Err(io::Error::last_os_error())
        }
    }
}

#[cfg(target_os = "macos")]
mod macos {

    use std::{
        ffi::OsStr,
        io::Result,
        process::{Command, ExitStatus, Stdio},
    };

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> Result<ExitStatus> {
        Command::new("open")
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path.as_ref())
            .spawn()?
            .wait()
    }

    pub fn with<T: AsRef<OsStr> + Sized>(path: T, app: impl Into<String>) -> Result<ExitStatus> {
        Command::new("open")
            .arg(path.as_ref())
            .arg("-a")
            .arg(app.into())
            .spawn()?
            .wait()
    }
}

#[cfg(any(
    target_os = "linux",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
mod unix {

    use std::{
        ffi::OsStr,
        io::{Error, Result},
        process::{Command, ExitStatus, Stdio},
    };

    use which::which;

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> Result<ExitStatus> {
        ["xdg-open", "gnome-open", "kde-open", "wslview"] // Open handlers
            .iter()
            .find(|it| which(it).is_ok()) // find the first handler that exists
            .ok_or(Error::from_raw_os_error(0)) // If not found, return err
            .and_then(|program| {
                // If found run the handler
                Command::new(program)
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .arg(path.as_ref())
                    .spawn()?
                    .wait()
            })
    }

    pub fn with<T: AsRef<OsStr> + Sized>(path: T, app: impl Into<String>) -> Result<ExitStatus> {
        Command::new(app.into()).arg(path.as_ref()).spawn()?.wait()
    }
}
<commit_msg>minor refactor<commit_after>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//! Alternatively, specify the program to open something with. It should expect to receive the path or URL as first argument.
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::with("http://rust-lang.org", "firefox").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```

use std::{ffi::OsStr, io, process::ExitStatus, thread};

#[cfg(target_os = "windows")]
pub use windows::{that, with};

#[cfg(target_os = "macos")]
pub use macos::{that, with};

#[cfg(any(
    target_os = "linux",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
pub use unix::{that, with};

/// Convenience function for opening the passed path in a new thread.
/// See documentation of `that(...)` for more details.
pub fn that_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    thread::spawn(|| that(path))
}

pub fn with_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
    app: impl Into<String>,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    let app = app.into();
    thread::spawn(|| with(path, app))
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::{ffi::OsStrExt, process::ExitStatusExt};
    use std::process::ExitStatus;
    use std::ptr;

    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
        const SW_SHOW: c_int = 5;

        let path = convert_path(path.as_ref())?;
        let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                ptr::null(),
                SW_SHOW,
            )
        };
        if result as c_int > 32 {
            Ok(ExitStatus::from_raw(0))
        } else {
            Err(io::Error::last_os_error())
        }
    }

    pub fn with<T: AsRef<OsStr> + Sized>(
        path: T,
        app: impl Into<String>,
    ) -> io::Result<ExitStatus> {
        const SW_SHOW: c_int = 5;

        let path = convert_path(path.as_ref())?;
        let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
        let app_name: Vec<u16> = OsStr::new(&format!("{}\0", app.into()))
            .encode_wide()
            .collect();
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                app_name.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                SW_SHOW,
            )
        };
        if result as c_int > 32 {
            Ok(ExitStatus::from_raw(0))
        } else {
            Err(io::Error::last_os_error())
        }
    }
}

#[cfg(target_os = "macos")]
mod macos {
    use std::{
        ffi::OsStr,
        io::Result,
        process::{Command, ExitStatus, Stdio},
    };

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> Result<ExitStatus> {
        Command::new("open")
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path.as_ref())
            .spawn()?
            .wait()
    }

    pub fn with<T: AsRef<OsStr> + Sized>(path: T, app: impl Into<String>) -> Result<ExitStatus> {
        Command::new("open")
            .arg(path.as_ref())
            .arg("-a")
            .arg(app.into())
            .spawn()?
            .wait()
    }
}

#[cfg(any(
    target_os = "linux",
    target_os = "freebsd",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
mod unix {
    use std::{
        ffi::OsStr,
        io::{Error, Result},
        process::{Command, ExitStatus, Stdio},
    };

    use which::which;

    pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> Result<ExitStatus> {
        ["xdg-open", "gnome-open", "kde-open", "wslview"] // Open handlers
            .iter()
            .find(|it| which(it).is_ok()) // find the first handler that exists
            .ok_or(Error::from_raw_os_error(0)) // If not found, return err
            .and_then(|program| {
                // If found run the handler
                Command::new(program)
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .arg(path.as_ref())
                    .spawn()?
                    .wait()
            })
    }

    pub fn with<T: AsRef<OsStr> + Sized>(path: T, app: impl Into<String>) -> Result<ExitStatus> {
        Command::new(app.into()).arg(path.as_ref()).spawn()?.wait()
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]
#![feature(box_syntax)]
#![cfg_attr(test, feature(test))]
#![feature(alloc)]
#![feature(libc)]

#[cfg(feature = "c_api")]
extern crate libc;
extern crate lzw;
extern crate num;

#[macro_use] extern crate enum_primitive;

mod traits;
mod reader;
mod writer;

#[cfg(feature = "c_api")]
mod c_api_utils;
#[cfg(feature = "c_api")]
pub mod c_api;

pub use traits::HasParameters;

pub use reader::{Decoder, Progress, Decoded, DecodingError, Frame};
/// Decoder configuration parameters
pub use reader::{ColorOutput, Extensions};
pub use reader::{Block, Extension, DisposalMethod};
pub use reader::Reader;

pub use writer::{Encoder, HeaderWritten, ExtensionData};

#[cfg(test)]
#[test]
fn round_trip() {
	use std::io::prelude::*;
	use std::fs::File;
	let mut data = vec![];
	File::open("tests/samples/sample_1.gif").unwrap().read_to_end(&mut data).unwrap();
	let mut decoder = Reader::new(&*data);
    let frame = &decoder.read_to_end().unwrap()[0];
	let mut data2 = vec![];
	{
		let mut encoder = Encoder::new(&mut data2, frame.width, frame.height);
		let _ = encoder.write_frame(frame);
	}

}<commit_msg>add encoding test case<commit_after>#![feature(collections)]
#![feature(core)]
#![feature(box_syntax)]
#![cfg_attr(test, feature(test))]
#![feature(alloc)]
#![feature(libc)]

#[cfg(feature = "c_api")]
extern crate libc;
extern crate lzw;
extern crate num;

#[macro_use] extern crate enum_primitive;

mod traits;
mod reader;
mod writer;

#[cfg(feature = "c_api")]
mod c_api_utils;
#[cfg(feature = "c_api")]
pub mod c_api;

pub use traits::HasParameters;

pub use reader::{Decoder, Progress, Decoded, DecodingError, Frame};
/// Decoder configuration parameters
pub use reader::{ColorOutput, Extensions};
pub use reader::{Block, Extension, DisposalMethod};
pub use reader::Reader;

pub use writer::{Encoder, HeaderWritten, ExtensionData};

#[cfg(test)]
#[test]
fn round_trip() {
	use std::io::prelude::*;
	use std::fs::File;
	let mut data = vec![];
	File::open("tests/samples/sample_1.gif").unwrap().read_to_end(&mut data).unwrap();
	let mut decoder = Reader::new(&*data);
	let _ = decoder.read_to_end().unwrap();
	let mut data2 = vec![];
	{
    	let encoder = {
    		let frame = &decoder.frames()[0];
    		Encoder::new(&mut data2, frame.width, frame.height)
    	};
		let mut encoder = encoder.write_global_palette(decoder.global_palette()).unwrap();
		let frame = &decoder.frames()[0];

		encoder.write_frame(frame).unwrap();
	}
	assert_eq!(&data[..], &data2[..])
}<|endoftext|>


<commit_before>#![crate_name = "seax_compiler_tools"]
#![crate_type = "lib"]
#![stable(feature = "tools", since = "0.0.1")]
#![feature(staged_api)]
#![staged_api]

//! Seax Compiler Tools
//! -------------------
//!
//! Library containing general-purpose tools for compiling programs for
//! the [Seax](hawkweisman.me/seax) platform.

#[macro_use]
extern crate seax_svm as svm;

#[stable(feature = "forktable", since = "0.0.1")]
pub mod forktable;
#[stable(feature = "ast", since = "0.0.1")]
pub mod ast;

#[stable(feature = "scope", since = "0.0.1")]
pub type Index = (u64, u64);

/// The symbol table for bound names is represented as a
/// `ForkTable` mapping `&str` (names) to `(uint,uint)` tuples,
/// representing the location in the `$e` stack storing the value
/// bound to that name.
#[stable(feature = "forktable", since = "0.0.1")]
pub type SymTable<'a> = self::forktable::ForkTable<'a, &'a str, Index>;

/// A `CompileResult` is either `Ok(SVMCell)` or `Err(&str)`
#[stable(feature = "compile", since = "0.0.1")]
pub type CompileResult = Result<Vec<svm::cell::SVMCell>, String>;

/// Trait for a symbol table
#[stable(feature = "scope", since = "0.0.1")]
pub trait Scope<K>
    where K: Eq + std::hash::Hash
{
    /// Bind a name to a scope.
    ///
    /// Returnsthe indices for that name in the SVM environment.
    #[stable(feature = "scope", since = "0.0.1")]
    fn bind(&mut self, name: K, lvl: u64) -> Index;
    /// Look up a name against a scope.
    ///
    /// Returns the indices for that name in the SVM environment,
    /// or None if that name is unbound.
    #[stable(feature = "scope", since = "0.0.1")]
    fn lookup(&self, name: &K)            -> Option<Index>;
}
<commit_msg>Add conditional compilation for #1<commit_after>#![crate_name = "seax_compiler_tools"]
#![crate_type = "lib"]
#![cfg_attr(feature = "nightly" feature(staged_api) )]
#![cfg_attr(feature = "nightly" staged_api)]
#![stable(feature = "tools", since = "0.0.1")]

//! Seax Compiler Tools
//! -------------------
//!
//! Library containing general-purpose tools for compiling programs for
//! the [Seax](hawkweisman.me/seax) platform.

#[macro_use]
extern crate seax_svm as svm;

#[stable(feature = "forktable", since = "0.0.1")]
pub mod forktable;
#[stable(feature = "ast", since = "0.0.1")]
pub mod ast;

#[stable(feature = "scope", since = "0.0.1")]
pub type Index = (u64, u64);

/// The symbol table for bound names is represented as a
/// `ForkTable` mapping `&str` (names) to `(uint,uint)` tuples,
/// representing the location in the `$e` stack storing the value
/// bound to that name.
#[stable(feature = "forktable", since = "0.0.1")]
pub type SymTable<'a> = self::forktable::ForkTable<'a, &'a str, Index>;

/// A `CompileResult` is either `Ok(SVMCell)` or `Err(&str)`
#[stable(feature = "compile", since = "0.0.1")]
pub type CompileResult = Result<Vec<svm::cell::SVMCell>, String>;

/// Trait for a symbol table
#[stable(feature = "scope", since = "0.0.1")]
pub trait Scope<K>
    where K: Eq + std::hash::Hash
{
    /// Bind a name to a scope.
    ///
    /// Returnsthe indices for that name in the SVM environment.
    #[stable(feature = "scope", since = "0.0.1")]
    fn bind(&mut self, name: K, lvl: u64) -> Index;
    /// Look up a name against a scope.
    ///
    /// Returns the indices for that name in the SVM environment,
    /// or None if that name is unbound.
    #[stable(feature = "scope", since = "0.0.1")]
    fn lookup(&self, name: &K)            -> Option<Index>;
}
<|endoftext|>


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

//! # Message Format
//!
//! A [`Message`] is a piece of user-visible text that typically has
//! variable elements.
//!
//! This crate provides [ICU-style message formatting]. This provides
//! for formatting values taking localization rules into account. ICU
//! MessageFormat is widely supported in many languages and environments.
//! This library will endeavor to support all of the ICU MessageFormat
//! with the exception of the deprecated `ChoiceFormat`.
//!
//! [`Message`]: struct.Message.html
//! [ICU-style message formatting]: http://userguide.icu-project.org/formatparse/messages

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate nom;

use std::fmt;

pub mod ast;
mod parse_message;

use ast::Format;
pub use self::parse_message::parse_message;

/// A message that has been localized and can be formatted in a
/// locale-aware manner.
pub struct Message {
    parts: Vec<Box<Format>>,
}

impl Message {
    /// Construct a message from constituent parts.
    pub fn new(parts: Vec<Box<Format>>) -> Self {
        Message { parts: parts }
    }

    /// Format a message to a stream.
    pub fn format_message(&self, stream: &mut fmt::Write, args: &Args) -> fmt::Result {
        for part in &self.parts {
            try!(part.apply_format(stream, args));
        }
        Ok(())
    }
}

#[allow(dead_code,missing_docs)]
pub struct FormatArg<'a, T: 'a + fmt::Display> {
    name: &'a str,
    value: &'a T,
    prev: Option<&'a Args<'a>>,
}

#[allow(missing_docs)]
pub fn arg<'a, T: 'a + fmt::Display>(name: &'a str, value: &'a T) -> FormatArg<'a, T> {
    FormatArg {
        name: name,
        value: value,
        prev: None,
    }
}

#[allow(missing_docs)]
pub trait Args<'a> {
    fn arg<T: fmt::Display>(&'a self, name: &'a str, value: &'a T) -> FormatArg<'a, T>
        where Self: Sized
    {
        FormatArg {
            name: name,
            value: value,
            prev: Some(self),
        }
    }

    fn get(&self, name: &str) -> Option<&fmt::Display>;

    fn next(&self) -> Option<&'a Args<'a>>;
}

impl<'a, T> Args<'a> for FormatArg<'a, T>
    where T: std::fmt::Display
{
    fn next(&self) -> Option<&'a Args<'a>> {
        self.prev
    }

    #[allow(missing_docs)]
    fn get(&self, _name: &str) -> Option<&fmt::Display> {
        None
        // self.args.iter().find(|ref a| a.name == name).map(|a| a.value)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>Rename FormatArg back to Arg.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Message Format
//!
//! A [`Message`] is a piece of user-visible text that typically has
//! variable elements.
//!
//! This crate provides [ICU-style message formatting]. This provides
//! for formatting values taking localization rules into account. ICU
//! MessageFormat is widely supported in many languages and environments.
//! This library will endeavor to support all of the ICU MessageFormat
//! with the exception of the deprecated `ChoiceFormat`.
//!
//! [`Message`]: struct.Message.html
//! [ICU-style message formatting]: http://userguide.icu-project.org/formatparse/messages

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate nom;

use std::fmt;

pub mod ast;
mod parse_message;

use ast::Format;
pub use self::parse_message::parse_message;

/// A message that has been localized and can be formatted in a
/// locale-aware manner.
pub struct Message {
    parts: Vec<Box<Format>>,
}

impl Message {
    /// Construct a message from constituent parts.
    pub fn new(parts: Vec<Box<Format>>) -> Self {
        Message { parts: parts }
    }

    /// Format a message to a stream.
    pub fn format_message(&self, stream: &mut fmt::Write, args: &Args) -> fmt::Result {
        for part in &self.parts {
            try!(part.apply_format(stream, args));
        }
        Ok(())
    }
}

#[allow(dead_code,missing_docs)]
pub struct Arg<'a, T: 'a + fmt::Display> {
    name: &'a str,
    value: &'a T,
    prev: Option<&'a Args<'a>>,
}

#[allow(missing_docs)]
pub fn arg<'a, T: 'a + fmt::Display>(name: &'a str, value: &'a T) -> Arg<'a, T> {
    Arg {
        name: name,
        value: value,
        prev: None,
    }
}

#[allow(missing_docs)]
pub trait Args<'a> {
    fn arg<T: fmt::Display>(&'a self, name: &'a str, value: &'a T) -> Arg<'a, T>
        where Self: Sized
    {
        Arg {
            name: name,
            value: value,
            prev: Some(self),
        }
    }

    fn get(&self, name: &str) -> Option<&fmt::Display>;

    fn next(&self) -> Option<&'a Args<'a>>;
}

impl<'a, T> Args<'a> for Arg<'a, T>
    where T: std::fmt::Display
{
    fn next(&self) -> Option<&'a Args<'a>> {
        self.prev
    }

    #[allow(missing_docs)]
    fn get(&self, _name: &str) -> Option<&fmt::Display> {
        None
        // self.args.iter().find(|ref a| a.name == name).map(|a| a.value)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>/*!

A basic library for finding primes, providing a basic Iterator over all primes. It is not as fast as
`slow_primes`, but it is meant to be easy to use!

The simplest usage is simply to create an `Iterator`:

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();

for (ix, n) in pset.iter().enumerate().take(10) {
    println!("Prime {}: {}", ix, n);
}
```

This library provides methods for generating primes, testing whether a number is prime, and
factorizing numbers. Most methods generate primes lazily, so only enough primes will be generated
for the given test, and primes are cached for later use.

[*Source*](https://github.com/wackywendell/primes)

# Example: Find the millionth prime

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000_000);

println!("Prime {}: {}", ix, n);
```

# Example: Find the first ten primes *after* the thousandth prime
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
for (ix, n) in pset.iter().enumerate().skip(1_000).take(10) {
    println!("Prime {}: {}", ix, n);
}
```

# Example: Find the first prime greater than 1000
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000);
println!("The first prime after 1000 is the {}th prime: {}", ix, n);

assert_eq!(pset.find(n), (ix, n));
```

For more info on use, see `PrimeSet`, a class which handles the Sieve and has multiple methods for
iterating over primes.

This also provides a few functions unconnected to `PrimeSet`, which will be faster for the first
case, but slower in the long term as they do not use any caching of primes.

*/
#![doc(html_root_url = "https://wackywendell.github.io/primes/")]

use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::Index;
use std::slice;

/** A prime generator, using the Sieve of Eratosthenes.

Create with `let mut pset = PrimeSet::new()`, and then use `pset.iter()` to iterate over all primes.
**/
#[derive(Default)]
pub struct PrimeSet {
    lst: Vec<u64>,
}

/// An iterator over generated primes. Created by PrimeSet::iter or
/// PrimeSet::generator
pub struct PrimeSetIter<'a> {
    p: &'a mut PrimeSet,
    n: usize,
    expand: bool,
}

impl PrimeSet {
    /// A new prime generator, primed with 2 and 3
    pub fn new() -> PrimeSet {
        PrimeSet { lst: vec![2, 3] }
    }

    /// Finds one more prime, and adds it to the list
    pub fn expand(&mut self) {
        let mut l: u64 = self.lst[self.lst.len() - 1] + 2;
        let mut remainder = 0;
        loop {
            for &n in &self.lst {
                remainder = l % n;
                if remainder == 0 || n * n > l {
                    break;
                }
            }

            if remainder != 0 {
                self.lst.push(l);
                break;
            };

            l += 2;
        }
    }

    /// Number of primes found so far
    pub fn len(&self) -> usize {
        self.lst.len()
    }

    pub fn is_empty(&self) -> bool {
        false
    }

    /// Return all primes found so far as a slice
    pub fn list(&self) -> &[u64] {
        &self.lst[..]
    }

    /// Iterator over all primes not yet found
    pub fn generator(&mut self) -> PrimeSetIter {
        let myn = self.len();
        PrimeSetIter {
            p: self,
            n: myn,
            expand: true,
        }
    }

    /// Iterator over all primes, starting with 2. If you don't care about the "state" of the
    /// PrimeSet, this is what you want!
    pub fn iter(&mut self) -> PrimeSetIter {
        PrimeSetIter {
            p: self,
            n: 0,
            expand: true,
        }
    }

    //~ pub fn iter_once(&'self mut self) -> PrimeSetIter<'self> {
    //~ PrimeSetIter{p:self, n:0, expand:false}
    //~ }

    /// Iterator over just the primes found so far
    pub fn iter_vec(&self) -> slice::Iter<u64> {
        self.lst.iter()
    }

    /// Find the next largest prime from a number
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find(&mut self, n: u64) -> (usize, u64) {
        while n > *(self.lst.last().unwrap_or(&0)) {
            self.expand();
        }
        self.find_vec(n).unwrap()
    }

    /// Check if a number is prime
    /// Note that this only requires primes up to n.sqrt() to be generated, and will generate
    /// them as necessary on its own.
    #[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
    pub fn is_prime(&mut self, n: u64) -> bool {
        if n <= 1 {
            return false;
        }
        if n == 2 {
            return true;
        } // otherwise we get 2 % 2 == 0!
        for m in self.iter() {
            if n % m == 0 {
                return false;
            };
            if m * m > n {
                return true;
            };
        }
        unreachable!("This iterator should not be empty.");
    }

    /// Find the next largest prime from a number, if it is within the already-found list
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find_vec(&self, n: u64) -> Option<(usize, u64)> {
        if n > *(self.lst.last().unwrap_or(&0)) {
            return None;
        }

        let mut base: usize = 0;
        let mut lim: usize = self.len();

        // Binary search algorithm
        while lim != 0 {
            let ix = base + (lim >> 1);
            match self.lst[ix].cmp(&n) {
                Equal => return Some((ix, self.lst[ix])),
                Less => {
                    base = ix + 1;
                    lim -= 1;
                }
                Greater => (),
            }
            lim >>= 1;
        }
        Some((base, self.lst[base]))
    }

    /// Get the nth prime, even if we haven't yet found it
    pub fn get(&mut self, index: usize) -> u64 {
        for _ in 0..(index as isize) + 1 - (self.lst.len() as isize) {
            self.expand();
        }
        self.lst[index]
    }

    /// Get the prime factors of a number, starting from 2, including repeats
    pub fn prime_factors(&mut self, n: u64) -> Vec<u64> {
        if n == 1 {
            return Vec::new();
        }
        let mut curn = n;
        let mut lst: Vec<u64> = Vec::new();
        for p in self.iter() {
            while curn % p == 0 {
                println!("Pushing {} ({} / {})", p, curn, n);
                lst.push(p);
                curn /= p;
                if curn == 1 {
                    return lst;
                }
            }

            if p * p > curn {
                println!("Final push {} ({} / {})", p, curn, n);
                lst.push(curn);
                return lst;
            }
        }
        unreachable!("This should be unreachable.");
    }
}

impl Index<usize> for PrimeSet {
    type Output = u64;
    fn index(&self, index: usize) -> &u64 {
        &self.lst[index]
    }
}

impl<'a> Iterator for PrimeSetIter<'a> {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        while self.n >= self.p.len() {
            if self.expand {
                self.p.expand()
            } else {
                return None;
            }
        }
        self.n += 1;

        let m = self.p.lst[self.n - 1];

        Some(m)
    }
}

/// Find the first factor (other than 1) of a number
fn firstfac(x: u64) -> u64 {
    if x % 2 == 0 {
        return 2;
    };
    // TODO: return to step_by
    // for n in (3..).step_by(2).take_while(|m| m*m <= x) {
    for n in (1..).map(|m| 2 * m + 1).take_while(|m| m * m <= x) {
        if x % n == 0 {
            return n;
        };
    }
    // No factor found. It must be prime.
    x
}

/// Find all prime factors of a number
/// Does not use a PrimeSet, but simply counts upwards
pub fn factors(x: u64) -> Vec<u64> {
    if x <= 1 {
        return vec![];
    };
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop {
        let m = firstfac(curn);
        lst.push(m);
        if m == curn {
            break;
        } else {
            curn /= m
        };
    }
    lst
}

/// Find all unique prime factors of a number
pub fn factors_uniq(x: u64) -> Vec<u64> {
    if x <= 1 {
        return vec![];
    };
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop {
        let m = firstfac(curn);
        lst.push(m);
        if curn == m {
            break;
        }
        while curn % m == 0 {
            curn /= m;
        }
        if curn == 1 {
            break;
        }
    }
    lst
}

/// Test whether a number is prime. Checks every odd number up to sqrt(n).
pub fn is_prime(n: u64) -> bool {
    if n <= 1 {
        return false;
    }
    firstfac(n) == n
}
<commit_msg>Fix docs<commit_after>/*!

A basic library for finding primes, providing a basic Iterator over all primes. It is not as fast as
`slow_primes`, but it is meant to be easy to use!

The simplest usage is simply to create an `Iterator`:

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();

for (ix, n) in pset.iter().enumerate().take(10) {
    println!("Prime {}: {}", ix, n);
}
```

This library provides methods for generating primes, testing whether a number is prime, and
factorizing numbers. Most methods generate primes lazily, so only enough primes will be generated
for the given test, and primes are cached for later use.

[*Source*](https://github.com/wackywendell/primes)

# Example: Find the first prime after 1 million

```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000_000);

println!("Prime {}: {}", ix, n);
```

# Example: Find the first ten primes *after* the thousandth prime
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
for (ix, n) in pset.iter().enumerate().skip(1_000).take(10) {
    println!("Prime {}: {}", ix, n);
}
```

# Example: Find the first prime greater than 1000
```
use primes::PrimeSet;

let mut pset = PrimeSet::new();
let (ix, n) = pset.find(1_000);
println!("The first prime after 1000 is the {}th prime: {}", ix, n);

assert_eq!(pset.find(n), (ix, n));
```

For more info on use, see `PrimeSet`, a class which handles the Sieve and has multiple methods for
iterating over primes.

This also provides a few functions unconnected to `PrimeSet`, which will be faster for the first
case, but slower in the long term as they do not use any caching of primes.

*/
#![doc(html_root_url = "https://wackywendell.github.io/primes/")]

use std::cmp::Ordering::{Equal, Greater, Less};
use std::ops::Index;
use std::slice;

/** A prime generator, using the Sieve of Eratosthenes.

Create with `let mut pset = PrimeSet::new()`, and then use `pset.iter()` to iterate over all primes.
**/
#[derive(Default)]
pub struct PrimeSet {
    lst: Vec<u64>,
}

/// An iterator over generated primes. Created by PrimeSet::iter or
/// PrimeSet::generator
pub struct PrimeSetIter<'a> {
    p: &'a mut PrimeSet,
    n: usize,
    expand: bool,
}

impl PrimeSet {
    /// A new prime generator, primed with 2 and 3
    pub fn new() -> PrimeSet {
        PrimeSet { lst: vec![2, 3] }
    }

    /// Finds one more prime, and adds it to the list
    pub fn expand(&mut self) {
        let mut l: u64 = self.lst[self.lst.len() - 1] + 2;
        let mut remainder = 0;
        loop {
            for &n in &self.lst {
                remainder = l % n;
                if remainder == 0 || n * n > l {
                    break;
                }
            }

            if remainder != 0 {
                self.lst.push(l);
                break;
            };

            l += 2;
        }
    }

    /// Number of primes found so far
    pub fn len(&self) -> usize {
        self.lst.len()
    }

    pub fn is_empty(&self) -> bool {
        false
    }

    /// Return all primes found so far as a slice
    pub fn list(&self) -> &[u64] {
        &self.lst[..]
    }

    /// Iterator over all primes not yet found
    pub fn generator(&mut self) -> PrimeSetIter {
        let myn = self.len();
        PrimeSetIter {
            p: self,
            n: myn,
            expand: true,
        }
    }

    /// Iterator over all primes, starting with 2. If you don't care about the "state" of the
    /// PrimeSet, this is what you want!
    pub fn iter(&mut self) -> PrimeSetIter {
        PrimeSetIter {
            p: self,
            n: 0,
            expand: true,
        }
    }

    //~ pub fn iter_once(&'self mut self) -> PrimeSetIter<'self> {
    //~ PrimeSetIter{p:self, n:0, expand:false}
    //~ }

    /// Iterator over just the primes found so far
    pub fn iter_vec(&self) -> slice::Iter<u64> {
        self.lst.iter()
    }

    /// Find the next largest prime from a number
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find(&mut self, n: u64) -> (usize, u64) {
        while n > *(self.lst.last().unwrap_or(&0)) {
            self.expand();
        }
        self.find_vec(n).unwrap()
    }

    /// Check if a number is prime
    /// Note that this only requires primes up to n.sqrt() to be generated, and will generate
    /// them as necessary on its own.
    #[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
    pub fn is_prime(&mut self, n: u64) -> bool {
        if n <= 1 {
            return false;
        }
        if n == 2 {
            return true;
        } // otherwise we get 2 % 2 == 0!
        for m in self.iter() {
            if n % m == 0 {
                return false;
            };
            if m * m > n {
                return true;
            };
        }
        unreachable!("This iterator should not be empty.");
    }

    /// Find the next largest prime from a number, if it is within the already-found list
    /// Returns (idx, prime)
    /// Note that if n is prime, then the output will be (idx, n)
    pub fn find_vec(&self, n: u64) -> Option<(usize, u64)> {
        if n > *(self.lst.last().unwrap_or(&0)) {
            return None;
        }

        let mut base: usize = 0;
        let mut lim: usize = self.len();

        // Binary search algorithm
        while lim != 0 {
            let ix = base + (lim >> 1);
            match self.lst[ix].cmp(&n) {
                Equal => return Some((ix, self.lst[ix])),
                Less => {
                    base = ix + 1;
                    lim -= 1;
                }
                Greater => (),
            }
            lim >>= 1;
        }
        Some((base, self.lst[base]))
    }

    /// Get the nth prime, even if we haven't yet found it
    pub fn get(&mut self, index: usize) -> u64 {
        for _ in 0..(index as isize) + 1 - (self.lst.len() as isize) {
            self.expand();
        }
        self.lst[index]
    }

    /// Get the prime factors of a number, starting from 2, including repeats
    pub fn prime_factors(&mut self, n: u64) -> Vec<u64> {
        if n == 1 {
            return Vec::new();
        }
        let mut curn = n;
        let mut lst: Vec<u64> = Vec::new();
        for p in self.iter() {
            while curn % p == 0 {
                println!("Pushing {} ({} / {})", p, curn, n);
                lst.push(p);
                curn /= p;
                if curn == 1 {
                    return lst;
                }
            }

            if p * p > curn {
                println!("Final push {} ({} / {})", p, curn, n);
                lst.push(curn);
                return lst;
            }
        }
        unreachable!("This should be unreachable.");
    }
}

impl Index<usize> for PrimeSet {
    type Output = u64;
    fn index(&self, index: usize) -> &u64 {
        &self.lst[index]
    }
}

impl<'a> Iterator for PrimeSetIter<'a> {
    type Item = u64;
    fn next(&mut self) -> Option<u64> {
        while self.n >= self.p.len() {
            if self.expand {
                self.p.expand()
            } else {
                return None;
            }
        }
        self.n += 1;

        let m = self.p.lst[self.n - 1];

        Some(m)
    }
}

/// Find the first factor (other than 1) of a number
fn firstfac(x: u64) -> u64 {
    if x % 2 == 0 {
        return 2;
    };
    // TODO: return to step_by
    // for n in (3..).step_by(2).take_while(|m| m*m <= x) {
    for n in (1..).map(|m| 2 * m + 1).take_while(|m| m * m <= x) {
        if x % n == 0 {
            return n;
        };
    }
    // No factor found. It must be prime.
    x
}

/// Find all prime factors of a number
/// Does not use a PrimeSet, but simply counts upwards
pub fn factors(x: u64) -> Vec<u64> {
    if x <= 1 {
        return vec![];
    };
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop {
        let m = firstfac(curn);
        lst.push(m);
        if m == curn {
            break;
        } else {
            curn /= m
        };
    }
    lst
}

/// Find all unique prime factors of a number
pub fn factors_uniq(x: u64) -> Vec<u64> {
    if x <= 1 {
        return vec![];
    };
    let mut lst: Vec<u64> = Vec::new();
    let mut curn = x;
    loop {
        let m = firstfac(curn);
        lst.push(m);
        if curn == m {
            break;
        }
        while curn % m == 0 {
            curn /= m;
        }
        if curn == 1 {
            break;
        }
    }
    lst
}

/// Test whether a number is prime. Checks every odd number up to sqrt(n).
pub fn is_prime(n: u64) -> bool {
    if n <= 1 {
        return false;
    }
    firstfac(n) == n
}
<|endoftext|>