<commit_before>use Result;
use DocId;
use schema::Schema;
use schema::Document;
use schema::Term;
use schema::FieldEntry;
use core::segment_serializer::SegmentSerializer;
use core::index::SegmentInfo;
use core::index::Segment;
use analyzer::SimpleTokenizer;
use core::index::SerializableSegment;
use analyzer::StreamingIterator;
use postings::PostingsWriter;
use fastfield::U32FastFieldsWriter;
use std::clone::Clone;
use schema::Field;
use schema::FieldValue;
use schema::TextIndexingOptions;
use postings::SpecializedPostingsWriter;
use postings::{NothingRecorder, TermFrequencyRecorder, TFAndPositionRecorder};

pub struct SegmentWriter {
    max_doc: DocId,
	tokenizer: SimpleTokenizer,
	per_field_postings_writers: Vec<Box<PostingsWriter>>,
	segment_serializer: SegmentSerializer,
	fast_field_writers: U32FastFieldsWriter,
	fieldnorms_writer: U32FastFieldsWriter,
}

fn create_fieldnorms_writer(schema: &Schema) -> U32FastFieldsWriter {
	let u32_fields: Vec<Field> = schema.fields()
		.iter()
		.enumerate()
		.filter(|&(_, field_entry)| field_entry.is_indexed())
		.map(|(field_id, _)| Field(field_id as u8))
		.collect();
	U32FastFieldsWriter::new(u32_fields)
}

fn posting_from_field_entry(field_entry: &FieldEntry) -> Box<PostingsWriter> {
	match field_entry {
		&FieldEntry::Text(_, ref text_options) => {
			match text_options.get_indexing_options() {
				TextIndexingOptions::TokenizedWithFreq => {
					SpecializedPostingsWriter::<TermFrequencyRecorder>::new_boxed()
				}
				TextIndexingOptions::TokenizedWithFreqAndPosition => {
					SpecializedPostingsWriter::<TFAndPositionRecorder>::new_boxed()
				}
				_ => {
					SpecializedPostingsWriter::<NothingRecorder>::new_boxed()
				}
			}
		}
		&FieldEntry::U32(_, _) => {
			SpecializedPostingsWriter::<NothingRecorder>::new_boxed()
		}
	}
}

impl SegmentWriter {
	pub fn for_segment(segment: Segment, schema: &Schema) -> Result<SegmentWriter> {
		let segment_serializer = try!(SegmentSerializer::for_segment(&segment));
		let per_field_postings_writers = schema.fields()
			  .iter()
			  .map(|field_entry| {
				  posting_from_field_entry(field_entry)
			  })
			  .collect();

		Ok(SegmentWriter {
			max_doc: 0,
			per_field_postings_writers: per_field_postings_writers,
			fieldnorms_writer: create_fieldnorms_writer(schema),
			segment_serializer: segment_serializer,
			tokenizer: SimpleTokenizer::new(),
			fast_field_writers: U32FastFieldsWriter::from_schema(schema),
		})
	}

	// Write on disk all of the stuff that
	// is still on RAM :
	// - the dictionary in an fst
	// - the postings
	// - the segment info
	// The segment writer cannot be used after this, which is
	// enforced by the fact that "self" is moved.
	pub fn finalize(mut self,) -> Result<()> {
		let segment_info = self.segment_info();
		for per_field_postings_writer in self.per_field_postings_writers.iter_mut() {
			per_field_postings_writer.close();
		}
		write(&self.per_field_postings_writers,
			  &self.fast_field_writers,
			  &self.fieldnorms_writer,
			  segment_info,
			  self.segment_serializer)
	}

    pub fn add_document(&mut self, doc: &Document, schema: &Schema) -> Result<()> {
        let doc_id = self.max_doc;
        for (field, field_values) in doc.get_sorted_fields() {
			let mut num_tokens: usize = 0;
			let field_posting_writers: &mut Box<PostingsWriter> = &mut self.per_field_postings_writers[field.0 as usize];
			for field_value in field_values {
				let field_options = schema.get_field_entry(field);
				match *field_options {
					FieldEntry::Text(_, ref text_options) => {
						if text_options.get_indexing_options().is_tokenized() {
							let mut tokens = self.tokenizer.tokenize(field_value.text());
							// right now num_tokens and pos are redundant, but it should
							// change when we get proper analyzers

							let mut pos = 0u32;
							let field = field_value.field();
							loop {
								match tokens.next() {
									Some(token) => {
										let term = Term::from_field_text(field, token);
										field_posting_writers.suscribe(doc_id, pos, term);
										pos += 1;
										num_tokens += 1;
									},
									None => { break; }
								}
							}
						}
						else {
							let term = Term::from_field_text(field, field_value.text());
							field_posting_writers.suscribe(doc_id, 0, term);
						}
					}
					FieldEntry::U32(_, ref u32_options) => {
						if u32_options.is_indexed() {
							let term = Term::from_field_u32(field_value.field(), field_value.u32_value());
							field_posting_writers.suscribe(doc_id, 0, term);
						}
					}
				}
			}
			self.fieldnorms_writer
				.get_field_writer(field)
				.map(|field_norms_writer| {
					field_norms_writer.add_val(num_tokens as u32)
				});
		}

		self.fieldnorms_writer.fill_val_up_to(doc_id);

		self.fast_field_writers.add_document(&doc);
		let stored_fieldvalues: Vec<&FieldValue> = doc
			.get_fields()
			.iter()
			.filter(|field_value| schema.get_field_entry(field_value.field()).is_stored())
			.collect();
		let doc_writer = self.segment_serializer.get_store_writer();
		try!(doc_writer.store(&stored_fieldvalues));
        self.max_doc += 1;
		Ok(())
    }

	fn segment_info(&self,) -> SegmentInfo {
		SegmentInfo {
			max_doc: self.max_doc
		}
	}
}

fn write(per_field_postings_writers: &Vec<Box<PostingsWriter>>,
		 fast_field_writers: &U32FastFieldsWriter,
		 fieldnorms_writer: &U32FastFieldsWriter,
		 segment_info: SegmentInfo,
	  	mut serializer: SegmentSerializer) -> Result<()> {
		for per_field_postings_writer in per_field_postings_writers.iter() {
			try!(per_field_postings_writer.serialize(serializer.get_postings_serializer()));
		}
		try!(fast_field_writers.serialize(serializer.get_fast_field_serializer()));
		try!(fieldnorms_writer.serialize(serializer.get_fieldnorms_serializer()));
		try!(serializer.write_segment_info(&segment_info));
		try!(serializer.close());
		Ok(())
}

impl SerializableSegment for SegmentWriter {
	fn write(&self, serializer: SegmentSerializer) -> Result<()> {
		write(&self.per_field_postings_writers,
		      &self.fast_field_writers,
			  &self.fieldnorms_writer,
			  self.segment_info(),
		      serializer)
	}
}
<commit_msg>moving stuff around in the segment writer<commit_after>use Result;
use DocId;
use schema::Schema;
use schema::Document;
use schema::Term;
use schema::FieldEntry;
use core::segment_serializer::SegmentSerializer;
use core::index::SegmentInfo;
use core::index::Segment;
use analyzer::SimpleTokenizer;
use core::index::SerializableSegment;
use analyzer::StreamingIterator;
use postings::PostingsWriter;
use fastfield::U32FastFieldsWriter;
use schema::Field;
use schema::FieldValue;
use schema::TextIndexingOptions;
use postings::SpecializedPostingsWriter;
use postings::{NothingRecorder, TermFrequencyRecorder, TFAndPositionRecorder};

pub struct SegmentWriter {
    max_doc: DocId,
	tokenizer: SimpleTokenizer,
	per_field_postings_writers: Vec<Box<PostingsWriter>>,
	segment_serializer: SegmentSerializer,
	fast_field_writers: U32FastFieldsWriter,
	fieldnorms_writer: U32FastFieldsWriter,
}

fn create_fieldnorms_writer(schema: &Schema) -> U32FastFieldsWriter {
	let u32_fields: Vec<Field> = schema.fields()
		.iter()
		.enumerate()
		.filter(|&(_, field_entry)| field_entry.is_indexed())
		.map(|(field_id, _)| Field(field_id as u8))
		.collect();
	U32FastFieldsWriter::new(u32_fields)
}

fn posting_from_field_entry(field_entry: &FieldEntry) -> Box<PostingsWriter> {
	match field_entry {
		&FieldEntry::Text(_, ref text_options) => {
			match text_options.get_indexing_options() {
				TextIndexingOptions::TokenizedWithFreq => {
					SpecializedPostingsWriter::<TermFrequencyRecorder>::new_boxed()
				}
				TextIndexingOptions::TokenizedWithFreqAndPosition => {
					SpecializedPostingsWriter::<TFAndPositionRecorder>::new_boxed()
				}
				_ => {
					SpecializedPostingsWriter::<NothingRecorder>::new_boxed()
				}
			}
		}
		&FieldEntry::U32(_, _) => {
			SpecializedPostingsWriter::<NothingRecorder>::new_boxed()
		}
	}
}

impl SegmentWriter {
	pub fn for_segment(segment: Segment, schema: &Schema) -> Result<SegmentWriter> {
		let segment_serializer = try!(SegmentSerializer::for_segment(&segment));
		let per_field_postings_writers = schema.fields()
			  .iter()
			  .map(|field_entry| {
				  posting_from_field_entry(field_entry)
			  })
			  .collect();

		Ok(SegmentWriter {
			max_doc: 0,
			per_field_postings_writers: per_field_postings_writers,
			fieldnorms_writer: create_fieldnorms_writer(schema),
			segment_serializer: segment_serializer,
			tokenizer: SimpleTokenizer::new(),
			fast_field_writers: U32FastFieldsWriter::from_schema(schema),
		})
	}

	// Write on disk all of the stuff that
	// is still on RAM :
	// - the dictionary in an fst
	// - the postings
	// - the segment info
	// The segment writer cannot be used after this, which is
	// enforced by the fact that "self" is moved.
	pub fn finalize(mut self,) -> Result<()> {
		let segment_info = self.segment_info();
		for per_field_postings_writer in self.per_field_postings_writers.iter_mut() {
			per_field_postings_writer.close();
		}
		write(&self.per_field_postings_writers,
			  &self.fast_field_writers,
			  &self.fieldnorms_writer,
			  segment_info,
			  self.segment_serializer)
	}

    pub fn add_document(&mut self, doc: &Document, schema: &Schema) -> Result<()> {
        let doc_id = self.max_doc;
        for (field, field_values) in doc.get_sorted_fields() {
			// TODO pos collision if the field is redundant
			let field_posting_writers: &mut Box<PostingsWriter> = &mut self.per_field_postings_writers[field.0 as usize];
			let field_options = schema.get_field_entry(field);
			match *field_options {
				FieldEntry::Text(_, ref text_options) => {
					let mut pos = 0u32;
					let mut num_tokens: usize = 0;
					for field_value in field_values {
						if text_options.get_indexing_options().is_tokenized() {
							let mut tokens = self.tokenizer.tokenize(field_value.text());
							// right now num_tokens and pos are redundant, but it should
							// change when we get proper analyzers
							let field = field_value.field();
							loop {
								match tokens.next() {
									Some(token) => {
										let term = Term::from_field_text(field, token);
										field_posting_writers.suscribe(doc_id, pos, term);
										pos += 1;
										num_tokens += 1;
									},
									None => { break; }
								}
							}
						}
						else {
							let term = Term::from_field_text(field, field_value.text());
							field_posting_writers.suscribe(doc_id, 0, term);
						}
						pos += 1;
						// THIS is to avoid phrase query accross field repetition.
						// span queries might still match though :|
					}
					self.fieldnorms_writer
						.get_field_writer(field)
						.map(|field_norms_writer| {
							field_norms_writer.add_val(num_tokens as u32)
						});
				}
				FieldEntry::U32(_, ref u32_options) => {
					if u32_options.is_indexed() {
						for field_value in field_values {
							let term = Term::from_field_u32(field_value.field(), field_value.u32_value());
							field_posting_writers.suscribe(doc_id, 0, term);
						}
					}
				}
			}

		}

		self.fieldnorms_writer.fill_val_up_to(doc_id);

		self.fast_field_writers.add_document(&doc);
		let stored_fieldvalues: Vec<&FieldValue> = doc
			.get_fields()
			.iter()
			.filter(|field_value| schema.get_field_entry(field_value.field()).is_stored())
			.collect();
		let doc_writer = self.segment_serializer.get_store_writer();
		try!(doc_writer.store(&stored_fieldvalues));
        self.max_doc += 1;
		Ok(())
    }

	fn segment_info(&self,) -> SegmentInfo {
		SegmentInfo {
			max_doc: self.max_doc
		}
	}

}

fn write(per_field_postings_writers: &Vec<Box<PostingsWriter>>,
		 fast_field_writers: &U32FastFieldsWriter,
		 fieldnorms_writer: &U32FastFieldsWriter,
		 segment_info: SegmentInfo,
	  	mut serializer: SegmentSerializer) -> Result<()> {
		for per_field_postings_writer in per_field_postings_writers.iter() {
			try!(per_field_postings_writer.serialize(serializer.get_postings_serializer()));
		}
		try!(fast_field_writers.serialize(serializer.get_fast_field_serializer()));
		try!(fieldnorms_writer.serialize(serializer.get_fieldnorms_serializer()));
		try!(serializer.write_segment_info(&segment_info));
		try!(serializer.close());
		Ok(())
}

impl SerializableSegment for SegmentWriter {
	fn write(&self, serializer: SegmentSerializer) -> Result<()> {
		write(&self.per_field_postings_writers,
		      &self.fast_field_writers,
			  &self.fieldnorms_writer,
			  self.segment_info(),
		      serializer)
	}
}
<|endoftext|>


<commit_before>fn main() {
    let _x = @{a: @10, b: ~true};
}
<commit_msg>add test for issue #1466 that runs with CC ZEAL enabled.<commit_after>// exec-env:RUST_CC_ZEAL=1

fn main() {
    #error["%?", os::getenv("RUST_CC_ZEAL")];
    let _x = @{a: @10, b: ~true};
}
<|endoftext|>


<commit_before>//! [Scott numerals](http://lucacardelli.name/Papers/Notes/scott2.pdf)

use data::boolean::{tru, fls};
use term::{Term, abs, app};
use term::Term::*;

/// Produces a Scott-encoded number zero.
///
/// ZERO := λxy.x = λ λ 2
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::zero;
/// use lambda_calculus::*;
///
/// assert_eq!(zero(), 0.into_scott());
/// ```
pub fn zero() -> Term { abs!(2, Var(2)) }

/// Applied to a Scott-encoded number it produces a lambda-encoded boolean, indicating whether its
/// argument is equal to zero.
///
/// IS_ZERO := λn.n TRUE (λx.FALSE) =  λ 1 TRUE (λ FALSE)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::is_zero;
/// use lambda_calculus::data::boolean::{tru, fls};
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(is_zero(), 0.into_scott()), NOR, 0), tru());
/// assert_eq!(beta(app(is_zero(), 1.into_scott()), NOR, 0), fls());
/// ```
pub fn is_zero() -> Term {
    abs(app!(Var(1), tru(), abs(fls())))
}

/// Applied to a Scott-encoded number it produces its successor.
///
/// SUCC := λnxy.y n = λ λ λ 1 3
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::succ;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(succ(), 0.into_scott()), NOR, 0), 1.into_scott());
/// assert_eq!(beta(app(succ(), 1.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn succ() -> Term {
    abs!(3, app(Var(1), Var(3)))
}

/// Applied to a Scott-encoded number it produces its predecessor.
///
/// PRED := λn.n ZERO (λx.x) = λ 1 ZERO (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::pred;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(pred(), 1.into_scott()), NOR, 0), 0.into_scott());
/// assert_eq!(beta(app(pred(), 3.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn pred() -> Term {
    abs(app!(Var(1), zero(), abs(Var(1))))
}
<commit_msg>add scott::one<commit_after>//! [Scott numerals](http://lucacardelli.name/Papers/Notes/scott2.pdf)

use data::boolean::{tru, fls};
use term::{Term, abs, app};
use term::Term::*;

/// Produces a Scott-encoded number zero.
///
/// ZERO := λxy.x = λ λ 2
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::zero;
/// use lambda_calculus::*;
///
/// assert_eq!(zero(), 0.into_scott());
/// ```
pub fn zero() -> Term { abs!(2, Var(2)) }

/// Applied to a Scott-encoded number it produces a lambda-encoded boolean, indicating whether its
/// argument is equal to zero.
///
/// IS_ZERO := λn.n TRUE (λx.FALSE) =  λ 1 TRUE (λ FALSE)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::is_zero;
/// use lambda_calculus::data::boolean::{tru, fls};
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(is_zero(), 0.into_scott()), NOR, 0), tru());
/// assert_eq!(beta(app(is_zero(), 1.into_scott()), NOR, 0), fls());
/// ```
pub fn is_zero() -> Term {
    abs(app!(Var(1), tru(), abs(fls())))
}

/// Produces a Scott-encoded number one.
///
/// ONE := λab.b ZERO = λ λ 1 ZERO
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::one;
/// use lambda_calculus::*;
///
/// assert_eq!(one(), 1.into_scott());
/// ```
pub fn one() -> Term { abs!(2, app(Var(1), abs!(2, Var(2)))) }

/// Applied to a Scott-encoded number it produces its successor.
///
/// SUCC := λnxy.y n = λ λ λ 1 3
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::succ;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(succ(), 0.into_scott()), NOR, 0), 1.into_scott());
/// assert_eq!(beta(app(succ(), 1.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn succ() -> Term {
    abs!(3, app(Var(1), Var(3)))
}

/// Applied to a Scott-encoded number it produces its predecessor.
///
/// PRED := λn.n ZERO (λx.x) = λ 1 ZERO (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::pred;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(pred(), 1.into_scott()), NOR, 0), 0.into_scott());
/// assert_eq!(beta(app(pred(), 3.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn pred() -> Term {
    abs(app!(Var(1), zero(), abs(Var(1))))
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// 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.

//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//!   *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//!   *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.66")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
        redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    indexing_slicing,
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

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

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ops, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::arc::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Work around unused_imports rustdoc bug<commit_after>// Copyright 2017 Serde Developers
//
// 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.

//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//!   *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//!   *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.66")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
        redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    indexing_slicing,
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]

////////////////////////////////////////////////////////////////////////////////

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

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ops, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::arc::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://github.com/apache/avro/blob/master/lang/rust/avro/README.md
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.143")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        empty_enum,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        derive_partial_eq_without_eq,
        enum_glob_use,
        explicit_auto_deref,
        let_underscore_drop,
        map_err_ignore,
        new_without_default,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

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

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<commit_msg>Link to apache-avro crate's published docs<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website <https://serde.rs/> for additional documentation and
//! usage examples.
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], a superset of JSON including some productions from ES5.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//!   and from DynamoDB.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
//! [Avro]: https://docs.rs/apache-avro
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.143")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
        semicolon_if_nothing_returned,
        // not available in our oldest supported compiler
        empty_enum,
        type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        derive_partial_eq_without_eq,
        enum_glob_use,
        explicit_auto_deref,
        let_underscore_drop,
        map_err_ignore,
        new_without_default,
        result_unit_err,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

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

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::num::Wrapping;
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
    pub use std::collections::Bound;

    #[cfg(not(no_core_reverse))]
    pub use self::core::cmp::Reverse;

    #[cfg(not(no_ops_bound))]
    pub use self::core::ops::Bound;

    #[cfg(not(no_range_inclusive))]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", not(no_std_atomic)))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", not(no_std_atomic64)))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(feature = "std", not(no_core_duration)))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Used by generated code and doc tests. Not public API.
#[doc(hidden)]
#[path = "private/mod.rs"]
pub mod __private;

#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;

#[path = "de/seed.rs"]
mod seed;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;

#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
    pub struct T;
}
<|endoftext|>


<commit_before>//! Module for generating various kinds of figurate numbers.
//!
//! This module has functions for generating normal, generalized,
//! and centered figurate numbers, as well as helper functions for
//! generating commonly used figurate numbers such
//! as triangular numbers.

/// Return the `n`th figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::figurate;
/// let a = figurate(3, 3);
/// let b = figurate(45, 91);
/// let c = figurate(17, 5);
/// assert_eq!(vec![a, b, c], vec![6, 176176, 155]);
/// ```
pub fn figurate(s: i64, n: i64) -> i64 {
    assert!(s >= 3, "cannot generate figurate numbers with less than
                         three sides!");

    ((s - 2) * n * (n - 1) / 2) + n
}

/// Return the `n`th general figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::general_figurate;
/// let a = general_figurate(5, 0);
/// let b = general_figurate(5, 1);
/// let c = general_figurate(5, 2);
/// assert_eq!(vec![a, b, c], vec![0, 1, 2]);
/// ```
pub fn general_figurate(s: i64, n: i64) -> i64 {
    let mut n = n + 1;
    if n % 2 == 1 {
        n *= -1;
    }

    figurate(s, n / 2)
}

/// Return the `n`th centered figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::centered_figurate;
/// let a = centered_figurate(3, 3);
/// let b = centered_figurate(4, 9);
/// let c = centered_figurate(8, 5);
/// assert_eq!(vec![a, b, c], vec![10, 145, 81]);
/// ```
pub fn centered_figurate(s: i64, n: i64) -> i64 {
    assert!(s >= 3, "cannot generate figurate numbers with less than
                         three sides!");

    (s * n * (n - 1) / 2) + 1
}

/// Return the `n`th triangular number
///
/// # Examples
///
/// ```
/// use reikna::figurate::triangular_number;
/// assert_eq!(triangular_number(5), 15);
/// ```
pub fn triangular_number(n: i64) -> i64 { figurate(3, n) }

/// Return the `n`th square number
///
/// # Examples
///
/// ```
/// use reikna::figurate::square_number;
/// assert_eq!(square_number(5), 25);
/// ```
pub fn square_number(n: i64) -> i64 { figurate(4, n) }

/// Return the `n`th pentagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::pentagonal_number;
/// assert_eq!(pentagonal_number(5), 35);
/// ```
pub fn pentagonal_number(n: i64) -> i64 { figurate(5, n) }

/// Return the `n`th hexagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::hexagonal_number;
/// assert_eq!(hexagonal_number(5), 45);
/// ```
pub fn hexagonal_number(n: i64) -> i64 { figurate(6, n) }

/// return the `n`th general pentagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::general_pentagonal_number;
/// assert_eq!(general_pentagonal_number(5), 12);
/// ```
pub fn general_pentagonal_number(n: i64) -> i64 { general_figurate(5, n) }

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

#[test]
#[should_panic]
    fn t_figurate_panic() {
        figurate(2, 1);
    }

#[test]
    fn t_figurate() {
        assert_eq!(figurate(3, 0), 0);
        assert_eq!(figurate(3, 1), 1);
        assert_eq!(figurate(3, 2), 3);
        assert_eq!(figurate(3, 10), 55);

        assert_eq!(figurate(4, 0), 0);
        assert_eq!(figurate(4, 1), 1);
        assert_eq!(figurate(4, 2), 4);
        assert_eq!(figurate(4, 10), 100);

        assert_eq!(figurate(5, 0), 0);
        assert_eq!(figurate(5, 1), 1);
        assert_eq!(figurate(5, 2), 5);
        assert_eq!(figurate(5, 10), 145);

        assert_eq!(figurate(9, 0), 0);
        assert_eq!(figurate(9, 1), 1);
        assert_eq!(figurate(9, 2), 9);
        assert_eq!(figurate(9, 10), 325);
    }

#[test]
    fn t_general_figurate() {
        assert_eq!(general_figurate(5, 0), 0);
        assert_eq!(general_figurate(5, 1), 1);
        assert_eq!(general_figurate(5, 2), 2);
        assert_eq!(general_figurate(5, 3), 5);
        assert_eq!(general_figurate(5, 4), 7);
        assert_eq!(general_figurate(5, 5), 12);
        assert_eq!(general_figurate(5, 6), 15);
    }

#[test]
    fn t_centered_figurate() {
        assert_eq!(centered_figurate(3, 1), 1);
        assert_eq!(centered_figurate(3, 2), 4);
        assert_eq!(centered_figurate(3, 4), 19);

        assert_eq!(centered_figurate(4, 1), 1);
        assert_eq!(centered_figurate(4, 2), 5);
        assert_eq!(centered_figurate(4, 4), 25);

        assert_eq!(centered_figurate(7, 1), 1);
        assert_eq!(centered_figurate(7, 2), 8);
        assert_eq!(centered_figurate(7, 4), 43);
    }
}
<commit_msg>fix typo<commit_after>//! Module for generating various kinds of figurate numbers.
//!
//! This module has functions for generating normal, generalized,
//! and centered figurate numbers, as well as helper functions for
//! generating commonly used figurate numbers such
//! as triangular numbers.

/// Return the `n`th figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::figurate;
/// let a = figurate(3, 3);
/// let b = figurate(45, 91);
/// let c = figurate(17, 5);
/// assert_eq!(vec![a, b, c], vec![6, 176176, 155]);
/// ```
pub fn figurate(s: i64, n: i64) -> i64 {
    assert!(s >= 3, "cannot generate figurate numbers with less than
                         three sides!");

    ((s - 2) * n * (n - 1) / 2) + n
}

/// Return the `n`th general figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::general_figurate;
/// let a = general_figurate(5, 0);
/// let b = general_figurate(5, 1);
/// let c = general_figurate(5, 2);
/// assert_eq!(vec![a, b, c], vec![0, 1, 2]);
/// ```
pub fn general_figurate(s: i64, n: i64) -> i64 {
    let mut n = n + 1;
    if n % 2 == 1 {
        n *= -1;
    }

    figurate(s, n / 2)
}

/// Return the `n`th centered figurate number with `s` sides
///
/// # Panics
///
/// Panics if `s` is less than three
///
/// # Examples
///
/// ```
/// use reikna::figurate::centered_figurate;
/// let a = centered_figurate(3, 3);
/// let b = centered_figurate(4, 9);
/// let c = centered_figurate(8, 5);
/// assert_eq!(vec![a, b, c], vec![10, 145, 81]);
/// ```
pub fn centered_figurate(s: i64, n: i64) -> i64 {
    assert!(s >= 3, "cannot generate figurate numbers with less than
                         three sides!");

    (s * n * (n - 1) / 2) + 1
}

/// Return the `n`th triangular number
///
/// # Examples
///
/// ```
/// use reikna::figurate::triangular_number;
/// assert_eq!(triangular_number(5), 15);
/// ```
pub fn triangular_number(n: i64) -> i64 { figurate(3, n) }

/// Return the `n`th square number
///
/// # Examples
///
/// ```
/// use reikna::figurate::square_number;
/// assert_eq!(square_number(5), 25);
/// ```
pub fn square_number(n: i64) -> i64 { figurate(4, n) }

/// Return the `n`th pentagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::pentagonal_number;
/// assert_eq!(pentagonal_number(5), 35);
/// ```
pub fn pentagonal_number(n: i64) -> i64 { figurate(5, n) }

/// Return the `n`th hexagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::hexagonal_number;
/// assert_eq!(hexagonal_number(5), 45);
/// ```
pub fn hexagonal_number(n: i64) -> i64 { figurate(6, n) }

/// Return the `n`th general pentagonal number
///
/// # Examples
///
/// ```
/// use reikna::figurate::general_pentagonal_number;
/// assert_eq!(general_pentagonal_number(5), 12);
/// ```
pub fn general_pentagonal_number(n: i64) -> i64 { general_figurate(5, n) }

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

#[test]
#[should_panic]
    fn t_figurate_panic() {
        figurate(2, 1);
    }

#[test]
    fn t_figurate() {
        assert_eq!(figurate(3, 0), 0);
        assert_eq!(figurate(3, 1), 1);
        assert_eq!(figurate(3, 2), 3);
        assert_eq!(figurate(3, 10), 55);

        assert_eq!(figurate(4, 0), 0);
        assert_eq!(figurate(4, 1), 1);
        assert_eq!(figurate(4, 2), 4);
        assert_eq!(figurate(4, 10), 100);

        assert_eq!(figurate(5, 0), 0);
        assert_eq!(figurate(5, 1), 1);
        assert_eq!(figurate(5, 2), 5);
        assert_eq!(figurate(5, 10), 145);

        assert_eq!(figurate(9, 0), 0);
        assert_eq!(figurate(9, 1), 1);
        assert_eq!(figurate(9, 2), 9);
        assert_eq!(figurate(9, 10), 325);
    }

#[test]
    fn t_general_figurate() {
        assert_eq!(general_figurate(5, 0), 0);
        assert_eq!(general_figurate(5, 1), 1);
        assert_eq!(general_figurate(5, 2), 2);
        assert_eq!(general_figurate(5, 3), 5);
        assert_eq!(general_figurate(5, 4), 7);
        assert_eq!(general_figurate(5, 5), 12);
        assert_eq!(general_figurate(5, 6), 15);
    }

#[test]
    fn t_centered_figurate() {
        assert_eq!(centered_figurate(3, 1), 1);
        assert_eq!(centered_figurate(3, 2), 4);
        assert_eq!(centered_figurate(3, 4), 19);

        assert_eq!(centered_figurate(4, 1), 1);
        assert_eq!(centered_figurate(4, 2), 5);
        assert_eq!(centered_figurate(4, 4), 25);

        assert_eq!(centered_figurate(7, 1), 1);
        assert_eq!(centered_figurate(7, 2), 8);
        assert_eq!(centered_figurate(7, 4), 43);
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use collections::vec::Vec;

use core::intrinsics::volatile_load;
use core::{mem, slice};

use drivers::mmio::Mmio;
use drivers::pci::config::PciConfig;

use schemes::KScheme;

use super::hci::{UsbHci, UsbMsg};
use super::setup::Setup;

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Gtd {
    flags: u32,
    buffer: u32,
    next: u32,
    end: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Ed {
    flags: u32,
    tail: u32,
    head: u32,
    next: u32,
}

const CTRL_CBSR: u32 = 0b11;
const CTRL_PLE: u32 = 1 << 2;
const CTRL_IE: u32 = 1 << 3;
const CTRL_CLE: u32 = 1 << 4;
const CTRL_BLE: u32 = 1 << 5;
const CTRL_HCFS: u32 = 0b11 << 6;
const CTRL_IR: u32 = 1 << 8;
const CTRL_RWC: u32 = 1 << 9;
const CTRL_RWE: u32 = 1 << 10;

const CMD_STS_HCR: u32 = 1;
const CMD_STS_CLF: u32 = 1 << 1;
const CMD_STS_BLF: u32 = 1 << 2;
const CMD_STS_OCR: u32 = 1 << 3;

const PORT_STS_CCS: u32 = 1;
const PORT_STS_PES: u32 = 1 << 1;
const PORT_STS_PSS: u32 = 1 << 2;
const PORT_STS_POCI: u32 = 1 << 3;
const PORT_STS_PPS: u32 = 1 << 8;
const PORT_STS_LSDA: u32 = 1 << 9;
const PORT_STS_CSC: u32 = 1 << 16;
const PORT_STS_PESC: u32 = 1 << 17;
const PORT_STS_PSSC: u32 = 1 << 18;
const PORT_STS_OCIC: u32 = 1 << 19;
const PORT_STS_PRSC: u32 = 1 << 20;

#[repr(packed)]
pub struct OhciRegs {
    pub revision: Mmio<u32>,
    pub control: Mmio<u32>,
    pub cmd_sts: Mmio<u32>,
    pub int_sts: Mmio<u32>,
    pub int_en: Mmio<u32>,
    pub int_dis: Mmio<u32>,
    pub hcca: Mmio<u32>,
    pub period_current: Mmio<u32>,
    pub control_head: Mmio<u32>,
    pub control_current: Mmio<u32>,
    pub bulk_head: Mmio<u32>,
    pub bulk_current: Mmio<u32>,
    pub done_head: Mmio<u32>,
    pub fm_interval: Mmio<u32>,
    pub fm_remain: Mmio<u32>,
    pub fm_num: Mmio<u32>,
    pub periodic_start: Mmio<u32>,
    pub ls_thresh: Mmio<u32>,
    pub rh_desc_a: Mmio<u32>,
    pub rh_desc_b: Mmio<u32>,
    pub rh_sts: Mmio<u32>,
    pub port_sts: [Mmio<u32>; 15],
}

pub struct Ohci {
    pub regs: &'static mut OhciRegs,
    pub irq: u8,
}

impl KScheme for Ohci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("OHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

impl Ohci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let base = pci.read(0x10) as usize & 0xFFFFFFF0;
        let regs = &mut *(base as *mut OhciRegs);

        let mut module = box Ohci {
            regs: regs,
            irq: pci.read(0x3C) as u8 & 0xF,
        };

        module.init();

        return module;
    }

    pub unsafe fn init(&mut self) {
        debugln!("OHCI on: {:X}, IRQ: {:X}", (self.regs as *mut OhciRegs) as usize, self.irq);

        debugln!("Reset: {:X}", self.regs.control.read());
        loop {
            let ctrl = self.regs.control.read();
            let desired_ctrl = ctrl & (0xFFFFFFFF - CTRL_HCFS);
            if ctrl != desired_ctrl {
                self.regs.control.write(desired_ctrl);
            } else {
                break;
            }
        }

        debugln!("Enable: {:X}", self.regs.control.read());
        loop {
            let ctrl = self.regs.control.read();
            let desired_ctrl = (ctrl & (0xFFFFFFFF - CTRL_HCFS)) | 0b10 << 6;
            if ctrl != desired_ctrl {
                self.regs.control.write(desired_ctrl);
            } else {
                break;
            }
        }

        debugln!("Port Enumeration: {:X}", self.regs.control.read());

        let ndp = self.regs.rh_desc_a.read() & 0xF;
        for i in 0..ndp as usize {
            debugln!("Port {}: {:X}", i, self.regs.port_sts[i].read());

            if self.regs.port_sts[i].readf(PORT_STS_CCS) {
                debugln!("Device");

                debugln!("Enable");
                while ! self.regs.port_sts[i].readf(PORT_STS_PES) {
                    self.regs.port_sts[i].writef(PORT_STS_PES, true);
                }

                self.device(i as u8);
            }
        }
    }
}

impl UsbHci for Ohci {
    fn msg(&mut self, address: u8, endpoint: u8, msgs: &[UsbMsg]) -> usize {
        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.last() {
                Some(td) => (td as *const Gtd) as u32,
                None => 0
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b00 << 19,
                    buffer: (setup as *const Setup) as u32,
                    next: link_ptr,
                    end: (setup as *const Setup) as u32 + mem::size_of::<Setup>() as u32
                }),
                UsbMsg::In(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b10 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::InIso(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b10 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::Out(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b01 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::OutIso(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b01 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                })
            }
        }

        let mut count = 0;

        if ! tds.is_empty() {
            let ed = box Ed {
                //TODO: Remove 1 << 13, it sets it to low speed
                flags: 0x3FF << 16 | 1 << 13 | (endpoint as u32) << 7 | address as u32,
                tail: 0,
                head: (tds.last().unwrap() as *const Gtd) as u32,
                next: 0
            };

            //TODO: Calculate actual bytes
            for td in tds.iter().rev() {
                count += (td.end - td.buffer) as usize;
            }

            self.regs.control_head.write((&*ed as *const Ed) as u32);
            while ! self.regs.control.readf(CTRL_CLE) {
                self.regs.control.writef(CTRL_CLE, true);
            }
            while ! self.regs.cmd_sts.readf(CMD_STS_CLF) {
                self.regs.cmd_sts.writef(CMD_STS_CLF, true);
            }

            for td in tds.iter().rev() {
                let mut spin = 1000000;
                while unsafe { volatile_load(td as *const Gtd).flags } & 0b1111 << 28 == 0b1111 << 28 && spin > 0 {
                    spin -= 1;
                    //unsafe { context_switch(false) };
                }
                let condition = (unsafe { volatile_load(td as *const Gtd).flags } & 0b1111 << 28) >> 28;
                if condition != 0 {
                    debugln!("Condition: {:X}", condition);
                    break;
                }
            }

            /*
            while self.regs.cmd_sts.readf(CMD_STS_CLF) {
                self.regs.cmd_sts.writef(CMD_STS_CLF, false);
            }
            */
            while self.regs.control.readf(CTRL_CLE) {
                self.regs.control.writef(CTRL_CLE, false);
            }
            self.regs.control_head.write(0);
        }

        count
    }
}
<commit_msg>Remove low speed flag, increase spin count<commit_after>use alloc::boxed::Box;

use collections::vec::Vec;

use core::intrinsics::volatile_load;
use core::{mem, slice};

use drivers::mmio::Mmio;
use drivers::pci::config::PciConfig;

use schemes::KScheme;

use super::hci::{UsbHci, UsbMsg};
use super::setup::Setup;

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Gtd {
    flags: u32,
    buffer: u32,
    next: u32,
    end: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Ed {
    flags: u32,
    tail: u32,
    head: u32,
    next: u32,
}

const CTRL_CBSR: u32 = 0b11;
const CTRL_PLE: u32 = 1 << 2;
const CTRL_IE: u32 = 1 << 3;
const CTRL_CLE: u32 = 1 << 4;
const CTRL_BLE: u32 = 1 << 5;
const CTRL_HCFS: u32 = 0b11 << 6;
const CTRL_IR: u32 = 1 << 8;
const CTRL_RWC: u32 = 1 << 9;
const CTRL_RWE: u32 = 1 << 10;

const CMD_STS_HCR: u32 = 1;
const CMD_STS_CLF: u32 = 1 << 1;
const CMD_STS_BLF: u32 = 1 << 2;
const CMD_STS_OCR: u32 = 1 << 3;

const PORT_STS_CCS: u32 = 1;
const PORT_STS_PES: u32 = 1 << 1;
const PORT_STS_PSS: u32 = 1 << 2;
const PORT_STS_POCI: u32 = 1 << 3;
const PORT_STS_PPS: u32 = 1 << 8;
const PORT_STS_LSDA: u32 = 1 << 9;
const PORT_STS_CSC: u32 = 1 << 16;
const PORT_STS_PESC: u32 = 1 << 17;
const PORT_STS_PSSC: u32 = 1 << 18;
const PORT_STS_OCIC: u32 = 1 << 19;
const PORT_STS_PRSC: u32 = 1 << 20;

#[repr(packed)]
pub struct OhciRegs {
    pub revision: Mmio<u32>,
    pub control: Mmio<u32>,
    pub cmd_sts: Mmio<u32>,
    pub int_sts: Mmio<u32>,
    pub int_en: Mmio<u32>,
    pub int_dis: Mmio<u32>,
    pub hcca: Mmio<u32>,
    pub period_current: Mmio<u32>,
    pub control_head: Mmio<u32>,
    pub control_current: Mmio<u32>,
    pub bulk_head: Mmio<u32>,
    pub bulk_current: Mmio<u32>,
    pub done_head: Mmio<u32>,
    pub fm_interval: Mmio<u32>,
    pub fm_remain: Mmio<u32>,
    pub fm_num: Mmio<u32>,
    pub periodic_start: Mmio<u32>,
    pub ls_thresh: Mmio<u32>,
    pub rh_desc_a: Mmio<u32>,
    pub rh_desc_b: Mmio<u32>,
    pub rh_sts: Mmio<u32>,
    pub port_sts: [Mmio<u32>; 15],
}

pub struct Ohci {
    pub regs: &'static mut OhciRegs,
    pub irq: u8,
}

impl KScheme for Ohci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("OHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

impl Ohci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let base = pci.read(0x10) as usize & 0xFFFFFFF0;
        let regs = &mut *(base as *mut OhciRegs);

        let mut module = box Ohci {
            regs: regs,
            irq: pci.read(0x3C) as u8 & 0xF,
        };

        module.init();

        return module;
    }

    pub unsafe fn init(&mut self) {
        debugln!("OHCI on: {:X}, IRQ: {:X}", (self.regs as *mut OhciRegs) as usize, self.irq);

        debugln!("Reset: {:X}", self.regs.control.read());
        loop {
            let ctrl = self.regs.control.read();
            let desired_ctrl = ctrl & (0xFFFFFFFF - CTRL_HCFS);
            if ctrl != desired_ctrl {
                self.regs.control.write(desired_ctrl);
            } else {
                break;
            }
        }

        debugln!("Enable: {:X}", self.regs.control.read());
        loop {
            let ctrl = self.regs.control.read();
            let desired_ctrl = (ctrl & (0xFFFFFFFF - CTRL_HCFS)) | 0b10 << 6;
            if ctrl != desired_ctrl {
                self.regs.control.write(desired_ctrl);
            } else {
                break;
            }
        }

        debugln!("Port Enumeration: {:X}", self.regs.control.read());

        let ndp = self.regs.rh_desc_a.read() & 0xF;
        for i in 0..ndp as usize {
            debugln!("Port {}: {:X}", i, self.regs.port_sts[i].read());

            if self.regs.port_sts[i].readf(PORT_STS_CCS) {
                debugln!("Device");

                debugln!("Enable");
                while ! self.regs.port_sts[i].readf(PORT_STS_PES) {
                    self.regs.port_sts[i].writef(PORT_STS_PES, true);
                }

                self.device(i as u8);
            }
        }
    }
}

impl UsbHci for Ohci {
    fn msg(&mut self, address: u8, endpoint: u8, msgs: &[UsbMsg]) -> usize {
        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.last() {
                Some(td) => (td as *const Gtd) as u32,
                None => 0
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b00 << 19,
                    buffer: (setup as *const Setup) as u32,
                    next: link_ptr,
                    end: (setup as *const Setup) as u32 + mem::size_of::<Setup>() as u32
                }),
                UsbMsg::In(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b10 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::InIso(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b10 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::Out(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b01 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                }),
                UsbMsg::OutIso(ref data) => tds.push(Gtd {
                    flags: 0b1111 << 28 | 0b01 << 19,
                    buffer: data.as_ptr() as u32,
                    next: link_ptr,
                    end: data.as_ptr() as u32 + data.len() as u32
                })
            }
        }

        let mut count = 0;

        if ! tds.is_empty() {
            let ed = box Ed {
                flags: 0x3FF << 16 | (endpoint as u32) << 7 | address as u32,
                tail: 0,
                head: (tds.last().unwrap() as *const Gtd) as u32,
                next: 0
            };

            //TODO: Calculate actual bytes
            for td in tds.iter().rev() {
                count += (td.end - td.buffer) as usize;
            }

            self.regs.control_head.write((&*ed as *const Ed) as u32);
            while ! self.regs.control.readf(CTRL_CLE) {
                self.regs.control.writef(CTRL_CLE, true);
            }
            while ! self.regs.cmd_sts.readf(CMD_STS_CLF) {
                self.regs.cmd_sts.writef(CMD_STS_CLF, true);
            }

            for td in tds.iter().rev() {
                let mut spin = 1000000000;
                while unsafe { volatile_load(td as *const Gtd).flags } & 0b1111 << 28 == 0b1111 << 28 && spin > 0 {
                    spin -= 1;
                    //unsafe { context_switch(false) };
                }
                let condition = (unsafe { volatile_load(td as *const Gtd).flags } & 0b1111 << 28) >> 28;
                if condition != 0 {
                    debugln!("Condition: {:X}", condition);
                    break;
                }
            }

            /*
            while self.regs.cmd_sts.readf(CMD_STS_CLF) {
                self.regs.cmd_sts.writef(CMD_STS_CLF, false);
            }
            */
            while self.regs.control.readf(CTRL_CLE) {
                self.regs.control.writef(CTRL_CLE, false);
            }
            self.regs.control_head.write(0);
        }

        count
    }
}
<|endoftext|>


<commit_before>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(ref input)) => { screen.on_input(&input, &window); }
                _ => {}
            }
        }
    }
}
<commit_msg>'Work in progress'<commit_after>use ::screen;
use ::screen::Screen;

use piston_window;

pub struct Game {
    window: piston_window::PistonWindow,
    screens: Vec<Box<screen::Screen>>,
}

impl Game {
    pub fn new() -> Game {
        let window: piston_window::PistonWindow = piston_window::WindowSettings::new("rrthozopsi", [600, 600]).exit_on_esc(true).build().unwrap();
        let screens: Vec<Box<screen::Screen>> = vec![Box::new(screen::MainMenuScreen::new())];
        Game {
            window: window,
            screens: screens,
        }
    }

    pub fn run(&mut self) {
        use piston_window::Event;

        let mut screen = self.screens.last_mut().unwrap();

        // TODO: Remove clone?
        for window in &mut self.window {
            match window.event {
                Some(Event::Update(args)) => { screen.on_update(&args); }
                Some(Event::Render(args)) => { screen.on_draw(&args, &window); }
                Some(Event::Input(ref input)) => {
            	    let result = screen.on_input(&input, &window);
            	}
                _ => {}
            }
        }
    }
}
<|endoftext|>